/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <cassert>
#include <stdlib.h>
#include <time.h>
#include <typeinfo>
#include <vcl/commandinfoprovider.hxx>
#include <vcl/help.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <vcl/decoview.hxx>
#include <vcl/toolbox.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/virdev.hxx>
#include <vcl/settings.hxx>
#include <sfx2/sfxhelp.hxx>
#include <sfx2/app.hxx>
#include <sfx2/sfxdlg.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/viewsh.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/minfitem.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/request.hxx>
#include <sfx2/filedlghelper.hxx>
#include <svl/stritem.hxx>
#include <svtools/svlbitm.hxx>
#include <svtools/treelistentry.hxx>
#include <svtools/viewdataentry.hxx>
#include <tools/diagnose_ex.h>
#include <toolkit/helper/vclunohelper.hxx>
#include <algorithm>
#include <strings.hrc>
#include <acccfg.hxx>
#include <cfg.hxx>
#include <SvxMenuConfigPage.hxx>
#include <SvxToolbarConfigPage.hxx>
#include <SvxConfigPageHelper.hxx>
#include "eventdlg.hxx"
#include <dialmgr.hxx>
#include <unotools/configmgr.hxx>
#include <o3tl/make_unique.hxx>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/FileSystemStorageFactory.hpp>
#include <com/sun/star/frame/UnknownModuleException.hpp>
#include <com/sun/star/frame/XFrames.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>
#include <com/sun/star/graphic/GraphicProvider.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/lang/IllegalAccessException.hpp>
#include <com/sun/star/ui/ItemType.hpp>
#include <com/sun/star/ui/ItemStyle.hpp>
#include <com/sun/star/ui/ImageManager.hpp>
#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfiguration.hpp>
#include <com/sun/star/ui/XUIConfigurationListener.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
#include <com/sun/star/ui/XUIConfigurationStorage.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManager.hpp>
#include <com/sun/star/ui/XUIElement.hpp>
#include <com/sun/star/ui/UIElementType.hpp>
#include <com/sun/star/ui/ImageType.hpp>
#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <com/sun/star/util/thePathSettings.hpp>
#include <comphelper/documentinfo.hxx>
#include <comphelper/propertysequence.hxx>
#include <dlgname.hxx>
#define ENTRY_HEIGHT 16
namespace uno = com::sun::star::uno;
namespace frame = com::sun::star::frame;
namespace lang = com::sun::star::lang;
namespace container = com::sun::star::container;
namespace beans = com::sun::star::beans;
namespace graphic = com::sun::star::graphic;
#if OSL_DEBUG_LEVEL > 1
void printPropertySet(
const OUString& prefix,
const uno::Reference< beans::XPropertySet >& xPropSet )
{
uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
xPropSet->getPropertySetInfo();
uno::Sequence< beans::Property > aPropDetails =
xPropSetInfo->getProperties();
SAL_WARN("cui", "printPropertySet: " << aPropDetails.getLength() << " properties" );
for ( sal_Int32 i = 0; i < aPropDetails.getLength(); ++i )
{
OUString tmp;
sal_Int32 ival;
uno::Any a = xPropSet->getPropertyValue( aPropDetails[i].Name );
if ( a >>= tmp )
{
SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << tmp);
}
else if ( ( a >>= ival ) )
{
SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << " = " << ival);
}
else
{
SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << " of type " << a.getValueTypeName());
}
}
}
void printProperties(
const OUString& prefix,
const uno::Sequence< beans::PropertyValue >& aProp )
{
for ( sal_Int32 i = 0; i < aProp.getLength(); ++i )
{
OUString tmp;
aProp[i].Value >>= tmp;
SAL_WARN("cui", prefix << ": Got property: " << aProp[i].Name << " = " << tmp);
}
}
void printEntries(SvxEntries* entries)
{
for (auto const& entry : *entries)
{
SAL_WARN("cui", "printEntries: " << entry->GetName());
}
}
#endif
bool
SvxConfigPage::CanConfig( const OUString& aModuleId )
{
return !(aModuleId == "com.sun.star.script.BasicIDE" || aModuleId == "com.sun.star.frame.Bibliography");
}
VclPtr<SfxTabPage> CreateSvxMenuConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
return VclPtr<SvxMenuConfigPage>::Create( pParent.pParent, *rSet );
}
VclPtr<SfxTabPage> CreateSvxContextMenuConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
return VclPtr<SvxMenuConfigPage>::Create( pParent.pParent, *rSet, false );
}
VclPtr<SfxTabPage> CreateKeyboardConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
return VclPtr<SfxAcceleratorConfigPage>::Create( pParent.pParent, *rSet );
}
VclPtr<SfxTabPage> CreateSvxToolbarConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
return VclPtr<SvxToolbarConfigPage>::Create( pParent.pParent, *rSet );
}
VclPtr<SfxTabPage> CreateSvxEventConfigPage( TabPageParent pParent, const SfxItemSet* rSet )
{
return VclPtr<SvxEventConfigPage>::Create( pParent.pParent, *rSet, SvxEventConfigPage::EarlyInit() );
}
/******************************************************************************
*
* SvxConfigDialog is the configuration dialog which is brought up from the
* Tools menu. It includes tabs for customizing menus, toolbars, events and
* key bindings.
*
*****************************************************************************/
SvxConfigDialog::SvxConfigDialog(vcl::Window * pParent, const SfxItemSet* pInSet)
: SfxTabDialog(pParent, "CustomizeDialog",
"cui/ui/customizedialog.ui", pInSet)
, m_nMenusPageId(0)
, m_nToolbarsPageId(0)
, m_nContextMenusPageId(0)
, m_nKeyboardPageId(0)
, m_nEventsPageId(0)
{
SvxConfigPageHelper::InitImageType();
m_nMenusPageId = AddTabPage("menus", CreateSvxMenuConfigPage, nullptr);
m_nToolbarsPageId = AddTabPage("toolbars", CreateSvxToolbarConfigPage, nullptr);
m_nContextMenusPageId = AddTabPage("contextmenus", CreateSvxContextMenuConfigPage, nullptr);
m_nKeyboardPageId = AddTabPage("keyboard", CreateKeyboardConfigPage, nullptr);
m_nEventsPageId = AddTabPage("events", CreateSvxEventConfigPage, nullptr);
const SfxPoolItem* pItem =
pInSet->GetItem( pInSet->GetPool()->GetWhich( SID_CONFIG ) );
if ( pItem )
{
OUString text = static_cast<const SfxStringItem*>(pItem)->GetValue();
if (text.startsWith( ITEM_TOOLBAR_URL ) )
{
SetCurPageId(m_nToolbarsPageId);
}
}
}
void SvxConfigDialog::SetFrame(const css::uno::Reference< css::frame::XFrame >& xFrame)
{
m_xFrame = xFrame;
if (!SvxConfigPageHelper::showKeyConfigTabPage( xFrame ))
RemoveTabPage(m_nKeyboardPageId);
}
void SvxConfigDialog::PageCreated( sal_uInt16 nId, SfxTabPage& rPage )
{
if (nId == m_nMenusPageId || nId == m_nKeyboardPageId ||
nId == m_nToolbarsPageId || nId == m_nContextMenusPageId)
{
rPage.SetFrame(m_xFrame);
}
else if (nId == m_nEventsPageId)
{
dynamic_cast< SvxEventConfigPage& >( rPage ).LateInit( m_xFrame );
}
}
/******************************************************************************
*
* The SaveInData class is used to hold data for entries in the Save In
* ListBox controls in the menu and toolbar tabs
*
******************************************************************************/
// Initialize static variable which holds default XImageManager
uno::Reference< css::ui::XImageManager>* SaveInData::xDefaultImgMgr = nullptr;
SaveInData::SaveInData(
const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
const OUString& aModuleId,
bool isDocConfig )
:
bModified( false ),
bDocConfig( isDocConfig ),
bReadOnly( false ),
m_xCfgMgr( xCfgMgr ),
m_xParentCfgMgr( xParentCfgMgr )
{
m_aSeparatorSeq.realloc( 1 );
m_aSeparatorSeq[0].Name = ITEM_DESCRIPTOR_TYPE;
m_aSeparatorSeq[0].Value <<= css::ui::ItemType::SEPARATOR_LINE;
if ( bDocConfig )
{
uno::Reference< css::ui::XUIConfigurationPersistence >
xDocPersistence( GetConfigManager(), uno::UNO_QUERY );
bReadOnly = xDocPersistence->isReadOnly();
}
uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
uno::Reference< container::XNameAccess > xNameAccess(
css::frame::theUICommandDescription::get(xContext) );
xNameAccess->getByName( aModuleId ) >>= m_xCommandToLabelMap;
if ( !m_xImgMgr.is() )
{
m_xImgMgr.set( GetConfigManager()->getImageManager(), uno::UNO_QUERY );
}
if ( !IsDocConfig() )
{
// If this is not a document configuration then it is the settings
// for the module (writer, calc, impress etc.) Use this as the default
// XImageManager instance
xDefaultImgMgr = &m_xImgMgr;
}
else
{
// If this is a document configuration then use the module image manager
// as default.
if ( m_xParentCfgMgr.is() )
{
m_xParentImgMgr.set( m_xParentCfgMgr->getImageManager(), uno::UNO_QUERY );
xDefaultImgMgr = &m_xParentImgMgr;
}
}
}
Image SaveInData::GetImage( const OUString& rCommandURL )
{
Image aImage;
uno::Reference< graphic::XGraphic > xGraphic =
SvxConfigPageHelper::GetGraphic( m_xImgMgr, rCommandURL );
if ( xGraphic.is() )
{
aImage = Image( xGraphic );
}
else if ( xDefaultImgMgr != nullptr && (*xDefaultImgMgr).is() )
{
xGraphic = SvxConfigPageHelper::GetGraphic( (*xDefaultImgMgr), rCommandURL );
if ( xGraphic.is() )
{
aImage = Image( xGraphic );
}
}
return aImage;
}
bool SaveInData::PersistChanges(
const uno::Reference< uno::XInterface >& xManager )
{
bool result = true;
try
{
if ( xManager.is() && !IsReadOnly() )
{
uno::Reference< css::ui::XUIConfigurationPersistence >
xConfigPersistence( xManager, uno::UNO_QUERY );
if ( xConfigPersistence->isModified() )
{
xConfigPersistence->store();
}
}
}
catch ( css::io::IOException& )
{
result = false;
}
return result;
}
/******************************************************************************
*
* The MenuSaveInData class extends SaveInData and provides menu specific
* load and store functionality.
*
******************************************************************************/
// Initialize static variable which holds default Menu data
MenuSaveInData* MenuSaveInData::pDefaultData = nullptr;
MenuSaveInData::MenuSaveInData(
const uno::Reference< css::ui::XUIConfigurationManager >& cfgmgr,
const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
const OUString& aModuleId,
bool isDocConfig )
:
SaveInData( cfgmgr, xParentCfgMgr, aModuleId, isDocConfig ),
m_aMenuResourceURL(
ITEM_MENUBAR_URL ),
m_aDescriptorContainer(
ITEM_DESCRIPTOR_CONTAINER )
{
try
{
OUString url( ITEM_MENUBAR_URL );
m_xMenuSettings = GetConfigManager()->getSettings( url, false );
}
catch ( container::NoSuchElementException& )
{
// will use menu settings for the module
}
// If this is not a document configuration then it is the settings
// for the module (writer, calc, impress etc.). These settings should
// be set as the default to be used for SaveIn locations that do not
// have custom settings
if ( !IsDocConfig() )
{
SetDefaultData( this );
}
}
MenuSaveInData::~MenuSaveInData()
{
}
SvxEntries*
MenuSaveInData::GetEntries()
{
if ( pRootEntry == nullptr )
{
pRootEntry.reset( new SvxConfigEntry( "MainMenus", OUString(), true, /*bParentData*/false) );
if ( m_xMenuSettings.is() )
{
LoadSubMenus( m_xMenuSettings, OUString(), pRootEntry.get(), false );
}
else if ( GetDefaultData() != nullptr )
{
// If the doc has no config settings use module config settings
LoadSubMenus( GetDefaultData()->m_xMenuSettings, OUString(), pRootEntry.get(), false );
}
}
return pRootEntry->GetEntries();
}
void
MenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
{
pRootEntry->SetEntries( std::move(pNewEntries) );
}
void SaveInData::LoadSubMenus( const uno::Reference< container::XIndexAccess >& xMenuSettings,
const OUString& rBaseTitle, SvxConfigEntry const * pParentData, bool bContextMenu )
{
SvxEntries* pEntries = pParentData->GetEntries();
// Don't access non existing menu configuration!
if ( !xMenuSettings.is() )
return;
for ( sal_Int32 nIndex = 0; nIndex < xMenuSettings->getCount(); ++nIndex )
{
uno::Reference< container::XIndexAccess > xSubMenu;
OUString aCommandURL;
OUString aLabel;
sal_uInt16 nType( css::ui::ItemType::DEFAULT );
sal_Int32 nStyle(0);
bool bItem = SvxConfigPageHelper::GetMenuItemData( xMenuSettings, nIndex,
aCommandURL, aLabel, nType, nStyle, xSubMenu );
if ( bItem )
{
bool bIsUserDefined = true;
if ( nType == css::ui::ItemType::DEFAULT )
{
uno::Any a;
try
{
a = m_xCommandToLabelMap->getByName( aCommandURL );
bIsUserDefined = false;
}
catch ( container::NoSuchElementException& )
{
bIsUserDefined = true;
}
bool bUseDefaultLabel = false;
// If custom label not set retrieve it from the command
// to info service
if ( aLabel.isEmpty() )
{
bUseDefaultLabel = true;
uno::Sequence< beans::PropertyValue > aPropSeq;
if ( a >>= aPropSeq )
{
OUString aMenuLabel;
for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
{
if ( bContextMenu )
{
if ( aPropSeq[i].Name == "PopupLabel" )
{
aPropSeq[i].Value >>= aLabel;
break;
}
else if ( aPropSeq[i].Name == "Label" )
{
aPropSeq[i].Value >>= aMenuLabel;
}
}
else if ( aPropSeq[i].Name == "Label" )
{
aPropSeq[i].Value >>= aLabel;
break;
}
}
if ( aLabel.isEmpty() )
aLabel = aMenuLabel;
}
}
SvxConfigEntry* pEntry = new SvxConfigEntry(
aLabel, aCommandURL, xSubMenu.is(), /*bParentData*/false );
pEntry->SetStyle( nStyle );
pEntry->SetUserDefined( bIsUserDefined );
if ( !bUseDefaultLabel )
pEntry->SetName( aLabel );
pEntries->push_back( pEntry );
if ( xSubMenu.is() )
{
// popup menu
OUString subMenuTitle( rBaseTitle );
if ( !subMenuTitle.isEmpty() )
{
subMenuTitle += aMenuSeparatorStr;
}
else
{
pEntry->SetMain();
}
subMenuTitle += SvxConfigPageHelper::stripHotKey( aLabel );
LoadSubMenus( xSubMenu, subMenuTitle, pEntry, bContextMenu );
}
}
else
{
SvxConfigEntry* pEntry = new SvxConfigEntry;
pEntry->SetUserDefined( bIsUserDefined );
pEntries->push_back( pEntry );
}
}
}
}
bool MenuSaveInData::Apply()
{
bool result = false;
if ( IsModified() )
{
// Apply new menu bar structure to our settings container
m_xMenuSettings.set( GetConfigManager()->createSettings(), uno::UNO_QUERY );
uno::Reference< container::XIndexContainer > xIndexContainer (
m_xMenuSettings, uno::UNO_QUERY );
uno::Reference< lang::XSingleComponentFactory > xFactory (
m_xMenuSettings, uno::UNO_QUERY );
Apply( xIndexContainer, xFactory );
try
{
if ( GetConfigManager()->hasSettings( m_aMenuResourceURL ) )
{
GetConfigManager()->replaceSettings(
m_aMenuResourceURL, m_xMenuSettings );
}
else
{
GetConfigManager()->insertSettings(
m_aMenuResourceURL, m_xMenuSettings );
}
}
catch ( container::NoSuchElementException& )
{
SAL_WARN("cui.customize", "caught container::NoSuchElementException saving settings");
}
catch ( css::io::IOException& )
{
SAL_WARN("cui.customize", "caught IOException saving settings");
}
catch ( css::uno::Exception& )
{
SAL_WARN("cui.customize", "caught some other exception saving settings");
}
SetModified( false );
result = PersistChanges( GetConfigManager() );
}
return result;
}
void MenuSaveInData::Apply(
uno::Reference< container::XIndexContainer > const & rMenuBar,
uno::Reference< lang::XSingleComponentFactory >& rFactory )
{
uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
for (auto const& entryData : *GetEntries())
{
uno::Sequence< beans::PropertyValue > aPropValueSeq =
SvxConfigPageHelper::ConvertSvxConfigEntry(entryData);
uno::Reference< container::XIndexContainer > xSubMenuBar(
rFactory->createInstanceWithContext( xContext ),
uno::UNO_QUERY );
sal_Int32 nIndex = aPropValueSeq.getLength();
aPropValueSeq.realloc( nIndex + 1 );
aPropValueSeq[nIndex].Name = m_aDescriptorContainer;
aPropValueSeq[nIndex].Value <<= xSubMenuBar;
rMenuBar->insertByIndex(
rMenuBar->getCount(), uno::Any( aPropValueSeq ));
ApplyMenu( xSubMenuBar, rFactory, entryData );
}
}
void SaveInData::ApplyMenu(
uno::Reference< container::XIndexContainer > const & rMenuBar,
uno::Reference< lang::XSingleComponentFactory >& rFactory,
SvxConfigEntry* pMenuData )
{
uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
for (auto const& entry : *pMenuData->GetEntries())
{
if (entry->IsPopup())
{
uno::Sequence< beans::PropertyValue > aPropValueSeq =
SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
uno::Reference< container::XIndexContainer > xSubMenuBar(
rFactory->createInstanceWithContext( xContext ),
uno::UNO_QUERY );
sal_Int32 nIndex = aPropValueSeq.getLength();
aPropValueSeq.realloc( nIndex + 1 );
aPropValueSeq[nIndex].Name = ITEM_DESCRIPTOR_CONTAINER;
aPropValueSeq[nIndex].Value <<= xSubMenuBar;
rMenuBar->insertByIndex(
rMenuBar->getCount(), uno::Any( aPropValueSeq ));
ApplyMenu( xSubMenuBar, rFactory, entry );
entry->SetModified( false );
}
else if (entry->IsSeparator())
{
rMenuBar->insertByIndex(
rMenuBar->getCount(), uno::Any( m_aSeparatorSeq ));
}
else
{
uno::Sequence< beans::PropertyValue > aPropValueSeq =
SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
rMenuBar->insertByIndex(
rMenuBar->getCount(), uno::Any( aPropValueSeq ));
}
}
pMenuData->SetModified( false );
}
void
MenuSaveInData::Reset()
{
try
{
GetConfigManager()->removeSettings( m_aMenuResourceURL );
}
catch ( const css::uno::Exception& )
{}
PersistChanges( GetConfigManager() );
pRootEntry.reset();
try
{
m_xMenuSettings = GetConfigManager()->getSettings(
m_aMenuResourceURL, false );
}
catch ( container::NoSuchElementException& )
{
// will use default settings
}
}
ContextMenuSaveInData::ContextMenuSaveInData(
const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
const OUString& aModuleId, bool bIsDocConfig )
: SaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bIsDocConfig )
{
css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
css::uno::Reference< css::container::XNameAccess > xConfig( css::ui::theWindowStateConfiguration::get( xContext ) );
xConfig->getByName( aModuleId ) >>= m_xPersistentWindowState;
}
ContextMenuSaveInData::~ContextMenuSaveInData()
{
}
OUString ContextMenuSaveInData::GetUIName( const OUString& rResourceURL )
{
if ( m_xPersistentWindowState.is() )
{
css::uno::Sequence< css::beans::PropertyValue > aProps;
try
{
m_xPersistentWindowState->getByName( rResourceURL ) >>= aProps;
}
catch ( const css::uno::Exception& )
{}
for ( const auto& aProp : aProps )
{
if ( aProp.Name == ITEM_DESCRIPTOR_UINAME )
{
OUString aResult;
aProp.Value >>= aResult;
return aResult;
}
}
}
return OUString();
}
SvxEntries* ContextMenuSaveInData::GetEntries()
{
if ( !m_pRootEntry )
{
std::unordered_map< OUString, bool > aMenuInfo;
m_pRootEntry.reset( new SvxConfigEntry( "ContextMenus", OUString(), true, /*bParentData*/false ) );
css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aElementsInfo;
try
{
aElementsInfo = GetConfigManager()->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
}
catch ( const css::lang::IllegalArgumentException& )
{}
for ( const auto& aElement : aElementsInfo )
{
OUString aUrl;
for ( const auto& aElementProp : aElement )
{
if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
{
aElementProp.Value >>= aUrl;
break;
}
}
css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
try
{
xPopupMenu = GetConfigManager()->getSettings( aUrl, false );
}
catch ( const css::uno::Exception& )
{}
if ( xPopupMenu.is() )
{
// insert into std::unordered_map to filter duplicates from the parent
aMenuInfo.emplace( aUrl, true );
OUString aUIMenuName = GetUIName( aUrl );
if ( aUIMenuName.isEmpty() )
// Menus without UI name aren't supposed to be customized.
continue;
SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, /*bParentData*/false );
pEntry->SetMain();
m_pRootEntry->GetEntries()->push_back( pEntry );
LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
}
}
// Retrieve also the parent menus, to make it possible to configure module menus and save them into the document.
css::uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aParentElementsInfo;
try
{
if ( xParentCfgMgr.is() )
aParentElementsInfo = xParentCfgMgr->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
}
catch ( const css::lang::IllegalArgumentException& )
{}
for ( const auto& aElement : aParentElementsInfo )
{
OUString aUrl;
for ( const auto& aElementProp : aElement )
{
if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
{
aElementProp.Value >>= aUrl;
break;
}
}
css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
try
{
if ( aMenuInfo.find( aUrl ) == aMenuInfo.end() )
xPopupMenu = xParentCfgMgr->getSettings( aUrl, false );
}
catch ( const css::uno::Exception& )
{}
if ( xPopupMenu.is() )
{
OUString aUIMenuName = GetUIName( aUrl );
if ( aUIMenuName.isEmpty() )
continue;
SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, true );
pEntry->SetMain();
m_pRootEntry->GetEntries()->push_back( pEntry );
LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
}
}
std::sort( m_pRootEntry->GetEntries()->begin(), m_pRootEntry->GetEntries()->end(), SvxConfigPageHelper::EntrySort );
}
return m_pRootEntry->GetEntries();
}
void ContextMenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
{
m_pRootEntry->SetEntries( std::move(pNewEntries) );
}
bool ContextMenuSaveInData::HasURL( const OUString& rURL )
{
SvxEntries* pEntries = GetEntries();
for ( const auto& pEntry : *pEntries )
if ( pEntry->GetCommand() == rURL )
return true;
return false;
}
bool ContextMenuSaveInData::HasSettings()
{
return m_pRootEntry && m_pRootEntry->GetEntries()->size();
}
bool ContextMenuSaveInData::Apply()
{
if ( !IsModified() )
return false;
SvxEntries* pEntries = GetEntries();
for ( const auto& pEntry : *pEntries )
{
if ( pEntry->IsModified() || SvxConfigPageHelper::SvxConfigEntryModified( pEntry ) )
{
css::uno::Reference< css::container::XIndexContainer > xIndexContainer( GetConfigManager()->createSettings(), css::uno::UNO_QUERY );
css::uno::Reference< css::lang::XSingleComponentFactory > xFactory( xIndexContainer, css::uno::UNO_QUERY );
ApplyMenu( xIndexContainer, xFactory, pEntry );
const OUString& aUrl = pEntry->GetCommand();
try
{
if ( GetConfigManager()->hasSettings( aUrl ) )
GetConfigManager()->replaceSettings( aUrl, xIndexContainer );
else
GetConfigManager()->insertSettings( aUrl, xIndexContainer );
}
catch ( const css::uno::Exception& )
{}
}
}
SetModified( false );
return PersistChanges( GetConfigManager() );
}
void ContextMenuSaveInData::Reset()
{
SvxEntries* pEntries = GetEntries();
for ( const auto& pEntry : *pEntries )
{
try
{
GetConfigManager()->removeSettings( pEntry->GetCommand() );
}
catch ( const css::uno::Exception& e )
{
SAL_WARN("cui.customize", "Exception caught while resetting context menus: " << e);
}
}
PersistChanges( GetConfigManager() );
m_pRootEntry.reset();
}
void ContextMenuSaveInData::ResetContextMenu( const SvxConfigEntry* pEntry )
{
try
{
GetConfigManager()->removeSettings( pEntry->GetCommand() );
}
catch ( const css::uno::Exception& e )
{
SAL_WARN("cui.customize", "Exception caught while resetting context menu: " << e);
}
PersistChanges( GetConfigManager() );
m_pRootEntry.reset();
}
class PopupPainter : public SvLBoxString
{
public:
explicit PopupPainter(const OUString& rStr)
: SvLBoxString(rStr)
{
}
virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext,
const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override
{
SvLBoxString::Paint(rPos, rOutDev, rRenderContext, pView, rEntry);
rRenderContext.Push(PushFlags::FILLCOLOR);
long nX = rOutDev.GetSizePixel().Width();
ScrollBar* pVScroll = rOutDev.GetVScroll();
if (pVScroll->IsVisible())
{
nX -= pVScroll->GetSizePixel().Width();
}
const SvViewDataItem* pItem = rOutDev.GetViewDataItem( &rEntry, this );
nX -= pItem->maSize.Height();
long nSize = pItem->maSize.Height() / 2;
long nHalfSize = nSize / 2;
long nY = rPos.Y() + nHalfSize;
if (rRenderContext.GetFillColor() == COL_WHITE)
{
rRenderContext.SetFillColor(COL_BLACK);
}
else
{
rRenderContext.SetFillColor(COL_WHITE);
}
long n = 0;
while (n <= nHalfSize)
{
rRenderContext.DrawRect(::tools::Rectangle(nX + n, nY + n, nX + n, nY + nSize - n));
++n;
}
rRenderContext.Pop();
}
};
/******************************************************************************
*
* SvxMenuEntriesListBox is the listbox in which the menu items for a
* particular menu are shown. We have a custom listbox because we need
* to add drag'n'drop support from the Macro Selector and within the
* listbox
*
*****************************************************************************/
SvxMenuEntriesListBox::SvxMenuEntriesListBox(vcl::Window* pParent, SvxConfigPage* pPg)
: SvTreeListBox(pParent, WB_TABSTOP|WB_CLIPCHILDREN|WB_HIDESELECTION|WB_BORDER)
, pPage(pPg)
, m_bIsInternalDrag( false )
{
SetSpaceBetweenEntries( 3 );
SetEntryHeight( ENTRY_HEIGHT );
SetHighlightRange();
SetSelectionMode(SelectionMode::Single);
SetDragDropMode( DragDropMode::CTRL_MOVE |
DragDropMode::APP_COPY |
DragDropMode::ENABLE_TOP |
DragDropMode::APP_DROP);
}
SvxMenuEntriesListBox::~SvxMenuEntriesListBox()
{
disposeOnce();
}
void SvxMenuEntriesListBox::dispose()
{
pPage.clear();
SvTreeListBox::dispose();
}
// drag and drop support
DragDropMode SvxMenuEntriesListBox::NotifyStartDrag(
TransferDataContainer&, SvTreeListEntry* )
{
m_bIsInternalDrag = true;
return GetDragDropMode();
}
void SvxMenuEntriesListBox::DragFinished( sal_Int8 )
{
m_bIsInternalDrag = false;
}
sal_Int8 SvxMenuEntriesListBox::AcceptDrop( const AcceptDropEvent& rEvt )
{
if ( m_bIsInternalDrag )
{
// internal copy isn't allowed!
if ( rEvt.mnAction == DND_ACTION_COPY )
return DND_ACTION_NONE;
else
return SvTreeListBox::AcceptDrop( rEvt );
}
// Always do COPY instead of MOVE if D&D comes from outside!
AcceptDropEvent aNewAcceptDropEvent( rEvt );
aNewAcceptDropEvent.mnAction = DND_ACTION_COPY;
return SvTreeListBox::AcceptDrop( aNewAcceptDropEvent );
}
bool SvxMenuEntriesListBox::NotifyAcceptDrop( SvTreeListEntry* )
{
return true;
}
TriState SvxMenuEntriesListBox::NotifyMoving(
SvTreeListEntry* pTarget, SvTreeListEntry* pSource,
SvTreeListEntry*& rpNewParent, sal_uLong& rNewChildPos)
{
// only try to do a move if we are dragging within the list box
if ( m_bIsInternalDrag )
{
if ( pPage->MoveEntryData( pSource, pTarget ) )
{
SvTreeListBox::NotifyMoving(
pTarget, pSource, rpNewParent, rNewChildPos );
return TRISTATE_TRUE;
}
else
{
return TRISTATE_FALSE;
}
}
else
{
return NotifyCopying( pTarget, pSource, rpNewParent, rNewChildPos );
}
}
TriState SvxMenuEntriesListBox::NotifyCopying(
SvTreeListEntry* pTarget, SvTreeListEntry*,
SvTreeListEntry*&, sal_uLong&)
{
if ( !m_bIsInternalDrag )
{
// if the target is NULL then add function to the start of the list
pPage->AddFunction( pTarget, pTarget == nullptr );
// AddFunction already adds the listbox entry so return TRISTATE_FALSE
// to stop another listbox entry being added
return TRISTATE_FALSE;
}
// Copying is only allowed from external controls, not within the listbox
return TRISTATE_FALSE;
}
void SvxMenuEntriesListBox::KeyInput( const KeyEvent& rKeyEvent )
{
vcl::KeyCode keycode = rKeyEvent.GetKeyCode();
// support DELETE for removing the current entry
if ( keycode == KEY_DELETE )
{
pPage->DeleteSelectedContent();
}
// support CTRL+UP and CTRL+DOWN for moving selected entries
else if ( keycode.GetCode() == KEY_UP && keycode.IsMod1() )
{
pPage->MoveEntry( true );
}
else if ( keycode.GetCode() == KEY_DOWN && keycode.IsMod1() )
{
pPage->MoveEntry( false );
}
else
{
// pass on to superclass
SvTreeListBox::KeyInput( rKeyEvent );
}
}
/******************************************************************************
*
* SvxConfigPage is the abstract base class on which the Menu and Toolbar
* configuration tabpages are based. It includes methods which are common to
* both tabpages to add, delete, move and rename items etc.
*
*****************************************************************************/
SvxConfigPage::SvxConfigPage(vcl::Window *pParent, const SfxItemSet& rSet)
: SfxTabPage(pParent, "MenuAssignPage", "cui/ui/menuassignpage.ui", &rSet)
, bInitialised(false)
, pCurrentSaveInData(nullptr)
, m_pContentsListBox(nullptr)
{
get(m_pSearchEdit, "searchEntry");
get(m_pCommandCategoryListBox, "commandcategorylist");
get(m_pFunctions, "functions");
get(m_pAddCommandButton, "add");
get(m_pRemoveCommandButton, "remove");
get(m_pTopLevelListBox, "toplevellist");
get(m_pGearBtn, "gearbtn");
get(m_pMoveUpButton, "up");
get(m_pMoveDownButton, "down");
get(m_pSaveInListBox, "savein");
get(m_pInsertBtn, "insert");
get(m_pModifyBtn, "modify");
get(m_pResetBtn, "defaultsbtn");
get(m_pDescriptionFieldLb, "descriptionlabel");
get(m_pDescriptionField, "desc");
m_pDescriptionField->set_height_request(m_pDescriptionField->GetTextHeight()*2.9);
get(m_pEntries, "entries");
Size aSize(LogicToPixel(Size(108, 115), MapMode(MapUnit::MapAppFont)));
m_pEntries->set_height_request(aSize.Height());
m_pEntries->set_width_request(aSize.Width());
m_pFunctions->set_height_request(aSize.Height());
//TODO: Add SvxMenuEntriesListBox into the glade catalog, and use it on the
// .ui file to get rid of the extra VCLContainer, and all these manual
// sizing and widget creation tricks.
m_pFunctions->set_width_request(aSize.Width() * 1.45);
m_pFunctions->SetNodeDefaultImages();
m_pFunctions->SetStyle( m_pFunctions->GetStyle() | WB_HASBUTTONS | WB_HASBUTTONSATROOT |
WB_HASLINES | WB_HASLINESATROOT | WB_CLIPCHILDREN | WB_HSCROLL );
// Make the middle buttons bigger
m_pAddCommandButton->set_height_request( m_pAddCommandButton->GetOptimalSize().Height() * 1.5 );
m_pAddCommandButton->set_width_request( m_pAddCommandButton->GetOptimalSize().Width() * 1.5 );
m_pRemoveCommandButton->set_height_request( m_pRemoveCommandButton->GetOptimalSize().Height() * 1.5 );
m_pRemoveCommandButton->set_width_request( m_pRemoveCommandButton->GetOptimalSize().Width() * 1.5 );
m_pDescriptionField->SetControlBackground( GetSettings().GetStyleSettings().GetDialogColor() );
m_pDescriptionField->EnableCursor( false );
m_pDescriptionField->SetStyle( m_pDescriptionField->GetStyle() | WB_TABSTOP ); // Include in the tab sequence
m_pSearchEdit->SetUpdateDataHdl ( LINK( this, SvxConfigPage, SearchUpdateHdl ));
m_pSearchEdit->EnableUpdateData();
m_pFunctions->SetDoubleClickHdl( LINK( this, SvxConfigPage, FunctionDoubleClickHdl ) );
m_pFunctions->SetSelectHdl(
LINK( this, SvxConfigPage, SelectFunctionHdl ) );
m_pGearBtn->SetDropDown(PushButtonDropdownStyle::NONE);
}
SvxConfigPage::~SvxConfigPage()
{
disposeOnce();
}
void SvxConfigPage::dispose()
{
m_pTopLevelListBox.clear();
m_pGearBtn.clear();
m_pSearchEdit.clear();
m_pCommandCategoryListBox.clear();
m_pEntries.clear();
m_pFunctions.clear();
m_pAddCommandButton.clear();
m_pRemoveCommandButton.clear();
m_pMoveUpButton.clear();
m_pMoveDownButton.clear();
m_pSaveInListBox.clear();
m_pInsertBtn.clear();
m_pModifyBtn.clear();
m_pResetBtn.clear();
m_pDescriptionFieldLb.clear();
m_pDescriptionField.clear();
m_pContentsListBox.disposeAndClear();
SfxTabPage::dispose();
}
void SvxConfigPage::Reset( const SfxItemSet* )
{
// If we haven't initialised our XMultiServiceFactory reference
// then Reset is being called at the opening of the dialog.
// Load menu configuration data for the module of the currently
// selected document, for the currently selected document, and for
// all other open documents of the same module type
if ( !bInitialised )
{
sal_Int32 nPos = 0;
uno::Reference < css::ui::XUIConfigurationManager > xCfgMgr;
uno::Reference < css::ui::XUIConfigurationManager > xDocCfgMgr;
uno::Reference< uno::XComponentContext > xContext(
::comphelper::getProcessComponentContext(), uno::UNO_QUERY_THROW );
m_xFrame = GetFrame();
OUString aModuleId = GetFrameWithDefaultAndIdentify( m_xFrame );
// replace %MODULENAME in the label with the correct module name
uno::Reference< css::frame::XModuleManager2 > xModuleManager(
css::frame::ModuleManager::create( xContext ));
OUString aModuleName = SvxConfigPageHelper::GetUIModuleName( aModuleId, xModuleManager );
uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier >
xModuleCfgSupplier( css::ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
// Set up data for module specific menus
SaveInData* pModuleData = nullptr;
try
{
xCfgMgr =
xModuleCfgSupplier->getUIConfigurationManager( aModuleId );
pModuleData = CreateSaveInData( xCfgMgr,
uno::Reference< css::ui::XUIConfigurationManager >(),
aModuleId,
false );
}
catch ( container::NoSuchElementException& )
{
}
if ( pModuleData != nullptr )
{
nPos = m_pSaveInListBox->InsertEntry(
utl::ConfigManager::getProductName() + " " + aModuleName );
m_pSaveInListBox->SetEntryData( nPos, pModuleData );
}
// try to retrieve the document based ui configuration manager
OUString aTitle;
uno::Reference< frame::XController > xController =
m_xFrame->getController();
if ( CanConfig( aModuleId ) && xController.is() )
{
uno::Reference< frame::XModel > xModel( xController->getModel() );
if ( xModel.is() )
{
uno::Reference< css::ui::XUIConfigurationManagerSupplier >
xCfgSupplier( xModel, uno::UNO_QUERY );
if ( xCfgSupplier.is() )
{
xDocCfgMgr = xCfgSupplier->getUIConfigurationManager();
}
aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
}
}
SaveInData* pDocData = nullptr;
if ( xDocCfgMgr.is() )
{
pDocData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, true );
if ( !pDocData->IsReadOnly() )
{
nPos = m_pSaveInListBox->InsertEntry( aTitle );
m_pSaveInListBox->SetEntryData( nPos, pDocData );
}
}
// if an item to select has been passed in (eg. the ResourceURL for a
// toolbar) then try to select the SaveInData entry that has that item
bool bURLToSelectFound = false;
if ( !m_aURLToSelect.isEmpty() )
{
if ( pDocData && pDocData->HasURL( m_aURLToSelect ) )
{
m_pSaveInListBox->SelectEntryPos( nPos );
pCurrentSaveInData = pDocData;
bURLToSelectFound = true;
}
else if ( pModuleData && pModuleData->HasURL( m_aURLToSelect ) )
{
m_pSaveInListBox->SelectEntryPos( 0 );
pCurrentSaveInData = pModuleData;
bURLToSelectFound = true;
}
}
if ( !bURLToSelectFound )
{
// if the document has menu configuration settings select it
// it the SaveIn listbox, otherwise select the module data
if ( pDocData != nullptr && pDocData->HasSettings() )
{
m_pSaveInListBox->SelectEntryPos( nPos );
pCurrentSaveInData = pDocData;
}
else
{
m_pSaveInListBox->SelectEntryPos( 0 );
pCurrentSaveInData = pModuleData;
}
}
#ifdef DBG_UTIL
DBG_ASSERT( pCurrentSaveInData, "SvxConfigPage::Reset(): no SaveInData" );
#endif
if ( CanConfig( aModuleId ) )
{
// Load configuration for other open documents which have
// same module type
uno::Sequence< uno::Reference< frame::XFrame > > aFrameList;
try
{
uno::Reference< frame::XDesktop2 > xFramesSupplier = frame::Desktop::create(
xContext );
uno::Reference< frame::XFrames > xFrames =
xFramesSupplier->getFrames();
aFrameList = xFrames->queryFrames(
frame::FrameSearchFlag::ALL & ~frame::FrameSearchFlag::SELF );
}
catch( const uno::Exception& )
{
DBG_UNHANDLED_EXCEPTION("cui.customize");
}
for ( sal_Int32 i = 0; i < aFrameList.getLength(); ++i )
{
uno::Reference < frame::XFrame > xf = aFrameList[i];
if ( xf.is() && xf != m_xFrame )
{
OUString aCheckId;
try{
aCheckId = xModuleManager->identify( xf );
} catch(const uno::Exception&)
{ aCheckId.clear(); }
if ( aModuleId == aCheckId )
{
// try to get the document based ui configuration manager
OUString aTitle2;
uno::Reference< frame::XController > xController_ =
xf->getController();
if ( xController_.is() )
{
uno::Reference< frame::XModel > xModel(
xController_->getModel() );
if ( xModel.is() )
{
uno::Reference<
css::ui::XUIConfigurationManagerSupplier >
xCfgSupplier( xModel, uno::UNO_QUERY );
if ( xCfgSupplier.is() )
{
xDocCfgMgr =
xCfgSupplier->getUIConfigurationManager();
}
aTitle2 = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
}
}
if ( xDocCfgMgr.is() )
{
SaveInData* pData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, true );
if ( pData && !pData->IsReadOnly() )
{
nPos = m_pSaveInListBox->InsertEntry( aTitle2 );
m_pSaveInListBox->SetEntryData( nPos, pData );
}
}
}
}
}
}
m_pSaveInListBox->SetSelectHdl(
LINK( this, SvxConfigPage, SelectSaveInLocation ) );
bInitialised = true;
Init();
}
else
{
if ( QueryReset() == RET_YES )
{
// Reset menu configuration for currently selected SaveInData
GetSaveInData()->Reset();
Init();
}
}
}
OUString SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference< frame::XFrame >& _inout_rxFrame )
{
OUString sModuleID;
try
{
uno::Reference< uno::XComponentContext > xContext(
::comphelper::getProcessComponentContext() );
uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(
xContext );
if ( !_inout_rxFrame.is() )
_inout_rxFrame = xDesktop->getActiveFrame();
if ( !_inout_rxFrame.is() )
{
_inout_rxFrame = xDesktop->getCurrentFrame();
}
if ( !_inout_rxFrame.is() && SfxViewFrame::Current() )
_inout_rxFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
if ( !_inout_rxFrame.is() )
{
SAL_WARN( "cui.customize", "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" );
return sModuleID;
}
uno::Reference< css::frame::XModuleManager2 > xModuleManager(
css::frame::ModuleManager::create( xContext ) );
try
{
sModuleID = xModuleManager->identify( _inout_rxFrame );
}
catch ( const frame::UnknownModuleException& )
{
}
}
catch( const uno::Exception& )
{
DBG_UNHANDLED_EXCEPTION("cui.customize");
}
return sModuleID;
}
OUString SvxConfigPage::GetScriptURL() const
{
OUString result;
SvTreeListEntry *pEntry = m_pFunctions->FirstSelected();
if ( pEntry )
{
SfxGroupInfo_Impl *pData = static_cast<SfxGroupInfo_Impl*>(pEntry->GetUserData());
if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) ||
( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) ||
( pData->nKind == SfxCfgKind::GROUP_STYLES ) )
{
result = pData->sCommand;
}
}
return result;
}
OUString SvxConfigPage::GetSelectedDisplayName()
{
return m_pFunctions->GetEntryText( m_pFunctions->FirstSelected() );
}
bool SvxConfigPage::FillItemSet( SfxItemSet* )
{
bool result = false;
for ( sal_Int32 i = 0 ; i < m_pSaveInListBox->GetEntryCount(); ++i )
{
SaveInData* pData =
static_cast<SaveInData*>(m_pSaveInListBox->GetEntryData( i ));
result = pData->Apply();
}
return result;
}
IMPL_LINK_NOARG( SvxConfigPage, SelectSaveInLocation, ListBox&, void )
{
pCurrentSaveInData = static_cast<SaveInData*>(m_pSaveInListBox->GetEntryData(
m_pSaveInListBox->GetSelectedEntryPos()));
Init();
}
void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry const * pToSelect )
{
sal_Int32 nSelectionPos = m_pTopLevelListBox->GetSelectedEntryPos();
m_pTopLevelListBox->Clear();
if ( GetSaveInData() && GetSaveInData()->GetEntries() )
{
for (auto const& entryData : *GetSaveInData()->GetEntries())
{
const sal_Int32 nPos = m_pTopLevelListBox->InsertEntry( SvxConfigPageHelper::stripHotKey(entryData->GetName()) );
m_pTopLevelListBox->SetEntryData( nPos, entryData );
if ( entryData == pToSelect )
nSelectionPos = nPos;
AddSubMenusToUI( SvxConfigPageHelper::stripHotKey( entryData->GetName() ), entryData );
}
}
#ifdef DBG_UTIL
else
{
DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" );
DBG_ASSERT( GetSaveInData()->GetEntries() ,
"SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" );
}
#endif
nSelectionPos = nSelectionPos < m_pTopLevelListBox->GetEntryCount() ?
nSelectionPos : m_pTopLevelListBox->GetEntryCount() - 1;
m_pTopLevelListBox->SelectEntryPos( nSelectionPos );
m_pTopLevelListBox->GetSelectHdl().Call( *m_pTopLevelListBox );
}
void SvxConfigPage::AddSubMenusToUI(
const OUString& rBaseTitle, SvxConfigEntry const * pParentData )
{
for (auto const& entryData : *pParentData->GetEntries())
{
if (entryData->IsPopup())
{
OUString subMenuTitle = rBaseTitle + aMenuSeparatorStr + SvxConfigPageHelper::stripHotKey(entryData->GetName());
const sal_Int32 nPos = m_pTopLevelListBox->InsertEntry( subMenuTitle );
m_pTopLevelListBox->SetEntryData( nPos, entryData );
AddSubMenusToUI( subMenuTitle, entryData );
}
}
}
SvxEntries* SvxConfigPage::FindParentForChild(
SvxEntries* pRootEntries, SvxConfigEntry* pChildData )
{
for (auto const& entryData : *pRootEntries)
{
if (entryData == pChildData)
{
return pRootEntries;
}
else if (entryData->IsPopup())
{
SvxEntries* result =
FindParentForChild( entryData->GetEntries(), pChildData );
if ( result != nullptr )
{
return result;
}
}
}
return nullptr;
}
SvTreeListEntry* SvxConfigPage::AddFunction(
SvTreeListEntry* pTarget, bool bFront, bool bAllowDuplicates )
{
OUString aURL = GetScriptURL();
if ( aURL.isEmpty() )
{
return nullptr;
}
OUString aDisplayName;
OUString aModuleId = vcl::CommandInfoProvider::GetModuleIdentifier( m_xFrame );
if ( typeid(*pCurrentSaveInData) == typeid(ContextMenuSaveInData) )
aDisplayName = vcl::CommandInfoProvider::GetPopupLabelForCommand( aURL, aModuleId );
else if ( typeid(*pCurrentSaveInData) == typeid(MenuSaveInData) )
aDisplayName = vcl::CommandInfoProvider::GetMenuLabelForCommand( aURL, aModuleId );
else
aDisplayName = vcl::CommandInfoProvider::GetLabelForCommand( aURL, aModuleId );
SvxConfigEntry* pNewEntryData =
new SvxConfigEntry( aDisplayName, aURL, false, /*bParentData*/false );
pNewEntryData->SetUserDefined();
if ( aDisplayName.isEmpty() )
pNewEntryData->SetName( GetSelectedDisplayName() );
// check that this function is not already in the menu
SvxConfigEntry* pParent = GetTopLevelSelection();
if ( !bAllowDuplicates )
{
for (auto const& entry : *pParent->GetEntries())
{
if ( entry->GetCommand() == pNewEntryData->GetCommand() )
{
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Info, VclButtonsType::Ok, CuiResId(RID_SVXSTR_MNUCFG_ALREADY_INCLUDED)));
(void)xBox->run();
delete pNewEntryData;
return nullptr;
}
}
}
return InsertEntry( pNewEntryData, pTarget, bFront );
}
SvTreeListEntry* SvxConfigPage::InsertEntry(
SvxConfigEntry* pNewEntryData,
SvTreeListEntry* pTarget,
bool bFront )
{
// Grab the entries list for the currently selected menu
SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
SvTreeListEntry* pNewEntry = nullptr;
SvTreeListEntry* pCurEntry =
pTarget != nullptr ? pTarget : m_pContentsListBox->GetCurEntry();
if ( bFront )
{
pEntries->insert( pEntries->begin(), pNewEntryData );
pNewEntry = InsertEntryIntoUI( pNewEntryData, 0 );
}
else if ( pCurEntry == nullptr || pCurEntry == m_pContentsListBox->Last() )
{
pEntries->push_back( pNewEntryData );
pNewEntry = InsertEntryIntoUI( pNewEntryData );
}
else
{
SvxConfigEntry* pEntryData =
static_cast<SvxConfigEntry*>(pCurEntry->GetUserData());
SvxEntries::iterator iter = pEntries->begin();
SvxEntries::const_iterator end = pEntries->end();
// Advance the iterator to the data for currently selected entry
sal_uInt16 nPos = 0;
while (*iter != pEntryData && ++iter != end)
{
++nPos;
}
// Now step past it to the entry after the currently selected one
++iter;
++nPos;
// Now add the new entry to the UI and to the parent's list
if ( iter != end )
{
pEntries->insert( iter, pNewEntryData );
pNewEntry = InsertEntryIntoUI( pNewEntryData, nPos );
}
}
if ( pNewEntry != nullptr )
{
m_pContentsListBox->Select( pNewEntry );
m_pContentsListBox->MakeVisible( pNewEntry );
GetSaveInData()->SetModified();
GetTopLevelSelection()->SetModified();
}
return pNewEntry;
}
SvTreeListEntry* SvxConfigPage::InsertEntryIntoUI(
SvxConfigEntry* pNewEntryData, sal_uLong nPos )
{
SvTreeListEntry* pNewEntry = nullptr;
if (pNewEntryData->IsSeparator())
{
pNewEntry = m_pContentsListBox->InsertEntry(
OUString("----------------------------------"),
nullptr, false, nPos, pNewEntryData);
}
else
{
OUString aName = SvxConfigPageHelper::stripHotKey( pNewEntryData->GetName() );
Image aImage = GetSaveInData()->GetImage(
pNewEntryData->GetCommand());
if ( !!aImage )
{
pNewEntry = m_pContentsListBox->InsertEntry(
aName, aImage, aImage, nullptr, false, nPos, pNewEntryData );
}
else
{
pNewEntry = m_pContentsListBox->InsertEntry(
aName, nullptr, false, nPos, pNewEntryData );
}
if ( pNewEntryData->IsPopup() ||
pNewEntryData->GetStyle() & css::ui::ItemStyle::DROP_DOWN )
{
// add new popup painter, it gets destructed by the entry
pNewEntry->ReplaceItem( o3tl::make_unique<PopupPainter>(aName), pNewEntry->ItemCount() - 1 );
}
}
return pNewEntry;
}
IMPL_LINK( SvxConfigPage, MoveHdl, Button *, pButton, void )
{
MoveEntry(pButton == m_pMoveUpButton);
}
IMPL_LINK_NOARG( SvxConfigPage, FunctionDoubleClickHdl, SvTreeListBox *, bool )
{
if ( m_pAddCommandButton->IsEnabled() )
m_pAddCommandButton->Click();
return false;
}
IMPL_LINK_NOARG( SvxConfigPage, SelectFunctionHdl, SvTreeListBox *, void )
{
// Store the tooltip of the description field at first run
static const OUString sDescTooltip = m_pDescriptionField->GetQuickHelpText();
// GetScriptURL() returns a non-empty string if a
// valid command is selected on the left box
bool bIsValidCommand = !GetScriptURL().isEmpty();
// Enable/disable Add and Remove buttons depending on current selection
if (bIsValidCommand)
{
m_pAddCommandButton->Enable();
m_pRemoveCommandButton->Enable();
m_pDescriptionField->SetText( m_pFunctions->GetHelpText( false ) );
}
else
{
m_pAddCommandButton->Disable();
m_pRemoveCommandButton->Disable();
m_pDescriptionField->SetText("");
}
// Disable the description field and its label if the local help is not installed
// And inform the user via tooltips
if ( !SfxHelp::IsHelpInstalled() )
{
m_pDescriptionField->Disable();
m_pDescriptionFieldLb->Disable();
m_pDescriptionField->SetQuickHelpText( sDescTooltip );
m_pDescriptionFieldLb->SetQuickHelpText( sDescTooltip );
}
else
{
m_pDescriptionField->Enable();
m_pDescriptionFieldLb->Enable();
m_pDescriptionField->SetQuickHelpText("");
m_pDescriptionFieldLb->SetQuickHelpText("");
}
}
IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, Edit&, void)
{
OUString aSearchTerm( m_pSearchEdit->GetText() );
m_pCommandCategoryListBox->categorySelected( m_pFunctions, aSearchTerm, GetSaveInData() );
}
void SvxConfigPage::MoveEntry( bool bMoveUp )
{
SvTreeListEntry *pSourceEntry = m_pContentsListBox->FirstSelected();
SvTreeListEntry *pTargetEntry = nullptr;
SvTreeListEntry *pToSelect = nullptr;
if ( !pSourceEntry )
{
return;
}
if ( bMoveUp )
{
// Move Up is just a Move Down with the source and target reversed
pTargetEntry = pSourceEntry;
pSourceEntry = pTargetEntry->PrevSibling();
pToSelect = pTargetEntry;
}
else
{
pTargetEntry = pSourceEntry->NextSibling();
pToSelect = pSourceEntry;
}
if ( MoveEntryData( pSourceEntry, pTargetEntry ) )
{
m_pContentsListBox->GetModel()->Move( pSourceEntry, pTargetEntry );
m_pContentsListBox->Select( pToSelect );
m_pContentsListBox->MakeVisible( pToSelect );
UpdateButtonStates();
}
}
bool SvxConfigPage::MoveEntryData(
SvTreeListEntry const * pSourceEntry, SvTreeListEntry const * pTargetEntry )
{
//#i53677#
if (nullptr == pSourceEntry || nullptr == pTargetEntry)
{
return false;
}
// Grab the entries list for the currently selected menu
SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
SvxConfigEntry* pSourceData =
static_cast<SvxConfigEntry*>(pSourceEntry->GetUserData());
SvxConfigEntry* pTargetData =
static_cast<SvxConfigEntry*>(pTargetEntry->GetUserData());
if ( pSourceData != nullptr && pTargetData != nullptr )
{
// remove the source entry from our list
SvxConfigPageHelper::RemoveEntry( pEntries, pSourceData );
SvxEntries::iterator iter = pEntries->begin();
SvxEntries::const_iterator end = pEntries->end();
// advance the iterator to the position of the target entry
while (*iter != pTargetData && ++iter != end) ;
// insert the source entry at the position after the target
pEntries->insert( ++iter, pSourceData );
GetSaveInData()->SetModified();
GetTopLevelSelection()->SetModified();
return true;
}
return false;
}
SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog(
weld::Window* pParent, SvxEntries* entries,
SvxConfigEntry const * selection, bool bCreateMenu )
: GenericDialogController(pParent, "cui/ui/movemenu.ui", "MoveMenuDialog")
, m_xMenuBox(m_xBuilder->weld_widget("namebox"))
, m_xMenuNameEdit(m_xBuilder->weld_entry("menuname"))
, m_xMenuListBox(m_xBuilder->weld_tree_view("menulist"))
, m_xMoveUpButton(m_xBuilder->weld_button("up"))
, m_xMoveDownButton(m_xBuilder->weld_button("down"))
{
m_xMenuListBox->set_size_request(-1, m_xMenuListBox->get_height_rows(12));
// Copy the entries list passed in
if ( entries != nullptr )
{
mpEntries.reset( new SvxEntries );
for (auto const& entry : *entries)
{
m_xMenuListBox->append(OUString::number(reinterpret_cast<sal_uInt64>(entry)),
SvxConfigPageHelper::stripHotKey(entry->GetName()), "");
mpEntries->push_back(entry);
if (entry == selection)
{
m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
}
}
}
if ( bCreateMenu )
{
// Generate custom name for new menu
OUString prefix = CuiResId( RID_SVXSTR_NEW_MENU );
OUString newname = SvxConfigPageHelper::generateCustomName( prefix, entries );
OUString newurl = SvxConfigPageHelper::generateCustomMenuURL( mpEntries.get() );
SvxConfigEntry* pNewEntryData =
new SvxConfigEntry( newname, newurl, true, /*bParentData*/false );
pNewEntryData->SetName( newname );
pNewEntryData->SetUserDefined();
pNewEntryData->SetMain();
m_sNewMenuEntryId = OUString::number(reinterpret_cast<sal_uInt64>(pNewEntryData));
m_xMenuListBox->append(m_sNewMenuEntryId,
SvxConfigPageHelper::stripHotKey(pNewEntryData->GetName()), "");
m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
if (mpEntries)
mpEntries->push_back(pNewEntryData);
m_xMenuNameEdit->set_text(newname);
m_xMenuNameEdit->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, ModifyHdl));
}
else
{
// hide name label and textfield
m_xMenuBox->hide();
// change the title
m_xDialog->set_title(CuiResId(RID_SVXSTR_MOVE_MENU));
}
m_xMenuListBox->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, SelectHdl));
m_xMoveUpButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
m_xMoveDownButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
}
SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog()
{
}
IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::Entry&, void)
{
// if the Edit control is empty do not change the name
if (m_xMenuNameEdit->get_text().isEmpty())
{
return;
}
SvxConfigEntry* pNewEntryData = reinterpret_cast<SvxConfigEntry*>(m_sNewMenuEntryId.toUInt64());
pNewEntryData->SetName(m_xMenuNameEdit->get_text());
const int nNewMenuPos = m_xMenuListBox->find_id(m_sNewMenuEntryId);
const int nOldSelection = m_xMenuListBox->get_selected_index();
m_xMenuListBox->remove(nNewMenuPos);
m_xMenuListBox->insert(nNewMenuPos, m_sNewMenuEntryId, pNewEntryData->GetName(), "");
m_xMenuListBox->select(nOldSelection);
}
IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, SelectHdl, weld::TreeView&, void)
{
UpdateButtonStates();
}
void SvxMainMenuOrganizerDialog::UpdateButtonStates()
{
// Disable Up and Down buttons depending on current selection
const int nSelected = m_xMenuListBox->get_selected_index();
m_xMoveUpButton->set_sensitive(nSelected > 0);
m_xMoveDownButton->set_sensitive(nSelected != -1 && nSelected < m_xMenuListBox->n_children() - 1);
}
IMPL_LINK( SvxMainMenuOrganizerDialog, MoveHdl, weld::Button&, rButton, void )
{
int nSourceEntry = m_xMenuListBox->get_selected_index();
if (nSourceEntry == -1)
return;
int nTargetEntry;
if (&rButton == m_xMoveDownButton.get())
{
nTargetEntry = nSourceEntry + 1;
}
else
{
// Move Up is just a Move Down with the source and target reversed
nTargetEntry = nSourceEntry - 1;
}
OUString sId = m_xMenuListBox->get_id(nSourceEntry);
OUString sEntry = m_xMenuListBox->get_text(nSourceEntry);
m_xMenuListBox->remove(nSourceEntry);
m_xMenuListBox->insert(nTargetEntry, sId, sEntry, "");
m_xMenuListBox->select(nTargetEntry);
UpdateButtonStates();
}
SvxConfigEntry* SvxMainMenuOrganizerDialog::GetSelectedEntry()
{
const int nSelected(m_xMenuListBox->get_selected_index());
if (nSelected == -1)
return nullptr;
return reinterpret_cast<SvxConfigEntry*>(m_xMenuListBox->get_id(nSelected).toUInt64());
}
SvxConfigEntry::SvxConfigEntry( const OUString& rDisplayName,
const OUString& rCommandURL, bool bPopup, bool bParentData )
: nId( 1 )
, aLabel(rDisplayName)
, aCommand(rCommandURL)
, bPopUp(bPopup)
, bStrEdited( false )
, bIsUserDefined( false )
, bIsMain( false )
, bIsParentData( bParentData )
, bIsModified( false )
, bIsVisible( true )
, nStyle( 0 )
{
if (bPopUp)
{
mpEntries.reset( new SvxEntries );
}
}
SvxConfigEntry::~SvxConfigEntry()
{
if (mpEntries)
{
for (auto const& entry : *mpEntries)
{
delete entry;
}
}
}
bool SvxConfigEntry::IsMovable()
{
return !IsPopup() || IsMain();
}
bool SvxConfigEntry::IsDeletable()
{
return !IsMain() || IsUserDefined();
}
bool SvxConfigEntry::IsRenamable()
{
return !IsMain() || IsUserDefined();
}
ToolbarSaveInData::ToolbarSaveInData(
const uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr,
const uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr,
const OUString& aModuleId,
bool docConfig ) :
SaveInData ( xCfgMgr, xParentCfgMgr, aModuleId, docConfig ),
m_aDescriptorContainer ( ITEM_DESCRIPTOR_CONTAINER )
{
uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
// Initialize the m_xPersistentWindowState variable which is used
// to get the default properties of system toolbars such as name
uno::Reference< container::XNameAccess > xPWSS = css::ui::theWindowStateConfiguration::get( xContext );
xPWSS->getByName( aModuleId ) >>= m_xPersistentWindowState;
}
ToolbarSaveInData::~ToolbarSaveInData()
{
}
sal_Int32 ToolbarSaveInData::GetSystemStyle( const OUString& rResourceURL )
{
sal_Int32 result = 0;
if ( rResourceURL.startsWith( "private" ) &&
m_xPersistentWindowState.is() &&
m_xPersistentWindowState->hasByName( rResourceURL ) )
{
try
{
uno::Sequence< beans::PropertyValue > aProps;
uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
if ( a >>= aProps )
{
for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
{
if ( aProps[ i ].Name == ITEM_DESCRIPTOR_STYLE )
{
aProps[i].Value >>= result;
break;
}
}
}
}
catch ( uno::Exception& )
{
// do nothing, a default value is returned
}
}
return result;
}
void ToolbarSaveInData::SetSystemStyle(
const uno::Reference< frame::XFrame >& xFrame,
const OUString& rResourceURL,
sal_Int32 nStyle )
{
// change the style using the API
SetSystemStyle( rResourceURL, nStyle );
// this code is a temporary hack as the UI is not updating after
// changing the toolbar style via the API
uno::Reference< css::frame::XLayoutManager > xLayoutManager;
vcl::Window *window = nullptr;
uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
if ( xPropSet.is() )
{
uno::Any a = xPropSet->getPropertyValue( "LayoutManager" );
a >>= xLayoutManager;
}
if ( xLayoutManager.is() )
{
uno::Reference< css::ui::XUIElement > xUIElement =
xLayoutManager->getElement( rResourceURL );
// check reference before we call getRealInterface. The layout manager
// can only provide references for elements that have been created
// before. It's possible that the current element is not available.
uno::Reference< css::awt::XWindow > xWindow;
if ( xUIElement.is() )
xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
window = VCLUnoHelper::GetWindow( xWindow ).get();
}
if ( window != nullptr && window->GetType() == WindowType::TOOLBOX )
{
ToolBox* toolbox = static_cast<ToolBox*>(window);
if ( nStyle == 0 )
{
toolbox->SetButtonType( ButtonType::SYMBOLONLY );
}
else if ( nStyle == 1 )
{
toolbox->SetButtonType( ButtonType::TEXT );
}
if ( nStyle == 2 )
{
toolbox->SetButtonType( ButtonType::SYMBOLTEXT );
}
}
}
void ToolbarSaveInData::SetSystemStyle(
const OUString& rResourceURL,
sal_Int32 nStyle )
{
if ( rResourceURL.startsWith( "private" ) &&
m_xPersistentWindowState.is() &&
m_xPersistentWindowState->hasByName( rResourceURL ) )
{
try
{
uno::Sequence< beans::PropertyValue > aProps;
uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
if ( a >>= aProps )
{
for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
{
if ( aProps[ i ].Name == ITEM_DESCRIPTOR_STYLE )
{
aProps[ i ].Value <<= nStyle;
break;
}
}
}
uno::Reference< container::XNameReplace >
xNameReplace( m_xPersistentWindowState, uno::UNO_QUERY );
xNameReplace->replaceByName( rResourceURL, uno::Any( aProps ) );
}
catch ( uno::Exception& )
{
// do nothing, a default value is returned
SAL_WARN("cui.customize", "Exception setting toolbar style");
}
}
}
OUString ToolbarSaveInData::GetSystemUIName( const OUString& rResourceURL )
{
OUString result;
if ( rResourceURL.startsWith( "private" ) &&
m_xPersistentWindowState.is() &&
m_xPersistentWindowState->hasByName( rResourceURL ) )
{
try
{
uno::Sequence< beans::PropertyValue > aProps;
uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
if ( a >>= aProps )
{
for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
{
if ( aProps[ i ].Name == ITEM_DESCRIPTOR_UINAME )
{
aProps[ i ].Value >>= result;
}
}
}
}
catch ( uno::Exception& )
{
// do nothing, an empty UIName will be returned
}
}
if ( rResourceURL.startsWith( ".uno" ) &&
m_xCommandToLabelMap.is() &&
m_xCommandToLabelMap->hasByName( rResourceURL ) )
{
uno::Any a;
try
{
a = m_xCommandToLabelMap->getByName( rResourceURL );
uno::Sequence< beans::PropertyValue > aPropSeq;
if ( a >>= aPropSeq )
{
for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
{
if ( aPropSeq[i].Name == ITEM_DESCRIPTOR_LABEL )
{
aPropSeq[i].Value >>= result;
}
}
}
}
catch ( uno::Exception& )
{
// not a system command name
}
}
return result;
}
SvxEntries* ToolbarSaveInData::GetEntries()
{
typedef std::unordered_map<OUString, bool > ToolbarInfo;
ToolbarInfo aToolbarInfo;
if ( pRootEntry == nullptr )
{
pRootEntry.reset( new SvxConfigEntry( "MainToolbars", OUString(), true, /*bParentData*/false) );
uno::Sequence< uno::Sequence < beans::PropertyValue > > info =
GetConfigManager()->getUIElementsInfo(
css::ui::UIElementType::TOOLBAR );
for ( sal_Int32 i = 0; i < info.getLength(); ++i )
{
uno::Sequence< beans::PropertyValue > props = info[ i ];
OUString url;
OUString systemname;
OUString uiname;
for ( sal_Int32 j = 0; j < props.getLength(); ++j )
{
if ( props[ j ].Name == ITEM_DESCRIPTOR_RESOURCEURL )
{
props[ j ].Value >>= url;
systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
}
else if ( props[ j ].Name == ITEM_DESCRIPTOR_UINAME )
{
props[ j ].Value >>= uiname;
}
}
try
{
uno::Reference< container::XIndexAccess > xToolbarSettings =
GetConfigManager()->getSettings( url, false );
if ( uiname.isEmpty() )
{
// try to get the name from m_xPersistentWindowState
uiname = GetSystemUIName( url );
if ( uiname.isEmpty() )
{
uiname = systemname;
}
}
SvxConfigEntry* pEntry = new SvxConfigEntry(
uiname, url, true, /*bParentData*/false );
pEntry->SetMain();
pEntry->SetStyle( GetSystemStyle( url ) );
// insert into std::unordered_map to filter duplicates from the parent
aToolbarInfo.emplace( systemname, true );
OUString custom(CUSTOM_TOOLBAR_STR);
if ( systemname.startsWith( custom ) )
{
pEntry->SetUserDefined();
}
else
{
pEntry->SetUserDefined( false );
}
pRootEntry->GetEntries()->push_back( pEntry );
LoadToolbar( xToolbarSettings, pEntry );
}
catch ( container::NoSuchElementException& )
{
// TODO, handle resourceURL with no settings
}
}
uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
if ( xParentCfgMgr.is() )
{
// Retrieve also the parent toolbars to make it possible
// to configure module toolbars and save them into the document
// config manager.
uno::Sequence< uno::Sequence < beans::PropertyValue > > info_ =
xParentCfgMgr->getUIElementsInfo(
css::ui::UIElementType::TOOLBAR );
for ( sal_Int32 i = 0; i < info_.getLength(); ++i )
{
uno::Sequence< beans::PropertyValue > props = info_[ i ];
OUString url;
OUString systemname;
OUString uiname;
for ( sal_Int32 j = 0; j < props.getLength(); ++j )
{
if ( props[ j ].Name == ITEM_DESCRIPTOR_RESOURCEURL )
{
props[ j ].Value >>= url;
systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
}
else if ( props[ j ].Name == ITEM_DESCRIPTOR_UINAME )
{
props[ j ].Value >>= uiname;
}
}
// custom toolbars of the parent are not visible in the document layer
OUString custom(CUSTOM_TOOLBAR_STR);
if ( systemname.startsWith( custom ) )
continue;
// check if toolbar is already in the document layer
ToolbarInfo::const_iterator pIter = aToolbarInfo.find( systemname );
if ( pIter == aToolbarInfo.end() )
{
aToolbarInfo.emplace( systemname, true );
try
{
uno::Reference< container::XIndexAccess > xToolbarSettings =
xParentCfgMgr->getSettings( url, false );
if ( uiname.isEmpty() )
{
// try to get the name from m_xPersistentWindowState
uiname = GetSystemUIName( url );
if ( uiname.isEmpty() )
{
uiname = systemname;
}
}
SvxConfigEntry* pEntry = new SvxConfigEntry(
uiname, url, true, true );
pEntry->SetMain();
pEntry->SetStyle( GetSystemStyle( url ) );
if ( systemname.startsWith( custom ) )
{
pEntry->SetUserDefined();
}
else
{
pEntry->SetUserDefined( false );
}
pRootEntry->GetEntries()->push_back( pEntry );
LoadToolbar( xToolbarSettings, pEntry );
}
catch ( container::NoSuchElementException& )
{
// TODO, handle resourceURL with no settings
}
}
}
}
std::sort( GetEntries()->begin(), GetEntries()->end(), SvxConfigPageHelper::EntrySort );
}
return pRootEntry->GetEntries();
}
void
ToolbarSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
{
pRootEntry->SetEntries( std::move(pNewEntries) );
}
bool
ToolbarSaveInData::HasURL( const OUString& rURL )
{
for (auto const& entry : *GetEntries())
{
if (entry->GetCommand() == rURL)
{
return !entry->IsParentData();
}
}
return false;
}
bool ToolbarSaveInData::HasSettings()
{
// return true if there is at least one toolbar entry
return GetEntries()->size() > 0;
}
void ToolbarSaveInData::Reset()
{
// reset each toolbar by calling removeSettings for its toolbar URL
for (auto const& entry : *GetEntries())
{
try
{
OUString url = entry->GetCommand();
GetConfigManager()->removeSettings( url );
}
catch ( uno::Exception& )
{
// error occurred removing the settings
// TODO - add error dialog in future?
}
}
// persist changes to toolbar storage
PersistChanges( GetConfigManager() );
// now delete the root SvxConfigEntry the next call to GetEntries()
// causes it to be reinitialised
pRootEntry.reset();
// reset all icons to default
try
{
GetImageManager()->reset();
PersistChanges( GetImageManager() );
}
catch ( uno::Exception& )
{
SAL_WARN("cui.customize", "Error resetting all icons when resetting toolbars");
}
}
bool ToolbarSaveInData::Apply()
{
// toolbar changes are instantly applied
return false;
}
void ToolbarSaveInData::ApplyToolbar(
uno::Reference< container::XIndexContainer > const & rToolbarBar,
uno::Reference< lang::XSingleComponentFactory >& rFactory,
SvxConfigEntry const * pToolbarData )
{
uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
for (auto const& entry : *pToolbarData->GetEntries())
{
if (entry->IsPopup())
{
uno::Sequence< beans::PropertyValue > aPropValueSeq =
SvxConfigPageHelper::ConvertToolbarEntry(entry);
uno::Reference< container::XIndexContainer > xSubMenuBar(
rFactory->createInstanceWithContext( xContext ),
uno::UNO_QUERY );
sal_Int32 nIndex = aPropValueSeq.getLength();
aPropValueSeq.realloc( nIndex + 1 );
aPropValueSeq[nIndex].Name = m_aDescriptorContainer;
aPropValueSeq[nIndex].Value <<= xSubMenuBar;
rToolbarBar->insertByIndex(
rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
ApplyToolbar(xSubMenuBar, rFactory, entry);
}
else if (entry->IsSeparator())
{
rToolbarBar->insertByIndex(
rToolbarBar->getCount(), uno::Any( m_aSeparatorSeq ));
}
else
{
uno::Sequence< beans::PropertyValue > aPropValueSeq =
SvxConfigPageHelper::ConvertToolbarEntry(entry);
rToolbarBar->insertByIndex(
rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
}
}
}
void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry* pToolbar )
{
// Apply new toolbar structure to our settings container
uno::Reference< container::XIndexAccess > xSettings(
GetConfigManager()->createSettings(), uno::UNO_QUERY );
uno::Reference< container::XIndexContainer > xIndexContainer (
xSettings, uno::UNO_QUERY );
uno::Reference< lang::XSingleComponentFactory > xFactory (
xSettings, uno::UNO_QUERY );
ApplyToolbar( xIndexContainer, xFactory, pToolbar );
uno::Reference< beans::XPropertySet > xProps(
xSettings, uno::UNO_QUERY );
if ( pToolbar->IsUserDefined() )
{
xProps->setPropertyValue(
ITEM_DESCRIPTOR_UINAME,
uno::Any( pToolbar->GetName() ) );
}
try
{
if ( GetConfigManager()->hasSettings( pToolbar->GetCommand() ) )
{
GetConfigManager()->replaceSettings(
pToolbar->GetCommand(), xSettings );
}
else
{
GetConfigManager()->insertSettings(
pToolbar->GetCommand(), xSettings );
if ( pToolbar->IsParentData() )
pToolbar->SetParentData( false );
}
}
catch ( container::NoSuchElementException& )
{
SAL_WARN("cui.customize", "caught container::NoSuchElementException saving settings");
}
catch ( css::io::IOException& )
{
SAL_WARN("cui.customize", "caught IOException saving settings");
}
catch ( css::uno::Exception& )
{
SAL_WARN("cui.customize", "caught some other exception saving settings");
}
PersistChanges( GetConfigManager() );
}
void ToolbarSaveInData::CreateToolbar( SvxConfigEntry* pToolbar )
{
// show the new toolbar in the UI also
uno::Reference< container::XIndexAccess >
xSettings( GetConfigManager()->createSettings(), uno::UNO_QUERY );
uno::Reference< beans::XPropertySet >
xPropertySet( xSettings, uno::UNO_QUERY );
xPropertySet->setPropertyValue(
ITEM_DESCRIPTOR_UINAME,
uno::Any( pToolbar->GetName() ) );
try
{
GetConfigManager()->insertSettings( pToolbar->GetCommand(), xSettings );
}
catch ( container::ElementExistException& )
{
SAL_WARN("cui.customize", "caught ElementExistsException saving settings");
}
catch ( css::lang::IllegalArgumentException& )
{
SAL_WARN("cui.customize", "caught IOException saving settings");
}
catch ( css::lang::IllegalAccessException& )
{
SAL_WARN("cui.customize", "caught IOException saving settings");
}
catch ( css::uno::Exception& )
{
SAL_WARN("cui.customize", "caught some other exception saving settings");
}
GetEntries()->push_back( pToolbar );
PersistChanges( GetConfigManager() );
}
void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry* pToolbar )
{
try
{
OUString url = pToolbar->GetCommand();
GetConfigManager()->removeSettings( url );
SvxConfigPageHelper::RemoveEntry( GetEntries(), pToolbar );
delete pToolbar;
PersistChanges( GetConfigManager() );
// remove the persistent window state data
css::uno::Reference< css::container::XNameContainer > xNameContainer(
m_xPersistentWindowState, css::uno::UNO_QUERY_THROW );
xNameContainer->removeByName( url );
}
catch ( uno::Exception& )
{
// error occurred removing the settings
}
}
void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry* pToolbar )
{
OUString url = pToolbar->GetCommand();
// Restore of toolbar is done by removing it from
// its configuration manager and then getting it again
bool bParentToolbar = pToolbar->IsParentData();
// Cannot restore parent toolbar
if ( bParentToolbar )
return;
try
{
GetConfigManager()->removeSettings( url );
pToolbar->GetEntries()->clear();
PersistChanges( GetConfigManager() );
}
catch ( uno::Exception& )
{
// if an error occurs removing the settings then just return
return;
}
// Now reload the toolbar settings
try
{
uno::Reference< container::XIndexAccess > xToolbarSettings;
if ( IsDocConfig() )
{
xToolbarSettings = GetParentConfigManager()->getSettings( url, false );
pToolbar->SetParentData();
}
else
xToolbarSettings = GetConfigManager()->getSettings( url, false );
LoadToolbar( xToolbarSettings, pToolbar );
// After reloading, ensure that the icon is reset of each entry
// in the toolbar
uno::Sequence< OUString > aURLSeq( 1 );
for (auto const& entry : *pToolbar->GetEntries())
{
aURLSeq[ 0 ] = entry->GetCommand();
try
{
GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq );
}
catch ( uno::Exception& )
{
SAL_WARN("cui.customize", "Error restoring icon when resetting toolbar");
}
}
PersistChanges( GetImageManager() );
}
catch ( container::NoSuchElementException& )
{
// cannot find the resource URL after removing it
// so no entry will appear in the toolbar list
}
}
void ToolbarSaveInData::LoadToolbar(
const uno::Reference< container::XIndexAccess >& xToolbarSettings,
SvxConfigEntry const * pParentData )
{
SvxEntries* pEntries = pParentData->GetEntries();
for ( sal_Int32 nIndex = 0; nIndex < xToolbarSettings->getCount(); ++nIndex )
{
OUString aCommandURL;
OUString aLabel;
bool bIsVisible;
sal_Int32 nStyle;
sal_uInt16 nType( css::ui::ItemType::DEFAULT );
bool bItem = SvxConfigPageHelper::GetToolbarItemData( xToolbarSettings, nIndex, aCommandURL,
aLabel, nType, bIsVisible, nStyle );
if ( bItem )
{
bool bIsUserDefined = true;
if ( nType == css::ui::ItemType::DEFAULT )
{
uno::Any a;
try
{
a = m_xCommandToLabelMap->getByName( aCommandURL );
bIsUserDefined = false;
}
catch ( container::NoSuchElementException& )
{
bIsUserDefined = true;
}
bool bUseDefaultLabel = false;
// If custom label not set retrieve it from the command
// to info service
if ( aLabel.isEmpty() )
{
bUseDefaultLabel = true;
uno::Sequence< beans::PropertyValue > aPropSeq;
if ( a >>= aPropSeq )
{
for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
{
if ( aPropSeq[i].Name == "Name" )
{
aPropSeq[i].Value >>= aLabel;
break;
}
}
}
}
SvxConfigEntry* pEntry = new SvxConfigEntry(
aLabel, aCommandURL, false, /*bParentData*/false );
pEntry->SetUserDefined( bIsUserDefined );
pEntry->SetVisible( bIsVisible );
pEntry->SetStyle( nStyle );
if ( !bUseDefaultLabel )
pEntry->SetName( aLabel );
pEntries->push_back( pEntry );
}
else
{
SvxConfigEntry* pEntry = new SvxConfigEntry;
pEntry->SetUserDefined( bIsUserDefined );
pEntries->push_back( pEntry );
}
}
}
}
SvxNewToolbarDialog::SvxNewToolbarDialog(weld::Window* pWindow, const OUString& rName)
: GenericDialogController(pWindow, "cui/ui/newtoolbardialog.ui", "NewToolbarDialog")
, m_xEdtName(m_xBuilder->weld_entry("edit"))
, m_xBtnOK(m_xBuilder->weld_button("ok"))
, m_xSaveInListBox(m_xBuilder->weld_combo_box_text("savein"))
{
m_xEdtName->set_text(rName);
m_xEdtName->select_region(0, -1);
}
SvxNewToolbarDialog::~SvxNewToolbarDialog()
{
}
/*******************************************************************************
*
* The SvxIconSelectorDialog class
*
*******************************************************************************/
SvxIconSelectorDialog::SvxIconSelectorDialog( vcl::Window *pWindow,
const uno::Reference< css::ui::XImageManager >& rXImageManager,
const uno::Reference< css::ui::XImageManager >& rXParentImageManager )
:
ModalDialog ( pWindow, "IconSelector", "cui/ui/iconselectordialog.ui" ),
m_nNextId ( 0 ),
m_xImageManager ( rXImageManager ),
m_xParentImageManager( rXParentImageManager )
{
get(pTbSymbol, "symbolsToolbar");
get(pFtNote, "noteLabel");
get(pBtnImport, "importButton");
get(pBtnDelete, "deleteButton");
Size aTbSize = pTbSymbol->LogicToPixel(Size(160, 80), MapMode(MapUnit::MapAppFont));
pTbSymbol->set_width_request(aTbSize.Width());
pTbSymbol->set_height_request(aTbSize.Height());
pTbSymbol->SetStyle(pTbSymbol->GetStyle() | WB_SCROLL);
pTbSymbol->SetLineSpacing(true);
typedef std::unordered_map< OUString, bool > ImageInfo;
pTbSymbol->SetPageScroll( true );
m_nExpectedSize = 16;
if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE)
m_nExpectedSize = 26;
else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32)
m_nExpectedSize = 32;
if ( m_nExpectedSize != 16 )
{
pFtNote->SetText( SvxConfigPageHelper::replaceSixteen( pFtNote->GetText(), m_nExpectedSize ) );
}
uno::Reference< uno::XComponentContext > xComponentContext =
::comphelper::getProcessComponentContext();
m_xGraphProvider.set( graphic::GraphicProvider::create( xComponentContext ) );
uno::Reference< css::util::XPathSettings > xPathSettings =
css::util::thePathSettings::get( xComponentContext );
OUString aDirectory = xPathSettings->getUserConfig();
sal_Int32 aCount = aDirectory.getLength();
if ( aCount > 0 )
{
sal_Unicode aChar = aDirectory[ aCount-1 ];
if ( aChar != '/')
{
aDirectory += "/";
}
}
else
{
pBtnImport->Enable( false );
}
aDirectory += "soffice.cfg/import";
uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
css::embed::FileSystemStorageFactory::create( xComponentContext ) );
uno::Sequence< uno::Any > aArgs( 2 );
aArgs[ 0 ] <<= aDirectory;
aArgs[ 1 ] <<= css::embed::ElementModes::READWRITE;
uno::Reference< css::embed::XStorage > xStorage(
xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY );
uno::Sequence<uno::Any> aProp(comphelper::InitAnyPropertySequence(
{
{"UserConfigStorage", uno::Any(xStorage)},
{"OpenMode", uno::Any(css::embed::ElementModes::READWRITE)}
}));
m_xImportedImageManager = css::ui::ImageManager::create( xComponentContext );
m_xImportedImageManager->initialize(aProp);
ImageInfo aImageInfo1;
uno::Sequence< OUString > names;
if ( m_xImportedImageManager.is() )
{
names = m_xImportedImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
for ( sal_Int32 n = 0; n < names.getLength(); ++n )
aImageInfo1.emplace( names[n], false );
}
sal_uInt16 nId = 1;
uno::Sequence< OUString > name( 1 );
for (auto const& elem : aImageInfo1)
{
name[ 0 ] = elem.first;
uno::Sequence< uno::Reference< graphic::XGraphic> > graphics = m_xImportedImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
if ( graphics.getLength() > 0 )
{
Image img = Image( graphics[ 0 ] );
pTbSymbol->InsertItem( nId, img, elem.first );
graphics[ 0 ]->acquire();
pTbSymbol->SetItemData(
nId, static_cast< void * > ( graphics[ 0 ].get() ) );
++nId;
}
}
ImageInfo aImageInfo;
if ( m_xParentImageManager.is() )
{
names = m_xParentImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
for ( sal_Int32 n = 0; n < names.getLength(); ++n )
aImageInfo.emplace( names[n], false );
}
names = m_xImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
for ( sal_Int32 n = 0; n < names.getLength(); ++n )
{
ImageInfo::iterator pIter = aImageInfo.find( names[n] );
if ( pIter != aImageInfo.end() )
pIter->second = true;
else
aImageInfo.emplace( names[n], true );
}
// large growth factor, expecting many entries
for (auto const& elem : aImageInfo)
{
name[ 0 ] = elem.first;
uno::Sequence< uno::Reference< graphic::XGraphic> > graphics;
try
{
if (elem.second)
graphics = m_xImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
else
graphics = m_xParentImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
}
catch ( uno::Exception& )
{
// can't get sequence for this name so it will not be
// added to the list
}
if ( graphics.getLength() > 0 )
{
Image img = Image( graphics[ 0 ] );
if ( !img.GetBitmapEx().IsEmpty() )
{
pTbSymbol->InsertItem( nId, img, elem.first );
uno::Reference< graphic::XGraphic > xGraphic = graphics[ 0 ];
if ( xGraphic.is() )
xGraphic->acquire();
pTbSymbol->SetItemData(
nId, static_cast< void * > ( xGraphic.get() ) );
++nId;
}
}
}
pBtnDelete->Enable( false );
pTbSymbol->SetSelectHdl( LINK(this, SvxIconSelectorDialog, SelectHdl) );
pBtnImport->SetClickHdl( LINK(this, SvxIconSelectorDialog, ImportHdl) );
pBtnDelete->SetClickHdl( LINK(this, SvxIconSelectorDialog, DeleteHdl) );
m_nNextId = pTbSymbol->GetItemCount()+1;
//TODO: ToolBox::ImplToolItems::size_type -> sal_uInt16!
}
SvxIconSelectorDialog::~SvxIconSelectorDialog()
{
disposeOnce();
}
void SvxIconSelectorDialog::dispose()
{
if (pTbSymbol)
{
ToolBox::ImplToolItems::size_type nCount = pTbSymbol->GetItemCount();
for (ToolBox::ImplToolItems::size_type n = 0; n < nCount; ++n )
{
sal_uInt16 nId = pTbSymbol->GetItemId(n);
uno::XInterface* xi = static_cast< uno::XInterface* >(
pTbSymbol->GetItemData( nId ) );
if ( xi != nullptr )
xi->release();
}
}
pTbSymbol.clear();
pFtNote.clear();
pBtnImport.clear();
pBtnDelete.clear();
ModalDialog::dispose();
}
uno::Reference< graphic::XGraphic> SvxIconSelectorDialog::GetSelectedIcon()
{
uno::Reference< graphic::XGraphic > result;
sal_uInt16 nId;
for ( ToolBox::ImplToolItems::size_type n = 0; n < pTbSymbol->GetItemCount(); ++n )
{
nId = pTbSymbol->GetItemId( n );
if ( pTbSymbol->IsItemChecked( nId ) )
{
result.set( static_cast< graphic::XGraphic* >( pTbSymbol->GetItemData( nId ) ) );
}
}
return result;
}
IMPL_LINK_NOARG( SvxIconSelectorDialog, SelectHdl, ToolBox *, void )
{
ToolBox::ImplToolItems::size_type nCount = pTbSymbol->GetItemCount();
for (ToolBox::ImplToolItems::size_type n = 0; n < nCount; ++n )
{
sal_uInt16 nId = pTbSymbol->GetItemId( n );
if ( pTbSymbol->IsItemChecked( nId ) )
{
pTbSymbol->CheckItem( nId, false );
}
}
sal_uInt16 nId = pTbSymbol->GetCurItemId();
pTbSymbol->CheckItem( nId );
OUString aSelImageText = pTbSymbol->GetItemText( nId );
if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), aSelImageText ) )
{
pBtnDelete->Enable();
}
else
{
pBtnDelete->Enable( false );
}
}
IMPL_LINK_NOARG( SvxIconSelectorDialog, ImportHdl, Button *, void)
{
sfx2::FileDialogHelper aImportDialog(
css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, GetFrameWeld());
// disable the link checkbox in the dialog
uno::Reference< css::ui::dialogs::XFilePickerControlAccess >
xController( aImportDialog.GetFilePicker(), uno::UNO_QUERY);
if ( xController.is() )
{
xController->enableControl(
css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK,
false);
}
aImportDialog.SetCurrentFilter(
"PNG - Portable Network Graphic");
if ( ERRCODE_NONE == aImportDialog.Execute() )
{
uno::Sequence< OUString > paths = aImportDialog.GetMPath();
ImportGraphics ( paths );
}
}
IMPL_LINK_NOARG( SvxIconSelectorDialog, DeleteHdl, Button *, void )
{
OUString message = CuiResId( RID_SVXSTR_DELETE_ICON_CONFIRM );
std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Warning, VclButtonsType::OkCancel,
message));
if (xWarn->run() == RET_OK)
{
ToolBox::ImplToolItems::size_type nCount = pTbSymbol->GetItemCount();
for (ToolBox::ImplToolItems::size_type n = 0; n < nCount; ++n )
{
sal_uInt16 nId = pTbSymbol->GetItemId( n );
if ( pTbSymbol->IsItemChecked( nId ) )
{
OUString aSelImageText = pTbSymbol->GetItemText( nId );
uno::Sequence< OUString > URLs { aSelImageText };
pTbSymbol->RemoveItem( pTbSymbol->GetItemPos( nId ) );
m_xImportedImageManager->removeImages( SvxConfigPageHelper::GetImageType(), URLs );
uno::Reference< css::ui::XUIConfigurationPersistence >
xConfigPersistence( m_xImportedImageManager, uno::UNO_QUERY );
if ( xConfigPersistence.is() && xConfigPersistence->isModified() )
{
xConfigPersistence->store();
}
break;
}
}
}
}
bool SvxIconSelectorDialog::ReplaceGraphicItem(
const OUString& aURL )
{
uno::Sequence< OUString > URLs(1);
uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 );
uno::Reference< css::ui::XUIConfigurationPersistence >
xConfigPer( m_xImportedImageManager, uno::UNO_QUERY );
uno::Reference< graphic::XGraphic > xGraphic;
uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
aMediaProps[0].Name = "URL";
aMediaProps[0].Value <<= aURL;
css::awt::Size aSize;
bool bOK = false;
try
{
xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
uno::Reference< beans::XPropertySet > props =
m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
uno::Any a = props->getPropertyValue( "SizePixel" );
a >>= aSize;
if (0 == aSize.Width || 0 == aSize.Height)
return false;
else
bOK = true;
}
catch ( uno::Exception& )
{
return false;
}
bool bResult( false );
ToolBox::ImplToolItems::size_type nCount = pTbSymbol->GetItemCount();
for (ToolBox::ImplToolItems::size_type n = 0; n < nCount; ++n )
{
sal_uInt16 nId = pTbSymbol->GetItemId( n );
if ( pTbSymbol->GetItemText( nId ) == aURL )
{
try
{
// replace/insert image with provided URL
pTbSymbol->RemoveItem( pTbSymbol->GetItemPos( nId ) );
aMediaProps[0].Value <<= aURL;
Image aImage( xGraphic );
if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
{
BitmapEx aBitmap = aImage.GetBitmapEx();
BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
aImage = Image( aBitmapex);
}
pTbSymbol->InsertItem( nId,aImage, aURL, ToolBoxItemBits::NONE, 0 ); //modify
xGraphic = Graphic(aImage.GetBitmapEx()).GetXGraphic();
URLs[0] = aURL;
aImportGraph[ 0 ] = xGraphic;
m_xImportedImageManager->replaceImages( SvxConfigPageHelper::GetImageType(), URLs, aImportGraph );
xConfigPer->store();
bResult = true;
break;
}
catch ( css::uno::Exception& )
{
break;
}
}
}
return bResult;
}
namespace
{
OUString ReplaceIconName(const OUString& rMessage)
{
OUString name;
OUString message = CuiResId( RID_SVXSTR_REPLACE_ICON_WARNING );
OUString placeholder("%ICONNAME" );
sal_Int32 pos = message.indexOf( placeholder );
if ( pos != -1 )
{
name = message.replaceAt(
pos, placeholder.getLength(), rMessage );
}
return name;
}
class SvxIconReplacementDialog
{
private:
std::unique_ptr<weld::MessageDialog> m_xQueryBox;
public:
SvxIconReplacementDialog(weld::Window *pParent, const OUString& rMessage, bool bYestoAll)
: m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning, VclButtonsType::NONE, ReplaceIconName(rMessage)))
{
m_xQueryBox->set_title(CuiResId(RID_SVXSTR_REPLACE_ICON_CONFIRM));
m_xQueryBox->add_button(Button::GetStandardText(StandardButtonType::Yes), 2);
if (bYestoAll)
m_xQueryBox->add_button(CuiResId(RID_SVXSTR_YESTOALL), 5);
m_xQueryBox->add_button(Button::GetStandardText(StandardButtonType::No), 4);
m_xQueryBox->add_button(Button::GetStandardText(StandardButtonType::Cancel), 6);
m_xQueryBox->set_default_response(2);
}
short run() { return m_xQueryBox->run(); }
};
}
void SvxIconSelectorDialog::ImportGraphics(
const uno::Sequence< OUString >& rPaths )
{
uno::Sequence< OUString > rejected( rPaths.getLength() );
sal_Int32 rejectedCount = 0;
sal_uInt16 ret = 0;
sal_Int32 aIndex;
OUString aIconName;
if ( rPaths.getLength() == 1 )
{
if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), rPaths[0] ) )
{
aIndex = rPaths[0].lastIndexOf( '/' );
aIconName = rPaths[0].copy( aIndex+1 );
SvxIconReplacementDialog aDlg(GetFrameWeld(), aIconName, false);
ret = aDlg.run();
if ( ret == 2 )
{
ReplaceGraphicItem( rPaths[0] );
}
}
else
{
if ( !ImportGraphic( rPaths[0] ) )
{
rejected[0] = rPaths[0];
rejectedCount = 1;
}
}
}
else
{
OUString aSourcePath( rPaths[0] );
if ( rPaths[0].lastIndexOf( '/' ) != rPaths[0].getLength() -1 )
aSourcePath = rPaths[0] + "/";
for ( sal_Int32 i = 1; i < rPaths.getLength(); ++i )
{
OUString aPath = aSourcePath + rPaths[i];
if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), aPath ) )
{
aIndex = rPaths[i].lastIndexOf( '/' );
aIconName = rPaths[i].copy( aIndex+1 );
SvxIconReplacementDialog aDlg(GetFrameWeld(), aIconName, true);
ret = aDlg.run();
if ( ret == 2 )
{
ReplaceGraphicItem( aPath );
}
else if ( ret == 5 )
{
for ( sal_Int32 k = i; k < rPaths.getLength(); ++k )
{
aPath = aSourcePath + rPaths[k];
bool bHasReplaced = ReplaceGraphicItem( aPath );
if ( !bHasReplaced )
{
bool result = ImportGraphic( aPath );
if ( !result )
{
rejected[ rejectedCount ] = rPaths[i];
++rejectedCount;
}
}
}
break;
}
}
else
{
bool result = ImportGraphic( aSourcePath + rPaths[i] );
if ( !result )
{
rejected[ rejectedCount ] = rPaths[i];
++rejectedCount;
}
}
}
}
if ( rejectedCount != 0 )
{
OUStringBuffer message;
OUString fPath;
if (rejectedCount > 1)
fPath = rPaths[0].copy(8) + "/";
for ( sal_Int32 i = 0; i < rejectedCount; ++i )
{
message.append(fPath).append(rejected[i]).append("\n");
}
SvxIconChangeDialog aDialog(GetFrameWeld(), message.makeStringAndClear());
(void)aDialog.run();
}
}
bool SvxIconSelectorDialog::ImportGraphic( const OUString& aURL )
{
bool result = false;
sal_uInt16 nId = m_nNextId;
++m_nNextId;
uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
aMediaProps[0].Name = "URL";
uno::Reference< graphic::XGraphic > xGraphic;
css::awt::Size aSize;
aMediaProps[0].Value <<= aURL;
try
{
uno::Reference< beans::XPropertySet > props =
m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
uno::Any a = props->getPropertyValue("SizePixel");
xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
if ( xGraphic.is() )
{
bool bOK = true;
a >>= aSize;
if ( 0 == aSize.Width || 0 == aSize.Height )
bOK = false;
Image aImage( xGraphic );
if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
{
BitmapEx aBitmap = aImage.GetBitmapEx();
BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
aImage = Image( aBitmapex);
}
if ( bOK && !!aImage )
{
pTbSymbol->InsertItem( nId, aImage, aURL, ToolBoxItemBits::NONE, 0 );
xGraphic = Graphic(aImage.GetBitmapEx()).GetXGraphic();
xGraphic->acquire();
pTbSymbol->SetItemData(
nId, static_cast< void * > ( xGraphic.get() ) );
uno::Sequence<OUString> aImportURL { aURL };
uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 );
aImportGraph[ 0 ] = xGraphic;
m_xImportedImageManager->insertImages( SvxConfigPageHelper::GetImageType(), aImportURL, aImportGraph );
uno::Reference< css::ui::XUIConfigurationPersistence >
xConfigPersistence( m_xImportedImageManager, uno::UNO_QUERY );
if ( xConfigPersistence.is() && xConfigPersistence->isModified() )
{
xConfigPersistence->store();
}
result = true;
}
else
{
SAL_WARN("cui.customize", "could not create Image from XGraphic");
}
}
else
{
SAL_WARN("cui.customize", "could not get query XGraphic");
}
}
catch( uno::Exception& e )
{
SAL_WARN("cui.customize", "Caught exception importing XGraphic: " << e);
}
return result;
}
/*******************************************************************************
*
* The SvxIconChangeDialog class added for issue83555
*
*******************************************************************************/
SvxIconChangeDialog::SvxIconChangeDialog(weld::Window *pWindow, const OUString& rMessage)
: MessageDialogController(pWindow, "cui/ui/iconchangedialog.ui", "IconChange", "grid")
, m_xLineEditDescription(m_xBuilder->weld_text_view("addrTextview"))
{
m_xLineEditDescription->set_size_request(m_xLineEditDescription->get_approximate_digit_width() * 48,
m_xLineEditDescription->get_text_height() * 8);
m_xLineEditDescription->set_text(rMessage);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V516 Consider inspecting an odd expression. Non-null function pointer is compared to null: '0 == aSize.Width'.
↑ V516 Consider inspecting an odd expression. Non-null function pointer is compared to null: '0 == aSize.Height'.
↑ V516 Consider inspecting an odd expression. Non-null function pointer is compared to null: '0 == aSize.Width'.
↑ V516 Consider inspecting an odd expression. Non-null function pointer is compared to null: '0 == aSize.Height'.