Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / cui / source / customize / cfg.cxx
blob2879d17b58ec27a8f4b1200af55fdbb8560b4997
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <cassert>
24 #include <stdlib.h>
25 #include <typeinfo>
27 #include <vcl/stdtext.hxx>
28 #include <vcl/commandinfoprovider.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/graph.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/toolbox.hxx>
33 #include <vcl/weld.hxx>
34 #include <vcl/decoview.hxx>
35 #include <vcl/virdev.hxx>
37 #include <sfx2/sfxhelp.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <sfx2/filedlghelper.hxx>
40 #include <sfx2/sfxsids.hrc>
41 #include <svl/stritem.hxx>
42 #include <tools/debug.hxx>
43 #include <tools/diagnose_ex.h>
44 #include <toolkit/helper/vclunohelper.hxx>
46 #include <algorithm>
47 #include <strings.hrc>
49 #include <acccfg.hxx>
50 #include <cfg.hxx>
51 #include <SvxMenuConfigPage.hxx>
52 #include <SvxToolbarConfigPage.hxx>
53 #include <SvxNotebookbarConfigPage.hxx>
54 #include <SvxConfigPageHelper.hxx>
55 #include "eventdlg.hxx"
56 #include <dialmgr.hxx>
58 #include <unotools/configmgr.hxx>
59 #include <com/sun/star/container/XNameContainer.hpp>
60 #include <com/sun/star/embed/ElementModes.hpp>
61 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
62 #include <com/sun/star/frame/ModuleManager.hpp>
63 #include <com/sun/star/frame/UnknownModuleException.hpp>
64 #include <com/sun/star/frame/XFrames.hpp>
65 #include <com/sun/star/frame/XLayoutManager.hpp>
66 #include <com/sun/star/frame/FrameSearchFlag.hpp>
67 #include <com/sun/star/frame/XController.hpp>
68 #include <com/sun/star/frame/Desktop.hpp>
69 #include <com/sun/star/frame/theUICommandDescription.hpp>
70 #include <com/sun/star/graphic/GraphicProvider.hpp>
71 #include <com/sun/star/io/IOException.hpp>
72 #include <com/sun/star/ui/ItemType.hpp>
73 #include <com/sun/star/ui/ItemStyle.hpp>
74 #include <com/sun/star/ui/ImageManager.hpp>
75 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
76 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
77 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
78 #include <com/sun/star/ui/XUIElement.hpp>
79 #include <com/sun/star/ui/UIElementType.hpp>
80 #include <com/sun/star/ui/ImageType.hpp>
81 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
82 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
83 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
84 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
85 #include <com/sun/star/util/thePathSettings.hpp>
86 #include <comphelper/documentinfo.hxx>
87 #include <comphelper/propertysequence.hxx>
88 #include <comphelper/processfactory.hxx>
90 namespace uno = com::sun::star::uno;
91 namespace frame = com::sun::star::frame;
92 namespace lang = com::sun::star::lang;
93 namespace container = com::sun::star::container;
94 namespace beans = com::sun::star::beans;
95 namespace graphic = com::sun::star::graphic;
97 #if OSL_DEBUG_LEVEL > 1
99 void printPropertySet(
100 const OUString& prefix,
101 const uno::Reference< beans::XPropertySet >& xPropSet )
103 uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
104 xPropSet->getPropertySetInfo();
106 uno::Sequence< beans::Property > aPropDetails =
107 xPropSetInfo->getProperties();
109 SAL_WARN("cui", "printPropertySet: " << aPropDetails.getLength() << " properties" );
111 for ( sal_Int32 i = 0; i < aPropDetails.getLength(); ++i )
113 OUString tmp;
114 sal_Int32 ival;
116 uno::Any a = xPropSet->getPropertyValue( aPropDetails[i].Name );
118 if ( a >>= tmp )
120 SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << tmp);
122 else if ( ( a >>= ival ) )
124 SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << " = " << ival);
126 else
128 SAL_WARN("cui", prefix << ": Got property: " << aPropDetails[i].Name << " of type " << a.getValueTypeName());
133 void printProperties(
134 const OUString& prefix,
135 const uno::Sequence< beans::PropertyValue >& aProp )
137 for ( sal_Int32 i = 0; i < aProp.getLength(); ++i )
139 OUString tmp;
141 aProp[i].Value >>= tmp;
143 SAL_WARN("cui", prefix << ": Got property: " << aProp[i].Name << " = " << tmp);
147 void printEntries(SvxEntries* entries)
149 for (auto const& entry : *entries)
151 SAL_WARN("cui", "printEntries: " << entry->GetName());
155 #endif
157 bool
158 SvxConfigPage::CanConfig( const OUString& aModuleId )
160 return !(aModuleId == "com.sun.star.script.BasicIDE" || aModuleId == "com.sun.star.frame.Bibliography");
163 static std::unique_ptr<SfxTabPage> CreateSvxMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
165 return std::make_unique<SvxMenuConfigPage>(pPage, pController, *rSet);
168 static std::unique_ptr<SfxTabPage> CreateSvxContextMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
170 return std::make_unique<SvxMenuConfigPage>(pPage, pController, *rSet, false);
173 static std::unique_ptr<SfxTabPage> CreateKeyboardConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
175 return std::make_unique<SfxAcceleratorConfigPage>(pPage, pController, *rSet);
178 static std::unique_ptr<SfxTabPage> CreateSvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController,
179 const SfxItemSet* rSet)
181 return std::make_unique<SvxNotebookbarConfigPage>(pPage, pController, *rSet);
184 static std::unique_ptr<SfxTabPage> CreateSvxToolbarConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
186 return std::make_unique<SvxToolbarConfigPage>(pPage, pController, *rSet);
189 static std::unique_ptr<SfxTabPage> CreateSvxEventConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
191 return std::make_unique<SvxEventConfigPage>(pPage, pController, *rSet, SvxEventConfigPage::EarlyInit());
194 /******************************************************************************
196 * SvxConfigDialog is the configuration dialog which is brought up from the
197 * Tools menu. It includes tabs for customizing menus, toolbars, events and
198 * key bindings.
200 *****************************************************************************/
201 SvxConfigDialog::SvxConfigDialog(weld::Window * pParent, const SfxItemSet* pInSet)
202 : SfxTabDialogController(pParent, "cui/ui/customizedialog.ui", "CustomizeDialog", pInSet)
204 SvxConfigPageHelper::InitImageType();
206 AddTabPage("menus", CreateSvxMenuConfigPage, nullptr);
207 AddTabPage("toolbars", CreateSvxToolbarConfigPage, nullptr);
208 AddTabPage("notebookbar", CreateSvxNotebookbarConfigPage, nullptr);
209 AddTabPage("contextmenus", CreateSvxContextMenuConfigPage, nullptr);
210 AddTabPage("keyboard", CreateKeyboardConfigPage, nullptr);
211 AddTabPage("events", CreateSvxEventConfigPage, nullptr);
213 const SfxPoolItem* pItem =
214 pInSet->GetItem( pInSet->GetPool()->GetWhich( SID_CONFIG ) );
216 if ( pItem )
218 OUString text = static_cast<const SfxStringItem*>(pItem)->GetValue();
220 if (text.startsWith( ITEM_TOOLBAR_URL ) )
222 SetCurPageId("toolbars");
227 void SvxConfigDialog::SetFrame(const css::uno::Reference<css::frame::XFrame>& xFrame)
229 m_xFrame = xFrame;
230 uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext(),
231 uno::UNO_SET_THROW);
233 OUString aModuleId = SvxConfigPage::GetFrameWithDefaultAndIdentify(m_xFrame);
234 uno::Reference<css::frame::XModuleManager2> xModuleManager(
235 css::frame::ModuleManager::create(xContext));
236 OUString aModuleName = SvxConfigPageHelper::GetUIModuleName(aModuleId, xModuleManager);
237 if (aModuleName != "Writer" && aModuleName != "Calc" && aModuleName != "Impress"
238 && aModuleName != "Draw")
239 RemoveTabPage("notebookbar");
241 if (!SvxConfigPageHelper::showKeyConfigTabPage(xFrame))
242 RemoveTabPage("keyboard");
245 void SvxConfigDialog::PageCreated(const OString &rId, SfxTabPage& rPage)
247 if (rId == "menus" || rId == "keyboard" || rId == "notebookbar"
248 || rId == "toolbars" || rId == "contextmenus")
250 rPage.SetFrame(m_xFrame);
252 else if (rId == "events")
254 dynamic_cast< SvxEventConfigPage& >( rPage ).LateInit( m_xFrame );
258 /******************************************************************************
260 * The SaveInData class is used to hold data for entries in the Save In
261 * ListBox controls in the menu and toolbar tabs
263 ******************************************************************************/
265 // Initialize static variable which holds default XImageManager
266 uno::Reference< css::ui::XImageManager>* SaveInData::xDefaultImgMgr = nullptr;
268 SaveInData::SaveInData(
269 const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
270 const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
271 const OUString& aModuleId,
272 bool isDocConfig )
274 bModified( false ),
275 bDocConfig( isDocConfig ),
276 bReadOnly( false ),
277 m_xCfgMgr( xCfgMgr ),
278 m_xParentCfgMgr( xParentCfgMgr )
280 m_aSeparatorSeq.realloc( 1 );
281 m_aSeparatorSeq[0].Name = ITEM_DESCRIPTOR_TYPE;
282 m_aSeparatorSeq[0].Value <<= css::ui::ItemType::SEPARATOR_LINE;
284 if ( bDocConfig )
286 uno::Reference< css::ui::XUIConfigurationPersistence >
287 xDocPersistence( GetConfigManager(), uno::UNO_QUERY );
289 bReadOnly = xDocPersistence->isReadOnly();
292 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
294 uno::Reference< container::XNameAccess > xNameAccess(
295 css::frame::theUICommandDescription::get(xContext) );
297 xNameAccess->getByName( aModuleId ) >>= m_xCommandToLabelMap;
299 if ( !m_xImgMgr.is() )
301 m_xImgMgr.set( GetConfigManager()->getImageManager(), uno::UNO_QUERY );
304 if ( !IsDocConfig() )
306 // If this is not a document configuration then it is the settings
307 // for the module (writer, calc, impress etc.) Use this as the default
308 // XImageManager instance
309 xDefaultImgMgr = &m_xImgMgr;
311 else
313 // If this is a document configuration then use the module image manager
314 // as default.
315 if ( m_xParentCfgMgr.is() )
317 m_xParentImgMgr.set( m_xParentCfgMgr->getImageManager(), uno::UNO_QUERY );
318 xDefaultImgMgr = &m_xParentImgMgr;
323 uno::Reference<graphic::XGraphic> SaveInData::GetImage(const OUString& rCommandURL)
325 uno::Reference< graphic::XGraphic > xGraphic =
326 SvxConfigPageHelper::GetGraphic( m_xImgMgr, rCommandURL );
328 if (!xGraphic.is() && xDefaultImgMgr != nullptr && (*xDefaultImgMgr).is())
330 xGraphic = SvxConfigPageHelper::GetGraphic( (*xDefaultImgMgr), rCommandURL );
333 return xGraphic;
336 bool SaveInData::PersistChanges(
337 const uno::Reference< uno::XInterface >& xManager )
339 bool result = true;
343 if ( xManager.is() && !IsReadOnly() )
345 uno::Reference< css::ui::XUIConfigurationPersistence >
346 xConfigPersistence( xManager, uno::UNO_QUERY );
348 if ( xConfigPersistence->isModified() )
350 xConfigPersistence->store();
354 catch ( css::io::IOException& )
356 result = false;
359 return result;
362 /******************************************************************************
364 * The MenuSaveInData class extends SaveInData and provides menu specific
365 * load and store functionality.
367 ******************************************************************************/
369 // Initialize static variable which holds default Menu data
370 MenuSaveInData* MenuSaveInData::pDefaultData = nullptr;
372 MenuSaveInData::MenuSaveInData(
373 const uno::Reference< css::ui::XUIConfigurationManager >& cfgmgr,
374 const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
375 const OUString& aModuleId,
376 bool isDocConfig )
378 SaveInData( cfgmgr, xParentCfgMgr, aModuleId, isDocConfig ),
379 m_aMenuResourceURL(
380 ITEM_MENUBAR_URL ),
381 m_aDescriptorContainer(
382 ITEM_DESCRIPTOR_CONTAINER )
386 OUString url( ITEM_MENUBAR_URL );
387 m_xMenuSettings = GetConfigManager()->getSettings( url, false );
389 catch ( container::NoSuchElementException& )
391 // will use menu settings for the module
394 // If this is not a document configuration then it is the settings
395 // for the module (writer, calc, impress etc.). These settings should
396 // be set as the default to be used for SaveIn locations that do not
397 // have custom settings
398 if ( !IsDocConfig() )
400 SetDefaultData( this );
404 MenuSaveInData::~MenuSaveInData()
408 SvxEntries*
409 MenuSaveInData::GetEntries()
411 if ( pRootEntry == nullptr )
413 pRootEntry.reset( new SvxConfigEntry( "MainMenus", OUString(), true, /*bParentData*/false) );
415 if ( m_xMenuSettings.is() )
417 LoadSubMenus( m_xMenuSettings, OUString(), pRootEntry.get(), false );
419 else if ( GetDefaultData() != nullptr )
421 // If the doc has no config settings use module config settings
422 LoadSubMenus( GetDefaultData()->m_xMenuSettings, OUString(), pRootEntry.get(), false );
426 return pRootEntry->GetEntries();
429 void
430 MenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
432 pRootEntry->SetEntries( std::move(pNewEntries) );
435 void SaveInData::LoadSubMenus( const uno::Reference< container::XIndexAccess >& xMenuSettings,
436 const OUString& rBaseTitle, SvxConfigEntry const * pParentData, bool bContextMenu )
438 SvxEntries* pEntries = pParentData->GetEntries();
440 // Don't access non existing menu configuration!
441 if ( !xMenuSettings.is() )
442 return;
444 for ( sal_Int32 nIndex = 0; nIndex < xMenuSettings->getCount(); ++nIndex )
446 uno::Reference< container::XIndexAccess > xSubMenu;
447 OUString aCommandURL;
448 OUString aLabel;
450 sal_uInt16 nType( css::ui::ItemType::DEFAULT );
451 sal_Int32 nStyle(0);
453 bool bItem = SvxConfigPageHelper::GetMenuItemData( xMenuSettings, nIndex,
454 aCommandURL, aLabel, nType, nStyle, xSubMenu );
456 if ( bItem )
458 bool bIsUserDefined = true;
460 if ( nType == css::ui::ItemType::DEFAULT )
462 uno::Any a;
465 a = m_xCommandToLabelMap->getByName( aCommandURL );
466 bIsUserDefined = false;
468 catch ( container::NoSuchElementException& )
470 bIsUserDefined = true;
473 bool bUseDefaultLabel = false;
474 // If custom label not set retrieve it from the command
475 // to info service
476 if ( aLabel.isEmpty() )
478 bUseDefaultLabel = true;
479 uno::Sequence< beans::PropertyValue > aPropSeq;
480 if ( a >>= aPropSeq )
482 OUString aMenuLabel;
483 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
485 if ( bContextMenu )
487 if ( aPropSeq[i].Name == "PopupLabel" )
489 aPropSeq[i].Value >>= aLabel;
490 break;
492 else if ( aPropSeq[i].Name == "Label" )
494 aPropSeq[i].Value >>= aMenuLabel;
497 else if ( aPropSeq[i].Name == "Label" )
499 aPropSeq[i].Value >>= aLabel;
500 break;
503 if ( aLabel.isEmpty() )
504 aLabel = aMenuLabel;
508 SvxConfigEntry* pEntry = new SvxConfigEntry(
509 aLabel, aCommandURL, xSubMenu.is(), /*bParentData*/false );
511 pEntry->SetStyle( nStyle );
512 pEntry->SetUserDefined( bIsUserDefined );
513 if ( !bUseDefaultLabel )
514 pEntry->SetName( aLabel );
516 pEntries->push_back( pEntry );
518 if ( xSubMenu.is() )
520 // popup menu
521 OUString subMenuTitle( rBaseTitle );
523 if ( !subMenuTitle.isEmpty() )
525 subMenuTitle += aMenuSeparatorStr;
527 else
529 pEntry->SetMain();
532 subMenuTitle += SvxConfigPageHelper::stripHotKey( aLabel );
534 LoadSubMenus( xSubMenu, subMenuTitle, pEntry, bContextMenu );
537 else
539 SvxConfigEntry* pEntry = new SvxConfigEntry;
540 pEntry->SetUserDefined( bIsUserDefined );
541 pEntries->push_back( pEntry );
547 bool MenuSaveInData::Apply()
549 bool result = false;
551 if ( IsModified() )
553 // Apply new menu bar structure to our settings container
554 m_xMenuSettings = GetConfigManager()->createSettings();
556 uno::Reference< container::XIndexContainer > xIndexContainer (
557 m_xMenuSettings, uno::UNO_QUERY );
559 uno::Reference< lang::XSingleComponentFactory > xFactory (
560 m_xMenuSettings, uno::UNO_QUERY );
562 Apply( xIndexContainer, xFactory );
566 if ( GetConfigManager()->hasSettings( m_aMenuResourceURL ) )
568 GetConfigManager()->replaceSettings(
569 m_aMenuResourceURL, m_xMenuSettings );
571 else
573 GetConfigManager()->insertSettings(
574 m_aMenuResourceURL, m_xMenuSettings );
577 catch ( css::uno::Exception& )
579 TOOLS_WARN_EXCEPTION("cui.customize", "caught some other exception saving settings");
582 SetModified( false );
584 result = PersistChanges( GetConfigManager() );
587 return result;
590 void MenuSaveInData::Apply(
591 uno::Reference< container::XIndexContainer > const & rMenuBar,
592 uno::Reference< lang::XSingleComponentFactory >& rFactory )
594 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
596 for (auto const& entryData : *GetEntries())
598 uno::Sequence< beans::PropertyValue > aPropValueSeq =
599 SvxConfigPageHelper::ConvertSvxConfigEntry(entryData);
601 uno::Reference< container::XIndexContainer > xSubMenuBar(
602 rFactory->createInstanceWithContext( xContext ),
603 uno::UNO_QUERY );
605 sal_Int32 nIndex = aPropValueSeq.getLength();
606 aPropValueSeq.realloc( nIndex + 1 );
607 aPropValueSeq[nIndex].Name = m_aDescriptorContainer;
608 aPropValueSeq[nIndex].Value <<= xSubMenuBar;
609 rMenuBar->insertByIndex(
610 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
611 ApplyMenu( xSubMenuBar, rFactory, entryData );
615 void SaveInData::ApplyMenu(
616 uno::Reference< container::XIndexContainer > const & rMenuBar,
617 uno::Reference< lang::XSingleComponentFactory >& rFactory,
618 SvxConfigEntry* pMenuData )
620 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
622 for (auto const& entry : *pMenuData->GetEntries())
624 if (entry->IsPopup())
626 uno::Sequence< beans::PropertyValue > aPropValueSeq =
627 SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
629 uno::Reference< container::XIndexContainer > xSubMenuBar(
630 rFactory->createInstanceWithContext( xContext ),
631 uno::UNO_QUERY );
633 sal_Int32 nIndex = aPropValueSeq.getLength();
634 aPropValueSeq.realloc( nIndex + 1 );
635 aPropValueSeq[nIndex].Name = ITEM_DESCRIPTOR_CONTAINER;
636 aPropValueSeq[nIndex].Value <<= xSubMenuBar;
638 rMenuBar->insertByIndex(
639 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
641 ApplyMenu( xSubMenuBar, rFactory, entry );
642 entry->SetModified( false );
644 else if (entry->IsSeparator())
646 rMenuBar->insertByIndex(
647 rMenuBar->getCount(), uno::Any( m_aSeparatorSeq ));
649 else
651 uno::Sequence< beans::PropertyValue > aPropValueSeq =
652 SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
653 rMenuBar->insertByIndex(
654 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
657 pMenuData->SetModified( false );
660 void
661 MenuSaveInData::Reset()
665 GetConfigManager()->removeSettings( m_aMenuResourceURL );
667 catch ( const css::uno::Exception& )
670 PersistChanges( GetConfigManager() );
672 pRootEntry.reset();
676 m_xMenuSettings = GetConfigManager()->getSettings(
677 m_aMenuResourceURL, false );
679 catch ( container::NoSuchElementException& )
681 // will use default settings
685 ContextMenuSaveInData::ContextMenuSaveInData(
686 const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
687 const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
688 const OUString& aModuleId, bool bIsDocConfig )
689 : SaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bIsDocConfig )
691 css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
692 css::uno::Reference< css::container::XNameAccess > xConfig( css::ui::theWindowStateConfiguration::get( xContext ) );
693 xConfig->getByName( aModuleId ) >>= m_xPersistentWindowState;
696 ContextMenuSaveInData::~ContextMenuSaveInData()
700 OUString ContextMenuSaveInData::GetUIName( const OUString& rResourceURL )
702 if ( m_xPersistentWindowState.is() )
704 css::uno::Sequence< css::beans::PropertyValue > aProps;
707 m_xPersistentWindowState->getByName( rResourceURL ) >>= aProps;
709 catch ( const css::uno::Exception& )
712 for ( const auto& aProp : std::as_const(aProps) )
714 if ( aProp.Name == ITEM_DESCRIPTOR_UINAME )
716 OUString aResult;
717 aProp.Value >>= aResult;
718 return aResult;
722 return OUString();
725 SvxEntries* ContextMenuSaveInData::GetEntries()
727 if ( !m_pRootEntry )
729 std::unordered_map< OUString, bool > aMenuInfo;
731 m_pRootEntry.reset( new SvxConfigEntry( "ContextMenus", OUString(), true, /*bParentData*/false ) );
732 css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aElementsInfo;
735 aElementsInfo = GetConfigManager()->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
737 catch ( const css::lang::IllegalArgumentException& )
740 for ( const auto& aElement : std::as_const(aElementsInfo) )
742 OUString aUrl;
743 for ( const auto& aElementProp : aElement )
745 if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
747 aElementProp.Value >>= aUrl;
748 break;
752 css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
755 xPopupMenu = GetConfigManager()->getSettings( aUrl, false );
757 catch ( const css::uno::Exception& )
760 if ( xPopupMenu.is() )
762 // insert into std::unordered_map to filter duplicates from the parent
763 aMenuInfo.emplace( aUrl, true );
765 OUString aUIMenuName = GetUIName( aUrl );
766 if ( aUIMenuName.isEmpty() )
767 // Menus without UI name aren't supposed to be customized.
768 continue;
770 SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, /*bParentData*/false );
771 pEntry->SetMain();
772 m_pRootEntry->GetEntries()->push_back( pEntry );
773 LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
777 // Retrieve also the parent menus, to make it possible to configure module menus and save them into the document.
778 css::uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
779 css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aParentElementsInfo;
782 if ( xParentCfgMgr.is() )
783 aParentElementsInfo = xParentCfgMgr->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
785 catch ( const css::lang::IllegalArgumentException& )
788 for ( const auto& aElement : std::as_const(aParentElementsInfo) )
790 OUString aUrl;
791 for ( const auto& aElementProp : aElement )
793 if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
795 aElementProp.Value >>= aUrl;
796 break;
800 css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
803 if ( aMenuInfo.find( aUrl ) == aMenuInfo.end() )
804 xPopupMenu = xParentCfgMgr->getSettings( aUrl, false );
806 catch ( const css::uno::Exception& )
809 if ( xPopupMenu.is() )
811 OUString aUIMenuName = GetUIName( aUrl );
812 if ( aUIMenuName.isEmpty() )
813 continue;
815 SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, true );
816 pEntry->SetMain();
817 m_pRootEntry->GetEntries()->push_back( pEntry );
818 LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
821 std::sort( m_pRootEntry->GetEntries()->begin(), m_pRootEntry->GetEntries()->end(), SvxConfigPageHelper::EntrySort );
823 return m_pRootEntry->GetEntries();
826 void ContextMenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
828 m_pRootEntry->SetEntries( std::move(pNewEntries) );
831 bool ContextMenuSaveInData::HasURL( const OUString& rURL )
833 SvxEntries* pEntries = GetEntries();
834 for ( const auto& pEntry : *pEntries )
835 if ( pEntry->GetCommand() == rURL )
836 return true;
838 return false;
841 bool ContextMenuSaveInData::HasSettings()
843 return m_pRootEntry && !m_pRootEntry->GetEntries()->empty();
846 bool ContextMenuSaveInData::Apply()
848 if ( !IsModified() )
849 return false;
851 SvxEntries* pEntries = GetEntries();
852 for ( const auto& pEntry : *pEntries )
854 if ( pEntry->IsModified() || SvxConfigPageHelper::SvxConfigEntryModified( pEntry ) )
856 css::uno::Reference< css::container::XIndexContainer > xIndexContainer = GetConfigManager()->createSettings();
857 css::uno::Reference< css::lang::XSingleComponentFactory > xFactory( xIndexContainer, css::uno::UNO_QUERY );
858 ApplyMenu( xIndexContainer, xFactory, pEntry );
860 const OUString& aUrl = pEntry->GetCommand();
863 if ( GetConfigManager()->hasSettings( aUrl ) )
864 GetConfigManager()->replaceSettings( aUrl, xIndexContainer );
865 else
866 GetConfigManager()->insertSettings( aUrl, xIndexContainer );
868 catch ( const css::uno::Exception& )
872 SetModified( false );
873 return PersistChanges( GetConfigManager() );
876 void ContextMenuSaveInData::Reset()
878 SvxEntries* pEntries = GetEntries();
879 for ( const auto& pEntry : *pEntries )
883 GetConfigManager()->removeSettings( pEntry->GetCommand() );
885 catch ( const css::uno::Exception& )
887 TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menus");
890 PersistChanges( GetConfigManager() );
891 m_pRootEntry.reset();
894 void ContextMenuSaveInData::ResetContextMenu( const SvxConfigEntry* pEntry )
898 GetConfigManager()->removeSettings( pEntry->GetCommand() );
900 catch ( const css::uno::Exception& )
902 TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menu");
904 PersistChanges( GetConfigManager() );
905 m_pRootEntry.reset();
908 void SvxMenuEntriesListBox::CreateDropDown()
910 int nWidth = m_xControl->get_text_height() / 2;
911 m_xDropDown->SetOutputSizePixel(Size(nWidth, nWidth));
912 DecorationView aDecoView(m_xDropDown.get());
913 aDecoView.DrawSymbol(tools::Rectangle(Point(0, 0), Size(nWidth, nWidth)),
914 SymbolType::SPIN_RIGHT, m_xDropDown->GetTextColor(),
915 DrawSymbolFlags::NONE);
918 /******************************************************************************
920 * SvxMenuEntriesListBox is the listbox in which the menu items for a
921 * particular menu are shown. We have a custom listbox because we need
922 * to add drag'n'drop support from the Macro Selector and within the
923 * listbox
925 *****************************************************************************/
926 SvxMenuEntriesListBox::SvxMenuEntriesListBox(std::unique_ptr<weld::TreeView> xControl, SvxConfigPage* pPg)
927 : m_xControl(std::move(xControl))
928 , m_xDropDown(m_xControl->create_virtual_device())
929 , m_pPage(pPg)
931 CreateDropDown();
932 m_xControl->connect_key_press(LINK(this, SvxMenuEntriesListBox, KeyInputHdl));
935 SvxMenuEntriesListBox::~SvxMenuEntriesListBox()
939 IMPL_LINK(SvxMenuEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
941 vcl::KeyCode keycode = rKeyEvent.GetKeyCode();
943 // support DELETE for removing the current entry
944 if ( keycode == KEY_DELETE )
946 m_pPage->DeleteSelectedContent();
948 // support CTRL+UP and CTRL+DOWN for moving selected entries
949 else if ( keycode.GetCode() == KEY_UP && keycode.IsMod1() )
951 m_pPage->MoveEntry( true );
953 else if ( keycode.GetCode() == KEY_DOWN && keycode.IsMod1() )
955 m_pPage->MoveEntry( false );
957 else
959 return false; // pass on to default handler
961 return true;
964 /******************************************************************************
966 * SvxConfigPage is the abstract base class on which the Menu and Toolbar
967 * configuration tabpages are based. It includes methods which are common to
968 * both tabpages to add, delete, move and rename items etc.
970 *****************************************************************************/
971 SvxConfigPage::SvxConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
972 : SfxTabPage(pPage, pController, "cui/ui/menuassignpage.ui", "MenuAssignPage", &rSet)
973 , m_aUpdateDataTimer("UpdateDataTimer")
974 , bInitialised(false)
975 , pCurrentSaveInData(nullptr)
976 , m_xCommandCategoryListBox(new CommandCategoryListBox(m_xBuilder->weld_combo_box("commandcategorylist")))
977 , m_xFunctions(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("functions")))
978 , m_xCategoryLabel(m_xBuilder->weld_label("categorylabel"))
979 , m_xDescriptionFieldLb(m_xBuilder->weld_label("descriptionlabel"))
980 , m_xDescriptionField(m_xBuilder->weld_text_view("desc"))
981 , m_xLeftFunctionLabel(m_xBuilder->weld_label("leftfunctionlabel"))
982 , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry"))
983 , m_xSearchLabel(m_xBuilder->weld_label("searchlabel"))
984 , m_xCustomizeLabel(m_xBuilder->weld_label("customizelabel"))
985 , m_xTopLevelListBox(m_xBuilder->weld_combo_box("toplevellist"))
986 , m_xMoveUpButton(m_xBuilder->weld_button("up"))
987 , m_xMoveDownButton(m_xBuilder->weld_button("down"))
988 , m_xSaveInListBox(m_xBuilder->weld_combo_box("savein"))
989 , m_xInsertBtn(m_xBuilder->weld_menu_button("insert"))
990 , m_xModifyBtn(m_xBuilder->weld_menu_button("modify"))
991 , m_xResetBtn(m_xBuilder->weld_button("defaultsbtn"))
992 , m_xAddCommandButton(m_xBuilder->weld_button("add"))
993 , m_xRemoveCommandButton(m_xBuilder->weld_button("remove"))
995 m_xTopLevelListBox->connect_changed(LINK(this, SvxConfigPage, SelectElementHdl));
997 weld::TreeView& rTreeView = m_xFunctions->get_widget();
998 Size aSize(rTreeView.get_approximate_digit_width() * 40, rTreeView.get_height_rows(8));
999 m_xFunctions->set_size_request(aSize.Width(), aSize.Height());
1000 m_xDescriptionField->set_size_request(aSize.Width(), m_xDescriptionField->get_height_rows(3));
1002 m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SvxConfigPage, ImplUpdateDataHdl));
1003 m_aUpdateDataTimer.SetDebugName( "SvxConfigPage UpdateDataTimer" );
1004 m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT);
1006 m_xSearchEdit->connect_changed(LINK(this, SvxConfigPage, SearchUpdateHdl));
1007 m_xSearchEdit->connect_focus_out(LINK(this, SvxConfigPage, FocusOut_Impl));
1009 rTreeView.connect_row_activated(LINK(this, SvxConfigPage, FunctionDoubleClickHdl));
1010 rTreeView.connect_changed(LINK(this, SvxConfigPage, SelectFunctionHdl));
1013 IMPL_LINK_NOARG(SvxConfigPage, SelectElementHdl, weld::ComboBox&, void)
1015 SelectElement();
1018 SvxConfigPage::~SvxConfigPage()
1022 void SvxConfigPage::Reset( const SfxItemSet* )
1024 // If we haven't initialised our XMultiServiceFactory reference
1025 // then Reset is being called at the opening of the dialog.
1027 // Load menu configuration data for the module of the currently
1028 // selected document, for the currently selected document, and for
1029 // all other open documents of the same module type
1030 if ( !bInitialised )
1032 sal_Int32 nPos = 0;
1033 uno::Reference < css::ui::XUIConfigurationManager > xCfgMgr;
1034 uno::Reference < css::ui::XUIConfigurationManager > xDocCfgMgr;
1036 uno::Reference< uno::XComponentContext > xContext(
1037 ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
1039 m_xFrame = GetFrame();
1040 OUString aModuleId = GetFrameWithDefaultAndIdentify( m_xFrame );
1042 // replace %MODULENAME in the label with the correct module name
1043 uno::Reference< css::frame::XModuleManager2 > xModuleManager(
1044 css::frame::ModuleManager::create( xContext ));
1045 OUString aModuleName = SvxConfigPageHelper::GetUIModuleName( aModuleId, xModuleManager );
1047 uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier >
1048 xModuleCfgSupplier( css::ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
1050 // Set up data for module specific menus
1051 SaveInData* pModuleData = nullptr;
1055 xCfgMgr =
1056 xModuleCfgSupplier->getUIConfigurationManager( aModuleId );
1058 pModuleData = CreateSaveInData( xCfgMgr,
1059 uno::Reference< css::ui::XUIConfigurationManager >(),
1060 aModuleId,
1061 false );
1063 catch ( container::NoSuchElementException& )
1067 if ( pModuleData != nullptr )
1069 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pModuleData)));
1070 m_xSaveInListBox->append(sId, utl::ConfigManager::getProductName() + " " + aModuleName);
1073 // try to retrieve the document based ui configuration manager
1074 OUString aTitle;
1075 uno::Reference< frame::XController > xController =
1076 m_xFrame->getController();
1077 if ( CanConfig( aModuleId ) && xController.is() )
1079 uno::Reference< frame::XModel > xModel( xController->getModel() );
1080 if ( xModel.is() )
1082 uno::Reference< css::ui::XUIConfigurationManagerSupplier >
1083 xCfgSupplier( xModel, uno::UNO_QUERY );
1085 if ( xCfgSupplier.is() )
1087 xDocCfgMgr = xCfgSupplier->getUIConfigurationManager();
1089 aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
1093 SaveInData* pDocData = nullptr;
1094 if ( xDocCfgMgr.is() )
1096 pDocData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, true );
1098 if ( !pDocData->IsReadOnly() )
1100 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pDocData)));
1101 m_xSaveInListBox->append(sId, aTitle);
1105 // if an item to select has been passed in (eg. the ResourceURL for a
1106 // toolbar) then try to select the SaveInData entry that has that item
1107 bool bURLToSelectFound = false;
1108 if ( !m_aURLToSelect.isEmpty() )
1110 if ( pDocData && pDocData->HasURL( m_aURLToSelect ) )
1112 m_xSaveInListBox->set_active(nPos);
1113 pCurrentSaveInData = pDocData;
1114 bURLToSelectFound = true;
1116 else if ( pModuleData && pModuleData->HasURL( m_aURLToSelect ) )
1118 m_xSaveInListBox->set_active(0);
1119 pCurrentSaveInData = pModuleData;
1120 bURLToSelectFound = true;
1124 if ( !bURLToSelectFound )
1126 // if the document has menu configuration settings select it
1127 // it the SaveIn listbox, otherwise select the module data
1128 if ( pDocData != nullptr && pDocData->HasSettings() )
1130 m_xSaveInListBox->set_active(nPos);
1131 pCurrentSaveInData = pDocData;
1133 else
1135 m_xSaveInListBox->set_active(0);
1136 pCurrentSaveInData = pModuleData;
1140 #ifdef DBG_UTIL
1141 DBG_ASSERT( pCurrentSaveInData, "SvxConfigPage::Reset(): no SaveInData" );
1142 #endif
1144 if ( CanConfig( aModuleId ) )
1146 // Load configuration for other open documents which have
1147 // same module type
1148 uno::Sequence< uno::Reference< frame::XFrame > > aFrameList;
1151 uno::Reference< frame::XDesktop2 > xFramesSupplier = frame::Desktop::create(
1152 xContext );
1154 uno::Reference< frame::XFrames > xFrames =
1155 xFramesSupplier->getFrames();
1157 aFrameList = xFrames->queryFrames(
1158 frame::FrameSearchFlag::ALL & ~frame::FrameSearchFlag::SELF );
1161 catch( const uno::Exception& )
1163 DBG_UNHANDLED_EXCEPTION("cui.customize");
1166 for ( sal_Int32 i = 0; i < aFrameList.getLength(); ++i )
1168 uno::Reference < frame::XFrame > xf = aFrameList[i];
1170 if ( xf.is() && xf != m_xFrame )
1172 OUString aCheckId;
1173 try{
1174 aCheckId = xModuleManager->identify( xf );
1175 } catch(const uno::Exception&)
1176 { aCheckId.clear(); }
1178 if ( aModuleId == aCheckId )
1180 // try to get the document based ui configuration manager
1181 OUString aTitle2;
1182 uno::Reference< frame::XController > xController_ =
1183 xf->getController();
1185 if ( xController_.is() )
1187 uno::Reference< frame::XModel > xModel(
1188 xController_->getModel() );
1190 if ( xModel.is() )
1192 uno::Reference<
1193 css::ui::XUIConfigurationManagerSupplier >
1194 xCfgSupplier( xModel, uno::UNO_QUERY );
1196 if ( xCfgSupplier.is() )
1198 xDocCfgMgr =
1199 xCfgSupplier->getUIConfigurationManager();
1201 aTitle2 = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
1205 if ( xDocCfgMgr.is() )
1207 SaveInData* pData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, true );
1209 if ( pData && !pData->IsReadOnly() )
1211 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pData)));
1212 m_xSaveInListBox->append(sId, aTitle2);
1220 m_xSaveInListBox->connect_changed(
1221 LINK( this, SvxConfigPage, SelectSaveInLocation ) );
1223 bInitialised = true;
1225 Init();
1227 else
1229 if ( QueryReset() == RET_YES )
1231 // Reset menu configuration for currently selected SaveInData
1232 GetSaveInData()->Reset();
1234 Init();
1239 OUString SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference< frame::XFrame >& _inout_rxFrame )
1241 OUString sModuleID;
1244 uno::Reference< uno::XComponentContext > xContext(
1245 ::comphelper::getProcessComponentContext() );
1247 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(
1248 xContext );
1250 if ( !_inout_rxFrame.is() )
1251 _inout_rxFrame = xDesktop->getActiveFrame();
1253 if ( !_inout_rxFrame.is() )
1255 _inout_rxFrame = xDesktop->getCurrentFrame();
1258 if ( !_inout_rxFrame.is() && SfxViewFrame::Current() )
1259 _inout_rxFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
1261 if ( !_inout_rxFrame.is() )
1263 SAL_WARN( "cui.customize", "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" );
1264 return sModuleID;
1267 uno::Reference< css::frame::XModuleManager2 > xModuleManager(
1268 css::frame::ModuleManager::create( xContext ) );
1272 sModuleID = xModuleManager->identify( _inout_rxFrame );
1274 catch ( const frame::UnknownModuleException& )
1279 catch( const uno::Exception& )
1281 DBG_UNHANDLED_EXCEPTION("cui.customize");
1284 return sModuleID;
1287 OUString SvxConfigPage::GetScriptURL() const
1289 OUString result;
1291 SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xFunctions->get_selected_id().toInt64());
1292 if (pData)
1294 if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) ||
1295 ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) ||
1296 ( pData->nKind == SfxCfgKind::GROUP_STYLES ) )
1298 result = pData->sCommand;
1302 return result;
1305 OUString SvxConfigPage::GetSelectedDisplayName() const
1307 return m_xFunctions->get_selected_text();
1310 bool SvxConfigPage::FillItemSet( SfxItemSet* )
1312 bool result = false;
1314 for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
1316 SaveInData* pData =
1317 reinterpret_cast<SaveInData*>(m_xSaveInListBox->get_id(i).toInt64());
1318 if(m_xSaveInListBox->get_id(i) != notebookbarTabScope)
1319 result = pData->Apply();
1321 return result;
1324 IMPL_LINK_NOARG(SvxConfigPage, SelectSaveInLocation, weld::ComboBox&, void)
1326 pCurrentSaveInData = reinterpret_cast<SaveInData*>(m_xSaveInListBox->get_active_id().toInt64());
1327 Init();
1330 void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry const * pToSelect )
1332 int nSelectionPos = m_xTopLevelListBox->get_active();
1333 m_xTopLevelListBox->clear();
1335 if ( GetSaveInData() && GetSaveInData()->GetEntries() )
1337 for (auto const& entryData : *GetSaveInData()->GetEntries())
1339 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(entryData)));
1340 m_xTopLevelListBox->append(sId, SvxConfigPageHelper::stripHotKey(entryData->GetName()));
1342 if (entryData == pToSelect)
1343 nSelectionPos = m_xTopLevelListBox->get_count() - 1;
1345 AddSubMenusToUI( SvxConfigPageHelper::stripHotKey( entryData->GetName() ), entryData );
1348 #ifdef DBG_UTIL
1349 else
1351 DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" );
1352 DBG_ASSERT( GetSaveInData()->GetEntries() ,
1353 "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" );
1355 #endif
1357 nSelectionPos = (nSelectionPos != -1 && nSelectionPos < m_xTopLevelListBox->get_count()) ?
1358 nSelectionPos : m_xTopLevelListBox->get_count() - 1;
1360 m_xTopLevelListBox->set_active(nSelectionPos);
1361 SelectElement();
1364 void SvxConfigPage::AddSubMenusToUI(
1365 const OUString& rBaseTitle, SvxConfigEntry const * pParentData )
1367 for (auto const& entryData : *pParentData->GetEntries())
1369 if (entryData->IsPopup())
1371 OUString subMenuTitle = rBaseTitle + aMenuSeparatorStr + SvxConfigPageHelper::stripHotKey(entryData->GetName());
1373 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(entryData)));
1374 m_xTopLevelListBox->append(sId, subMenuTitle);
1376 AddSubMenusToUI( subMenuTitle, entryData );
1381 SvxEntries* SvxConfigPage::FindParentForChild(
1382 SvxEntries* pRootEntries, SvxConfigEntry* pChildData )
1384 for (auto const& entryData : *pRootEntries)
1387 if (entryData == pChildData)
1389 return pRootEntries;
1391 else if (entryData->IsPopup())
1393 SvxEntries* result =
1394 FindParentForChild( entryData->GetEntries(), pChildData );
1396 if ( result != nullptr )
1398 return result;
1402 return nullptr;
1405 int SvxConfigPage::AddFunction(int nTarget, bool bAllowDuplicates)
1407 OUString aURL = GetScriptURL();
1408 SvxConfigEntry* pParent = GetTopLevelSelection();
1410 if ( aURL.isEmpty() || pParent == nullptr )
1412 return -1;
1415 OUString aDisplayName;
1416 OUString aModuleId = vcl::CommandInfoProvider::GetModuleIdentifier( m_xFrame );
1418 if ( typeid(*pCurrentSaveInData) == typeid(ContextMenuSaveInData) )
1419 aDisplayName = vcl::CommandInfoProvider::GetPopupLabelForCommand( aURL, aModuleId );
1420 else if ( typeid(*pCurrentSaveInData) == typeid(MenuSaveInData) )
1421 aDisplayName = vcl::CommandInfoProvider::GetMenuLabelForCommand( aURL, aModuleId );
1422 else
1423 aDisplayName = vcl::CommandInfoProvider::GetLabelForCommand( aURL, aModuleId );
1425 SvxConfigEntry* pNewEntryData =
1426 new SvxConfigEntry( aDisplayName, aURL, false, /*bParentData*/false );
1427 pNewEntryData->SetUserDefined();
1429 if ( aDisplayName.isEmpty() )
1430 pNewEntryData->SetName( GetSelectedDisplayName() );
1432 // check that this function is not already in the menu
1433 if ( !bAllowDuplicates )
1435 for (auto const& entry : *pParent->GetEntries())
1437 if ( entry->GetCommand() == pNewEntryData->GetCommand() )
1439 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
1440 VclMessageType::Info, VclButtonsType::Ok, CuiResId(RID_SVXSTR_MNUCFG_ALREADY_INCLUDED)));
1441 xBox->run();
1442 delete pNewEntryData;
1443 return -1;
1448 return AppendEntry(pNewEntryData, nTarget);
1451 int SvxConfigPage::AppendEntry(
1452 SvxConfigEntry* pNewEntryData,
1453 int nTarget)
1455 SvxConfigEntry* pTopLevelSelection = GetTopLevelSelection();
1457 if (pTopLevelSelection == nullptr)
1458 return -1;
1460 // Grab the entries list for the currently selected menu
1461 SvxEntries* pEntries = pTopLevelSelection->GetEntries();
1463 int nNewEntry = -1;
1464 int nCurEntry =
1465 nTarget != -1 ? nTarget : m_xContentsListBox->get_selected_index();
1467 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pNewEntryData)));
1469 if (nCurEntry == -1 || nCurEntry == m_xContentsListBox->n_children() - 1)
1471 pEntries->push_back( pNewEntryData );
1472 m_xContentsListBox->insert(-1, sId);
1473 nNewEntry = m_xContentsListBox->n_children() - 1;
1475 else
1477 SvxConfigEntry* pEntryData =
1478 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nCurEntry).toInt64());
1480 SvxEntries::iterator iter = pEntries->begin();
1481 SvxEntries::const_iterator end = pEntries->end();
1483 // Advance the iterator to the data for currently selected entry
1484 sal_uInt16 nPos = 0;
1485 while (*iter != pEntryData && ++iter != end)
1487 ++nPos;
1490 // Now step past it to the entry after the currently selected one
1491 ++iter;
1492 ++nPos;
1494 // Now add the new entry to the UI and to the parent's list
1495 if ( iter != end )
1497 pEntries->insert( iter, pNewEntryData );
1498 m_xContentsListBox->insert(nPos, sId);
1499 nNewEntry = nPos;
1503 if (nNewEntry != -1)
1505 m_xContentsListBox->select(nNewEntry);
1506 m_xContentsListBox->scroll_to_row(nNewEntry);
1508 GetSaveInData()->SetModified();
1509 GetTopLevelSelection()->SetModified();
1512 return nNewEntry;
1515 void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, int nPos, int nStartCol)
1517 OUString sId(OUString::number(reinterpret_cast<sal_Int64>(pNewEntryData)));
1519 m_xContentsListBox->set_id(nPos, sId);
1521 if (pNewEntryData->IsSeparator())
1523 m_xContentsListBox->set_text(nPos, "----------------------------------", nStartCol + 1);
1525 else
1527 auto xImage = GetSaveInData()->GetImage(pNewEntryData->GetCommand());
1528 if (xImage.is())
1529 m_xContentsListBox->set_image(nPos, xImage, nStartCol);
1530 OUString aName = SvxConfigPageHelper::stripHotKey( pNewEntryData->GetName() );
1531 m_xContentsListBox->set_text(nPos, aName, nStartCol + 1);
1534 if (nStartCol == 0) // menus
1536 if (pNewEntryData->IsPopup() || pNewEntryData->GetStyle() & css::ui::ItemStyle::DROP_DOWN)
1537 m_xContentsListBox->set_dropdown(nPos, nStartCol + 2);
1538 else
1539 m_xContentsListBox->set_image(nPos, nullptr, nStartCol + 2);
1543 IMPL_LINK(SvxConfigPage, MoveHdl, weld::Button&, rButton, void)
1545 MoveEntry(&rButton == m_xMoveUpButton.get());
1548 IMPL_LINK_NOARG(SvxConfigPage, FunctionDoubleClickHdl, weld::TreeView&, bool)
1550 if (m_xAddCommandButton->get_sensitive())
1551 m_xAddCommandButton->clicked();
1552 return true;
1555 IMPL_LINK_NOARG(SvxConfigPage, SelectFunctionHdl, weld::TreeView&, void)
1557 // Store the tooltip of the description field at first run
1558 static const OUString sDescTooltip = m_xDescriptionField->get_tooltip_text();
1560 // GetScriptURL() returns a non-empty string if a
1561 // valid command is selected on the left box
1562 bool bIsValidCommand = !GetScriptURL().isEmpty();
1564 // Enable/disable Add and Remove buttons depending on current selection
1565 if (bIsValidCommand)
1567 m_xAddCommandButton->set_sensitive(true);
1568 m_xRemoveCommandButton->set_sensitive(true);
1570 m_xDescriptionField->set_text(m_xFunctions->GetHelpText(false));
1572 else
1575 m_xAddCommandButton->set_sensitive(false);
1576 m_xRemoveCommandButton->set_sensitive(false);
1578 m_xDescriptionField->set_text("");
1581 // Disable the description field and its label if the local help is not installed
1582 // And inform the user via tooltips
1583 if ( !SfxHelp::IsHelpInstalled() )
1585 m_xDescriptionField->set_sensitive(false);
1586 m_xDescriptionFieldLb->set_sensitive(false);
1587 m_xDescriptionField->set_tooltip_text( sDescTooltip );
1588 m_xDescriptionFieldLb->set_tooltip_text( sDescTooltip );
1590 else
1592 m_xDescriptionField->set_sensitive(true);
1593 m_xDescriptionFieldLb->set_sensitive(true);
1594 m_xDescriptionField->set_tooltip_text("");
1595 m_xDescriptionFieldLb->set_tooltip_text("");
1599 IMPL_LINK_NOARG(SvxConfigPage, ImplUpdateDataHdl, Timer*, void)
1601 OUString aSearchTerm(m_xSearchEdit->get_text());
1602 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData());
1605 IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, weld::Entry&, void)
1607 m_aUpdateDataTimer.Start();
1610 IMPL_LINK_NOARG(SvxConfigPage, FocusOut_Impl, weld::Widget&, void)
1612 if (m_aUpdateDataTimer.IsActive())
1614 m_aUpdateDataTimer.Stop();
1615 m_aUpdateDataTimer.Invoke();
1619 void SvxConfigPage::MoveEntry(bool bMoveUp)
1621 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
1623 int nSourceEntry = rTreeView.get_selected_index();
1624 int nTargetEntry = -1;
1625 int nToSelect = -1;
1627 if (nSourceEntry == -1)
1629 return;
1632 if ( bMoveUp )
1634 // Move Up is just a Move Down with the source and target reversed
1635 nTargetEntry = nSourceEntry;
1636 nSourceEntry = nTargetEntry - 1;
1637 nToSelect = nSourceEntry;
1639 else
1641 nTargetEntry = nSourceEntry + 1;
1642 nToSelect = nTargetEntry;
1645 if (MoveEntryData(nSourceEntry, nTargetEntry))
1647 rTreeView.swap(nSourceEntry, nTargetEntry);
1648 rTreeView.select(nToSelect);
1649 rTreeView.scroll_to_row(nToSelect);
1651 UpdateButtonStates();
1655 bool SvxConfigPage::MoveEntryData(int nSourceEntry, int nTargetEntry)
1657 //#i53677#
1658 if (nSourceEntry == -1 || nTargetEntry == -1)
1660 return false;
1663 // Grab the entries list for the currently selected menu
1664 SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
1666 SvxConfigEntry* pSourceData =
1667 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nSourceEntry).toInt64());
1669 SvxConfigEntry* pTargetData =
1670 reinterpret_cast<SvxConfigEntry*>(m_xContentsListBox->get_id(nTargetEntry).toInt64());
1672 if ( pSourceData != nullptr && pTargetData != nullptr )
1674 // remove the source entry from our list
1675 SvxConfigPageHelper::RemoveEntry( pEntries, pSourceData );
1677 SvxEntries::iterator iter = pEntries->begin();
1678 SvxEntries::const_iterator end = pEntries->end();
1680 // advance the iterator to the position of the target entry
1681 while (*iter != pTargetData && ++iter != end) ;
1683 // insert the source entry at the position after the target
1684 pEntries->insert( ++iter, pSourceData );
1686 GetSaveInData()->SetModified();
1687 GetTopLevelSelection()->SetModified();
1689 return true;
1692 return false;
1695 SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog(
1696 weld::Window* pParent, SvxEntries* entries,
1697 SvxConfigEntry const * selection, bool bCreateMenu )
1698 : GenericDialogController(pParent, "cui/ui/movemenu.ui", "MoveMenuDialog")
1699 , m_xMenuBox(m_xBuilder->weld_widget("namebox"))
1700 , m_xMenuNameEdit(m_xBuilder->weld_entry("menuname"))
1701 , m_xMenuListBox(m_xBuilder->weld_tree_view("menulist"))
1702 , m_xMoveUpButton(m_xBuilder->weld_button("up"))
1703 , m_xMoveDownButton(m_xBuilder->weld_button("down"))
1705 m_xMenuListBox->set_size_request(-1, m_xMenuListBox->get_height_rows(12));
1707 // Copy the entries list passed in
1708 if ( entries != nullptr )
1710 mpEntries.reset( new SvxEntries );
1711 for (auto const& entry : *entries)
1713 m_xMenuListBox->append(OUString::number(reinterpret_cast<sal_uInt64>(entry)),
1714 SvxConfigPageHelper::stripHotKey(entry->GetName()));
1715 mpEntries->push_back(entry);
1716 if (entry == selection)
1718 m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
1723 if ( bCreateMenu )
1725 // Generate custom name for new menu
1726 OUString prefix = CuiResId( RID_SVXSTR_NEW_MENU );
1728 OUString newname = SvxConfigPageHelper::generateCustomName( prefix, entries );
1729 OUString newurl = SvxConfigPageHelper::generateCustomMenuURL( mpEntries.get() );
1731 SvxConfigEntry* pNewEntryData =
1732 new SvxConfigEntry( newname, newurl, true, /*bParentData*/false );
1733 pNewEntryData->SetName( newname );
1734 pNewEntryData->SetUserDefined();
1735 pNewEntryData->SetMain();
1737 m_sNewMenuEntryId = OUString::number(reinterpret_cast<sal_uInt64>(pNewEntryData));
1738 m_xMenuListBox->append(m_sNewMenuEntryId,
1739 SvxConfigPageHelper::stripHotKey(pNewEntryData->GetName()));
1740 m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
1742 if (mpEntries)
1743 mpEntries->push_back(pNewEntryData);
1745 m_xMenuNameEdit->set_text(newname);
1746 m_xMenuNameEdit->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, ModifyHdl));
1748 else
1750 // hide name label and textfield
1751 m_xMenuBox->hide();
1752 // change the title
1753 m_xDialog->set_title(CuiResId(RID_SVXSTR_MOVE_MENU));
1756 m_xMenuListBox->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, SelectHdl));
1758 m_xMoveUpButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
1759 m_xMoveDownButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
1761 UpdateButtonStates();
1764 SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog()
1768 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::Entry&, void)
1770 // if the Edit control is empty do not change the name
1771 if (m_xMenuNameEdit->get_text().isEmpty())
1773 return;
1776 SvxConfigEntry* pNewEntryData = reinterpret_cast<SvxConfigEntry*>(m_sNewMenuEntryId.toUInt64());
1777 pNewEntryData->SetName(m_xMenuNameEdit->get_text());
1779 const int nNewMenuPos = m_xMenuListBox->find_id(m_sNewMenuEntryId);
1780 const int nOldSelection = m_xMenuListBox->get_selected_index();
1781 m_xMenuListBox->remove(nNewMenuPos);
1782 m_xMenuListBox->insert(nNewMenuPos, pNewEntryData->GetName(), &m_sNewMenuEntryId, nullptr, nullptr);
1783 m_xMenuListBox->select(nOldSelection);
1786 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, SelectHdl, weld::TreeView&, void)
1788 UpdateButtonStates();
1791 void SvxMainMenuOrganizerDialog::UpdateButtonStates()
1793 // Disable Up and Down buttons depending on current selection
1794 const int nSelected = m_xMenuListBox->get_selected_index();
1795 m_xMoveUpButton->set_sensitive(nSelected > 0);
1796 m_xMoveDownButton->set_sensitive(nSelected != -1 && nSelected < m_xMenuListBox->n_children() - 1);
1799 IMPL_LINK( SvxMainMenuOrganizerDialog, MoveHdl, weld::Button&, rButton, void )
1801 int nSourceEntry = m_xMenuListBox->get_selected_index();
1802 if (nSourceEntry == -1)
1803 return;
1805 int nTargetEntry;
1807 if (&rButton == m_xMoveDownButton.get())
1809 nTargetEntry = nSourceEntry + 1;
1811 else
1813 // Move Up is just a Move Down with the source and target reversed
1814 nTargetEntry = nSourceEntry - 1;
1817 OUString sId = m_xMenuListBox->get_id(nSourceEntry);
1818 OUString sEntry = m_xMenuListBox->get_text(nSourceEntry);
1819 m_xMenuListBox->remove(nSourceEntry);
1820 m_xMenuListBox->insert(nTargetEntry, sEntry, &sId, nullptr, nullptr);
1821 m_xMenuListBox->select(nTargetEntry);
1823 std::swap(mpEntries->at(nSourceEntry), mpEntries->at(nTargetEntry));
1825 UpdateButtonStates();
1828 SvxConfigEntry* SvxMainMenuOrganizerDialog::GetSelectedEntry()
1830 const int nSelected(m_xMenuListBox->get_selected_index());
1831 if (nSelected == -1)
1832 return nullptr;
1833 return reinterpret_cast<SvxConfigEntry*>(m_xMenuListBox->get_id(nSelected).toUInt64());
1836 SvxConfigEntry::SvxConfigEntry( const OUString& rDisplayName,
1837 const OUString& rCommandURL, bool bPopup, bool bParentData )
1838 : nId( 1 )
1839 , aLabel(rDisplayName)
1840 , aCommand(rCommandURL)
1841 , bPopUp(bPopup)
1842 , bStrEdited( false )
1843 , bIsUserDefined( false )
1844 , bIsMain( false )
1845 , bIsParentData( bParentData )
1846 , bIsModified( false )
1847 , bIsVisible( true )
1848 , nStyle( 0 )
1850 if (bPopUp)
1852 mpEntries.reset( new SvxEntries );
1856 SvxConfigEntry::~SvxConfigEntry()
1858 if (mpEntries)
1860 for (auto const& entry : *mpEntries)
1862 delete entry;
1867 bool SvxConfigEntry::IsMovable() const
1869 return !IsPopup() || IsMain();
1872 bool SvxConfigEntry::IsDeletable() const
1874 return !IsMain() || IsUserDefined();
1877 bool SvxConfigEntry::IsRenamable() const
1879 return !IsMain() || IsUserDefined();
1882 ToolbarSaveInData::ToolbarSaveInData(
1883 const uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr,
1884 const uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr,
1885 const OUString& aModuleId,
1886 bool docConfig ) :
1888 SaveInData ( xCfgMgr, xParentCfgMgr, aModuleId, docConfig ),
1889 m_aDescriptorContainer ( ITEM_DESCRIPTOR_CONTAINER )
1892 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
1893 // Initialize the m_xPersistentWindowState variable which is used
1894 // to get the default properties of system toolbars such as name
1895 uno::Reference< container::XNameAccess > xPWSS = css::ui::theWindowStateConfiguration::get( xContext );
1897 xPWSS->getByName( aModuleId ) >>= m_xPersistentWindowState;
1900 ToolbarSaveInData::~ToolbarSaveInData()
1904 sal_Int32 ToolbarSaveInData::GetSystemStyle( const OUString& rResourceURL )
1906 sal_Int32 result = 0;
1908 if ( rResourceURL.startsWith( "private" ) &&
1909 m_xPersistentWindowState.is() &&
1910 m_xPersistentWindowState->hasByName( rResourceURL ) )
1914 uno::Sequence< beans::PropertyValue > aProps;
1915 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
1917 if ( a >>= aProps )
1919 for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
1921 if ( aProps[ i ].Name == ITEM_DESCRIPTOR_STYLE )
1923 aProps[i].Value >>= result;
1924 break;
1929 catch ( uno::Exception& )
1931 // do nothing, a default value is returned
1935 return result;
1938 void ToolbarSaveInData::SetSystemStyle(
1939 const uno::Reference< frame::XFrame >& xFrame,
1940 const OUString& rResourceURL,
1941 sal_Int32 nStyle )
1943 // change the style using the API
1944 SetSystemStyle( rResourceURL, nStyle );
1946 // this code is a temporary hack as the UI is not updating after
1947 // changing the toolbar style via the API
1948 uno::Reference< css::frame::XLayoutManager > xLayoutManager;
1949 vcl::Window *window = nullptr;
1951 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
1952 if ( xPropSet.is() )
1954 uno::Any a = xPropSet->getPropertyValue( "LayoutManager" );
1955 a >>= xLayoutManager;
1958 if ( xLayoutManager.is() )
1960 uno::Reference< css::ui::XUIElement > xUIElement =
1961 xLayoutManager->getElement( rResourceURL );
1963 // check reference before we call getRealInterface. The layout manager
1964 // can only provide references for elements that have been created
1965 // before. It's possible that the current element is not available.
1966 uno::Reference< css::awt::XWindow > xWindow;
1967 if ( xUIElement.is() )
1968 xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
1970 window = VCLUnoHelper::GetWindow( xWindow ).get();
1973 if ( window != nullptr && window->GetType() == WindowType::TOOLBOX )
1975 ToolBox* toolbox = static_cast<ToolBox*>(window);
1977 if ( nStyle == 0 )
1979 toolbox->SetButtonType( ButtonType::SYMBOLONLY );
1981 else if ( nStyle == 1 )
1983 toolbox->SetButtonType( ButtonType::TEXT );
1985 if ( nStyle == 2 )
1987 toolbox->SetButtonType( ButtonType::SYMBOLTEXT );
1992 void ToolbarSaveInData::SetSystemStyle(
1993 const OUString& rResourceURL,
1994 sal_Int32 nStyle )
1996 if ( rResourceURL.startsWith( "private" ) &&
1997 m_xPersistentWindowState.is() &&
1998 m_xPersistentWindowState->hasByName( rResourceURL ) )
2002 uno::Sequence< beans::PropertyValue > aProps;
2004 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
2006 if ( a >>= aProps )
2008 for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
2010 if ( aProps[ i ].Name == ITEM_DESCRIPTOR_STYLE )
2012 aProps[ i ].Value <<= nStyle;
2013 break;
2018 uno::Reference< container::XNameReplace >
2019 xNameReplace( m_xPersistentWindowState, uno::UNO_QUERY );
2021 xNameReplace->replaceByName( rResourceURL, uno::Any( aProps ) );
2023 catch ( uno::Exception& )
2025 // do nothing, a default value is returned
2026 SAL_WARN("cui.customize", "Exception setting toolbar style");
2031 OUString ToolbarSaveInData::GetSystemUIName( const OUString& rResourceURL )
2033 OUString result;
2035 if ( rResourceURL.startsWith( "private" ) &&
2036 m_xPersistentWindowState.is() &&
2037 m_xPersistentWindowState->hasByName( rResourceURL ) )
2041 uno::Sequence< beans::PropertyValue > aProps;
2042 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
2044 if ( a >>= aProps )
2046 for ( sal_Int32 i = 0; i < aProps.getLength(); ++i )
2048 if ( aProps[ i ].Name == ITEM_DESCRIPTOR_UINAME )
2050 aProps[ i ].Value >>= result;
2055 catch ( uno::Exception& )
2057 // do nothing, an empty UIName will be returned
2061 if ( rResourceURL.startsWith( ".uno" ) &&
2062 m_xCommandToLabelMap.is() &&
2063 m_xCommandToLabelMap->hasByName( rResourceURL ) )
2065 uno::Any a;
2068 a = m_xCommandToLabelMap->getByName( rResourceURL );
2070 uno::Sequence< beans::PropertyValue > aPropSeq;
2071 if ( a >>= aPropSeq )
2073 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
2075 if ( aPropSeq[i].Name == ITEM_DESCRIPTOR_LABEL )
2077 aPropSeq[i].Value >>= result;
2082 catch ( uno::Exception& )
2084 // not a system command name
2088 return result;
2091 SvxEntries* ToolbarSaveInData::GetEntries()
2093 typedef std::unordered_map<OUString, bool > ToolbarInfo;
2095 ToolbarInfo aToolbarInfo;
2097 if ( pRootEntry == nullptr )
2100 pRootEntry.reset( new SvxConfigEntry( "MainToolbars", OUString(), true, /*bParentData*/false) );
2102 uno::Sequence< uno::Sequence < beans::PropertyValue > > info =
2103 GetConfigManager()->getUIElementsInfo(
2104 css::ui::UIElementType::TOOLBAR );
2106 for ( sal_Int32 i = 0; i < info.getLength(); ++i )
2108 uno::Sequence< beans::PropertyValue > props = info[ i ];
2110 OUString url;
2111 OUString systemname;
2112 OUString uiname;
2114 for ( sal_Int32 j = 0; j < props.getLength(); ++j )
2116 if ( props[ j ].Name == ITEM_DESCRIPTOR_RESOURCEURL )
2118 props[ j ].Value >>= url;
2119 systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
2121 else if ( props[ j ].Name == ITEM_DESCRIPTOR_UINAME )
2123 props[ j ].Value >>= uiname;
2129 uno::Reference< container::XIndexAccess > xToolbarSettings =
2130 GetConfigManager()->getSettings( url, false );
2132 if ( uiname.isEmpty() )
2134 // try to get the name from m_xPersistentWindowState
2135 uiname = GetSystemUIName( url );
2137 if ( uiname.isEmpty() )
2139 uiname = systemname;
2143 SvxConfigEntry* pEntry = new SvxConfigEntry(
2144 uiname, url, true, /*bParentData*/false );
2146 pEntry->SetMain();
2147 pEntry->SetStyle( GetSystemStyle( url ) );
2150 // insert into std::unordered_map to filter duplicates from the parent
2151 aToolbarInfo.emplace( systemname, true );
2153 OUString custom(CUSTOM_TOOLBAR_STR);
2154 if ( systemname.startsWith( custom ) )
2156 pEntry->SetUserDefined();
2158 else
2160 pEntry->SetUserDefined( false );
2163 pRootEntry->GetEntries()->push_back( pEntry );
2165 LoadToolbar( xToolbarSettings, pEntry );
2167 catch ( container::NoSuchElementException& )
2169 // TODO, handle resourceURL with no settings
2173 uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
2174 if ( xParentCfgMgr.is() )
2176 // Retrieve also the parent toolbars to make it possible
2177 // to configure module toolbars and save them into the document
2178 // config manager.
2179 uno::Sequence< uno::Sequence < beans::PropertyValue > > info_ =
2180 xParentCfgMgr->getUIElementsInfo(
2181 css::ui::UIElementType::TOOLBAR );
2183 for ( sal_Int32 i = 0; i < info_.getLength(); ++i )
2185 uno::Sequence< beans::PropertyValue > props = info_[ i ];
2187 OUString url;
2188 OUString systemname;
2189 OUString uiname;
2191 for ( sal_Int32 j = 0; j < props.getLength(); ++j )
2193 if ( props[ j ].Name == ITEM_DESCRIPTOR_RESOURCEURL )
2195 props[ j ].Value >>= url;
2196 systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
2198 else if ( props[ j ].Name == ITEM_DESCRIPTOR_UINAME )
2200 props[ j ].Value >>= uiname;
2204 // custom toolbars of the parent are not visible in the document layer
2205 OUString custom(CUSTOM_TOOLBAR_STR);
2206 if ( systemname.startsWith( custom ) )
2207 continue;
2209 // check if toolbar is already in the document layer
2210 ToolbarInfo::const_iterator pIter = aToolbarInfo.find( systemname );
2211 if ( pIter == aToolbarInfo.end() )
2213 aToolbarInfo.emplace( systemname, true );
2217 uno::Reference< container::XIndexAccess > xToolbarSettings =
2218 xParentCfgMgr->getSettings( url, false );
2220 if ( uiname.isEmpty() )
2222 // try to get the name from m_xPersistentWindowState
2223 uiname = GetSystemUIName( url );
2225 if ( uiname.isEmpty() )
2227 uiname = systemname;
2231 SvxConfigEntry* pEntry = new SvxConfigEntry(
2232 uiname, url, true, true );
2234 pEntry->SetMain();
2235 pEntry->SetStyle( GetSystemStyle( url ) );
2237 if ( systemname.startsWith( custom ) )
2239 pEntry->SetUserDefined();
2241 else
2243 pEntry->SetUserDefined( false );
2246 pRootEntry->GetEntries()->push_back( pEntry );
2248 LoadToolbar( xToolbarSettings, pEntry );
2250 catch ( container::NoSuchElementException& )
2252 // TODO, handle resourceURL with no settings
2258 std::sort( GetEntries()->begin(), GetEntries()->end(), SvxConfigPageHelper::EntrySort );
2261 return pRootEntry->GetEntries();
2264 void
2265 ToolbarSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
2267 pRootEntry->SetEntries( std::move(pNewEntries) );
2270 bool
2271 ToolbarSaveInData::HasURL( const OUString& rURL )
2273 for (auto const& entry : *GetEntries())
2275 if (entry->GetCommand() == rURL)
2277 return !entry->IsParentData();
2280 return false;
2283 bool ToolbarSaveInData::HasSettings()
2285 // return true if there is at least one toolbar entry
2286 return !GetEntries()->empty();
2289 void ToolbarSaveInData::Reset()
2291 // reset each toolbar by calling removeSettings for its toolbar URL
2292 for (auto const& entry : *GetEntries())
2296 const OUString& url = entry->GetCommand();
2297 GetConfigManager()->removeSettings( url );
2299 catch ( uno::Exception& )
2301 // error occurred removing the settings
2302 // TODO - add error dialog in future?
2306 // persist changes to toolbar storage
2307 PersistChanges( GetConfigManager() );
2309 // now delete the root SvxConfigEntry the next call to GetEntries()
2310 // causes it to be reinitialised
2311 pRootEntry.reset();
2313 // reset all icons to default
2316 GetImageManager()->reset();
2317 PersistChanges( GetImageManager() );
2319 catch ( uno::Exception& )
2321 SAL_WARN("cui.customize", "Error resetting all icons when resetting toolbars");
2325 bool ToolbarSaveInData::Apply()
2327 // toolbar changes are instantly applied
2328 return false;
2331 void ToolbarSaveInData::ApplyToolbar(
2332 uno::Reference< container::XIndexContainer > const & rToolbarBar,
2333 uno::Reference< lang::XSingleComponentFactory >& rFactory,
2334 SvxConfigEntry const * pToolbarData )
2336 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2338 for (auto const& entry : *pToolbarData->GetEntries())
2340 if (entry->IsPopup())
2342 uno::Sequence< beans::PropertyValue > aPropValueSeq =
2343 SvxConfigPageHelper::ConvertToolbarEntry(entry);
2345 uno::Reference< container::XIndexContainer > xSubMenuBar(
2346 rFactory->createInstanceWithContext( xContext ),
2347 uno::UNO_QUERY );
2349 sal_Int32 nIndex = aPropValueSeq.getLength();
2350 aPropValueSeq.realloc( nIndex + 1 );
2351 aPropValueSeq[nIndex].Name = m_aDescriptorContainer;
2352 aPropValueSeq[nIndex].Value <<= xSubMenuBar;
2353 rToolbarBar->insertByIndex(
2354 rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
2356 ApplyToolbar(xSubMenuBar, rFactory, entry);
2358 else if (entry->IsSeparator())
2360 rToolbarBar->insertByIndex(
2361 rToolbarBar->getCount(), uno::Any( m_aSeparatorSeq ));
2363 else
2365 uno::Sequence< beans::PropertyValue > aPropValueSeq =
2366 SvxConfigPageHelper::ConvertToolbarEntry(entry);
2368 rToolbarBar->insertByIndex(
2369 rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
2374 void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry* pToolbar )
2376 // Apply new toolbar structure to our settings container
2377 uno::Reference< container::XIndexAccess > xSettings =
2378 GetConfigManager()->createSettings();
2380 uno::Reference< container::XIndexContainer > xIndexContainer (
2381 xSettings, uno::UNO_QUERY );
2383 uno::Reference< lang::XSingleComponentFactory > xFactory (
2384 xSettings, uno::UNO_QUERY );
2386 ApplyToolbar( xIndexContainer, xFactory, pToolbar );
2388 uno::Reference< beans::XPropertySet > xProps(
2389 xSettings, uno::UNO_QUERY );
2391 if ( pToolbar->IsUserDefined() )
2393 xProps->setPropertyValue(
2394 ITEM_DESCRIPTOR_UINAME,
2395 uno::Any( pToolbar->GetName() ) );
2400 if ( GetConfigManager()->hasSettings( pToolbar->GetCommand() ) )
2402 GetConfigManager()->replaceSettings(
2403 pToolbar->GetCommand(), xSettings );
2405 else
2407 GetConfigManager()->insertSettings(
2408 pToolbar->GetCommand(), xSettings );
2409 if ( pToolbar->IsParentData() )
2410 pToolbar->SetParentData( false );
2413 catch ( css::uno::Exception const & )
2415 TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings");
2418 PersistChanges( GetConfigManager() );
2421 void ToolbarSaveInData::CreateToolbar( SvxConfigEntry* pToolbar )
2423 // show the new toolbar in the UI also
2424 uno::Reference< container::XIndexAccess >
2425 xSettings = GetConfigManager()->createSettings();
2427 uno::Reference< beans::XPropertySet >
2428 xPropertySet( xSettings, uno::UNO_QUERY );
2430 xPropertySet->setPropertyValue(
2431 ITEM_DESCRIPTOR_UINAME,
2432 uno::Any( pToolbar->GetName() ) );
2436 GetConfigManager()->insertSettings( pToolbar->GetCommand(), xSettings );
2438 catch ( css::uno::Exception const & )
2440 TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings");
2443 GetEntries()->push_back( pToolbar );
2445 PersistChanges( GetConfigManager() );
2448 void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry* pToolbar )
2452 OUString url = pToolbar->GetCommand();
2453 GetConfigManager()->removeSettings( url );
2454 SvxConfigPageHelper::RemoveEntry( GetEntries(), pToolbar );
2455 delete pToolbar;
2457 PersistChanges( GetConfigManager() );
2459 // remove the persistent window state data
2460 css::uno::Reference< css::container::XNameContainer > xNameContainer(
2461 m_xPersistentWindowState, css::uno::UNO_QUERY_THROW );
2463 xNameContainer->removeByName( url );
2465 catch ( uno::Exception& )
2467 // error occurred removing the settings
2471 void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry* pToolbar )
2473 OUString url = pToolbar->GetCommand();
2475 // Restore of toolbar is done by removing it from
2476 // its configuration manager and then getting it again
2477 bool bParentToolbar = pToolbar->IsParentData();
2479 // Cannot restore parent toolbar
2480 if ( bParentToolbar )
2481 return;
2485 GetConfigManager()->removeSettings( url );
2486 pToolbar->GetEntries()->clear();
2487 PersistChanges( GetConfigManager() );
2489 catch ( uno::Exception& )
2491 // if an error occurs removing the settings then just return
2492 return;
2495 // Now reload the toolbar settings
2498 uno::Reference< container::XIndexAccess > xToolbarSettings;
2499 if ( IsDocConfig() )
2501 xToolbarSettings = GetParentConfigManager()->getSettings( url, false );
2502 pToolbar->SetParentData();
2504 else
2505 xToolbarSettings = GetConfigManager()->getSettings( url, false );
2507 LoadToolbar( xToolbarSettings, pToolbar );
2509 // After reloading, ensure that the icon is reset of each entry
2510 // in the toolbar
2511 uno::Sequence< OUString > aURLSeq( 1 );
2512 for (auto const& entry : *pToolbar->GetEntries())
2514 aURLSeq[ 0 ] = entry->GetCommand();
2518 GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq );
2520 catch ( uno::Exception& )
2522 SAL_WARN("cui.customize", "Error restoring icon when resetting toolbar");
2525 PersistChanges( GetImageManager() );
2527 catch ( container::NoSuchElementException& )
2529 // cannot find the resource URL after removing it
2530 // so no entry will appear in the toolbar list
2534 void ToolbarSaveInData::LoadToolbar(
2535 const uno::Reference< container::XIndexAccess >& xToolbarSettings,
2536 SvxConfigEntry const * pParentData )
2538 SvxEntries* pEntries = pParentData->GetEntries();
2540 for ( sal_Int32 nIndex = 0; nIndex < xToolbarSettings->getCount(); ++nIndex )
2542 OUString aCommandURL;
2543 OUString aLabel;
2544 bool bIsVisible;
2545 sal_Int32 nStyle;
2547 sal_uInt16 nType( css::ui::ItemType::DEFAULT );
2549 bool bItem = SvxConfigPageHelper::GetToolbarItemData( xToolbarSettings, nIndex, aCommandURL,
2550 aLabel, nType, bIsVisible, nStyle );
2552 if ( bItem )
2554 bool bIsUserDefined = true;
2556 if ( nType == css::ui::ItemType::DEFAULT )
2558 uno::Any a;
2561 a = m_xCommandToLabelMap->getByName( aCommandURL );
2562 bIsUserDefined = false;
2564 catch ( container::NoSuchElementException& )
2566 bIsUserDefined = true;
2569 bool bUseDefaultLabel = false;
2570 // If custom label not set retrieve it from the command
2571 // to info service
2572 if ( aLabel.isEmpty() )
2574 bUseDefaultLabel = true;
2575 uno::Sequence< beans::PropertyValue > aPropSeq;
2576 if ( a >>= aPropSeq )
2578 for ( sal_Int32 i = 0; i < aPropSeq.getLength(); ++i )
2580 if ( aPropSeq[i].Name == "Name" )
2582 aPropSeq[i].Value >>= aLabel;
2583 break;
2589 SvxConfigEntry* pEntry = new SvxConfigEntry(
2590 aLabel, aCommandURL, false, /*bParentData*/false );
2592 pEntry->SetUserDefined( bIsUserDefined );
2593 pEntry->SetVisible( bIsVisible );
2594 pEntry->SetStyle( nStyle );
2596 if ( !bUseDefaultLabel )
2597 pEntry->SetName( aLabel );
2599 pEntries->push_back( pEntry );
2601 else
2603 SvxConfigEntry* pEntry = new SvxConfigEntry;
2604 pEntry->SetUserDefined( bIsUserDefined );
2605 pEntries->push_back( pEntry );
2611 SvxNewToolbarDialog::SvxNewToolbarDialog(weld::Window* pWindow, const OUString& rName)
2612 : GenericDialogController(pWindow, "cui/ui/newtoolbardialog.ui", "NewToolbarDialog")
2613 , m_xEdtName(m_xBuilder->weld_entry("edit"))
2614 , m_xBtnOK(m_xBuilder->weld_button("ok"))
2615 , m_xSaveInListBox(m_xBuilder->weld_combo_box("savein"))
2617 m_xEdtName->set_text(rName);
2618 m_xEdtName->select_region(0, -1);
2621 SvxNewToolbarDialog::~SvxNewToolbarDialog()
2625 /*******************************************************************************
2627 * The SvxIconSelectorDialog class
2629 *******************************************************************************/
2630 SvxIconSelectorDialog::SvxIconSelectorDialog(weld::Window *pWindow,
2631 const uno::Reference< css::ui::XImageManager >& rXImageManager,
2632 const uno::Reference< css::ui::XImageManager >& rXParentImageManager)
2633 : GenericDialogController(pWindow, "cui/ui/iconselectordialog.ui", "IconSelector")
2634 , m_xImageManager(rXImageManager)
2635 , m_xParentImageManager(rXParentImageManager)
2636 , m_xTbSymbol(new SvtValueSet(m_xBuilder->weld_scrolled_window("symbolswin")))
2637 , m_xTbSymbolWin(new weld::CustomWeld(*m_xBuilder, "symbolsToolbar", *m_xTbSymbol))
2638 , m_xFtNote(m_xBuilder->weld_label("noteLabel"))
2639 , m_xBtnImport(m_xBuilder->weld_button("importButton"))
2640 , m_xBtnDelete(m_xBuilder->weld_button("deleteButton"))
2642 typedef std::unordered_map< OUString, bool > ImageInfo;
2644 m_nExpectedSize = 16;
2645 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE)
2646 m_nExpectedSize = 24;
2647 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32)
2648 m_nExpectedSize = 32;
2650 if ( m_nExpectedSize != 16 )
2652 m_xFtNote->set_label(SvxConfigPageHelper::replaceSixteen(m_xFtNote->get_label(), m_nExpectedSize));
2655 m_xTbSymbol->SetStyle(m_xTbSymbol->GetStyle() | WB_ITEMBORDER | WB_VSCROLL);
2656 m_xTbSymbol->SetColCount(11);
2657 m_xTbSymbol->SetLineCount(5);
2658 m_xTbSymbol->SetItemWidth(m_nExpectedSize);
2659 m_xTbSymbol->SetItemHeight(m_nExpectedSize);
2660 m_xTbSymbol->SetExtraSpacing(6);
2661 Size aSize(m_xTbSymbol->CalcWindowSizePixel(Size(m_nExpectedSize, m_nExpectedSize), 11, 5));
2662 m_xTbSymbol->set_size_request(aSize.Width(), aSize.Height());
2664 uno::Reference< uno::XComponentContext > xComponentContext =
2665 ::comphelper::getProcessComponentContext();
2667 m_xGraphProvider.set( graphic::GraphicProvider::create( xComponentContext ) );
2669 uno::Reference< css::util::XPathSettings > xPathSettings =
2670 css::util::thePathSettings::get( xComponentContext );
2673 OUString aDirectory = xPathSettings->getUserConfig();
2675 sal_Int32 aCount = aDirectory.getLength();
2677 if ( aCount > 0 )
2679 sal_Unicode aChar = aDirectory[ aCount-1 ];
2680 if ( aChar != '/')
2682 aDirectory += "/";
2685 else
2687 m_xBtnImport->set_sensitive(false);
2690 aDirectory += "soffice.cfg/import";
2692 uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
2693 css::embed::FileSystemStorageFactory::create( xComponentContext ) );
2695 uno::Sequence< uno::Any > aArgs( 2 );
2696 aArgs[ 0 ] <<= aDirectory;
2697 aArgs[ 1 ] <<= css::embed::ElementModes::READWRITE;
2699 uno::Reference< css::embed::XStorage > xStorage(
2700 xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY );
2702 uno::Sequence<uno::Any> aProp(comphelper::InitAnyPropertySequence(
2704 {"UserConfigStorage", uno::Any(xStorage)},
2705 {"OpenMode", uno::Any(css::embed::ElementModes::READWRITE)}
2706 }));
2707 m_xImportedImageManager = css::ui::ImageManager::create( xComponentContext );
2708 m_xImportedImageManager->initialize(aProp);
2710 ImageInfo aImageInfo1;
2711 uno::Sequence< OUString > names;
2712 if ( m_xImportedImageManager.is() )
2714 names = m_xImportedImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2715 for ( sal_Int32 n = 0; n < names.getLength(); ++n )
2716 aImageInfo1.emplace( names[n], false );
2719 uno::Sequence< OUString > name( 1 );
2720 for (auto const& elem : aImageInfo1)
2722 name[ 0 ] = elem.first;
2723 uno::Sequence< uno::Reference< graphic::XGraphic> > graphics = m_xImportedImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2724 if ( graphics.hasElements() )
2726 m_aGraphics.push_back(graphics[0]);
2727 Image img(graphics[0]);
2728 m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first);
2732 ImageInfo aImageInfo;
2734 if ( m_xParentImageManager.is() )
2736 names = m_xParentImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2737 for ( sal_Int32 n = 0; n < names.getLength(); ++n )
2738 aImageInfo.emplace( names[n], false );
2741 names = m_xImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2742 for ( sal_Int32 n = 0; n < names.getLength(); ++n )
2744 ImageInfo::iterator pIter = aImageInfo.find( names[n] );
2745 if ( pIter != aImageInfo.end() )
2746 pIter->second = true;
2747 else
2748 aImageInfo.emplace( names[n], true );
2751 // large growth factor, expecting many entries
2752 for (auto const& elem : aImageInfo)
2754 name[ 0 ] = elem.first;
2756 uno::Sequence< uno::Reference< graphic::XGraphic> > graphics;
2759 if (elem.second)
2760 graphics = m_xImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2761 else
2762 graphics = m_xParentImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2764 catch ( uno::Exception& )
2766 // can't get sequence for this name so it will not be
2767 // added to the list
2770 if ( graphics.hasElements() )
2772 Image img(graphics[0]);
2773 if (!img.GetBitmapEx().IsEmpty())
2775 m_aGraphics.push_back(graphics[0]);
2776 m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first);
2781 m_xBtnDelete->set_sensitive( false );
2782 m_xTbSymbol->SetSelectHdl( LINK(this, SvxIconSelectorDialog, SelectHdl) );
2783 m_xBtnImport->connect_clicked( LINK(this, SvxIconSelectorDialog, ImportHdl) );
2784 m_xBtnDelete->connect_clicked( LINK(this, SvxIconSelectorDialog, DeleteHdl) );
2787 SvxIconSelectorDialog::~SvxIconSelectorDialog()
2791 uno::Reference< graphic::XGraphic> SvxIconSelectorDialog::GetSelectedIcon()
2793 uno::Reference<graphic::XGraphic> result;
2795 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2797 if (nId)
2799 result = m_aGraphics[nId - 1];
2802 return result;
2805 IMPL_LINK_NOARG(SvxIconSelectorDialog, SelectHdl, SvtValueSet*, void)
2807 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2809 if (!nId)
2811 m_xBtnDelete->set_sensitive(false);
2812 return;
2815 OUString aSelImageText = m_xTbSymbol->GetItemText(nId);
2816 if (m_xImportedImageManager->hasImage(SvxConfigPageHelper::GetImageType(), aSelImageText))
2818 m_xBtnDelete->set_sensitive(true);
2820 else
2822 m_xBtnDelete->set_sensitive(false);
2826 IMPL_LINK_NOARG(SvxIconSelectorDialog, ImportHdl, weld::Button&, void)
2828 sfx2::FileDialogHelper aImportDialog(
2829 css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
2830 FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, m_xDialog.get());
2832 // disable the link checkbox in the dialog
2833 uno::Reference< css::ui::dialogs::XFilePickerControlAccess >
2834 xController( aImportDialog.GetFilePicker(), uno::UNO_QUERY);
2835 if ( xController.is() )
2837 xController->enableControl(
2838 css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK,
2839 false);
2842 aImportDialog.SetCurrentFilter(
2843 "PNG - Portable Network Graphic");
2845 if ( ERRCODE_NONE == aImportDialog.Execute() )
2847 uno::Sequence< OUString > paths = aImportDialog.GetMPath();
2848 ImportGraphics ( paths );
2852 IMPL_LINK_NOARG(SvxIconSelectorDialog, DeleteHdl, weld::Button&, void)
2854 OUString message = CuiResId( RID_SVXSTR_DELETE_ICON_CONFIRM );
2856 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xDialog.get(),
2857 VclMessageType::Warning, VclButtonsType::OkCancel,
2858 message));
2859 if (xWarn->run() == RET_OK)
2861 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2863 OUString aSelImageText = m_xTbSymbol->GetItemText( nId );
2864 uno::Sequence< OUString > URLs { aSelImageText };
2865 m_xTbSymbol->RemoveItem(nId);
2866 m_xImportedImageManager->removeImages( SvxConfigPageHelper::GetImageType(), URLs );
2867 if ( m_xImportedImageManager->isModified() )
2869 m_xImportedImageManager->store();
2874 bool SvxIconSelectorDialog::ReplaceGraphicItem(
2875 const OUString& aURL )
2877 uno::Sequence< OUString > URLs(1);
2878 uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 );
2880 uno::Reference< graphic::XGraphic > xGraphic;
2881 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
2882 aMediaProps[0].Name = "URL";
2883 aMediaProps[0].Value <<= aURL;
2885 css::awt::Size aSize;
2886 bool bOK = false;
2889 xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
2891 uno::Reference< beans::XPropertySet > props =
2892 m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
2893 uno::Any a = props->getPropertyValue( "SizePixel" );
2894 a >>= aSize;
2895 if (0 == aSize.Width || 0 == aSize.Height)
2896 return false;
2897 else
2898 bOK = true;
2900 catch ( uno::Exception& )
2902 return false;
2905 bool bResult( false );
2906 size_t nCount = m_xTbSymbol->GetItemCount();
2907 for (size_t n = 0; n < nCount; ++n)
2909 sal_uInt16 nId = m_xTbSymbol->GetItemId( n );
2911 if ( m_xTbSymbol->GetItemText( nId ) == aURL )
2915 // replace/insert image with provided URL
2916 size_t nPos = nId - 1;
2917 assert(nPos == m_xTbSymbol->GetItemPos(nId));
2918 m_xTbSymbol->RemoveItem(nId);
2919 aMediaProps[0].Value <<= aURL;
2921 Image aImage( xGraphic );
2922 if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
2924 BitmapEx aBitmap = aImage.GetBitmapEx();
2925 BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
2926 aImage = Image( aBitmapex);
2928 m_xTbSymbol->InsertItem(nId, aImage, aURL, nPos); //modify
2930 m_aGraphics[nPos] = Graphic(aImage.GetBitmapEx()).GetXGraphic();
2932 URLs[0] = aURL;
2933 aImportGraph[ 0 ] = xGraphic;
2934 m_xImportedImageManager->replaceImages( SvxConfigPageHelper::GetImageType(), URLs, aImportGraph );
2935 m_xImportedImageManager->store();
2937 bResult = true;
2938 break;
2940 catch ( css::uno::Exception& )
2942 break;
2947 return bResult;
2950 namespace
2952 OUString ReplaceIconName(const OUString& rMessage)
2954 OUString name;
2955 OUString message = CuiResId( RID_SVXSTR_REPLACE_ICON_WARNING );
2956 OUString placeholder("%ICONNAME" );
2957 sal_Int32 pos = message.indexOf( placeholder );
2958 if ( pos != -1 )
2960 name = message.replaceAt(
2961 pos, placeholder.getLength(), rMessage );
2963 return name;
2966 class SvxIconReplacementDialog
2968 private:
2969 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
2970 public:
2971 SvxIconReplacementDialog(weld::Window *pParent, const OUString& rMessage, bool bYestoAll)
2972 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning, VclButtonsType::NONE, ReplaceIconName(rMessage)))
2974 m_xQueryBox->set_title(CuiResId(RID_SVXSTR_REPLACE_ICON_CONFIRM));
2975 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Yes), 2);
2976 if (bYestoAll)
2977 m_xQueryBox->add_button(CuiResId(RID_SVXSTR_YESTOALL), 5);
2978 m_xQueryBox->add_button(GetStandardText(StandardButtonType::No), 4);
2979 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), 6);
2980 m_xQueryBox->set_default_response(2);
2982 short run() { return m_xQueryBox->run(); }
2986 void SvxIconSelectorDialog::ImportGraphics(
2987 const uno::Sequence< OUString >& rPaths )
2989 uno::Sequence< OUString > rejected( rPaths.getLength() );
2990 sal_Int32 rejectedCount = 0;
2992 sal_uInt16 ret = 0;
2993 sal_Int32 aIndex;
2994 OUString aIconName;
2996 if ( rPaths.getLength() == 1 )
2998 if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), rPaths[0] ) )
3000 aIndex = rPaths[0].lastIndexOf( '/' );
3001 aIconName = rPaths[0].copy( aIndex+1 );
3002 SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, false);
3003 ret = aDlg.run();
3004 if ( ret == 2 )
3006 ReplaceGraphicItem( rPaths[0] );
3009 else
3011 if ( !ImportGraphic( rPaths[0] ) )
3013 rejected[0] = rPaths[0];
3014 rejectedCount = 1;
3018 else
3020 OUString aSourcePath( rPaths[0] );
3021 if ( rPaths[0].lastIndexOf( '/' ) != rPaths[0].getLength() -1 )
3022 aSourcePath = rPaths[0] + "/";
3024 for ( sal_Int32 i = 1; i < rPaths.getLength(); ++i )
3026 OUString aPath = aSourcePath + rPaths[i];
3027 if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), aPath ) )
3029 aIndex = rPaths[i].lastIndexOf( '/' );
3030 aIconName = rPaths[i].copy( aIndex+1 );
3031 SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, true);
3032 ret = aDlg.run();
3033 if ( ret == 2 )
3035 ReplaceGraphicItem( aPath );
3037 else if ( ret == 5 )
3039 for ( sal_Int32 k = i; k < rPaths.getLength(); ++k )
3041 aPath = aSourcePath + rPaths[k];
3042 bool bHasReplaced = ReplaceGraphicItem( aPath );
3044 if ( !bHasReplaced )
3046 bool result = ImportGraphic( aPath );
3047 if ( !result )
3049 rejected[ rejectedCount ] = rPaths[i];
3050 ++rejectedCount;
3054 break;
3057 else
3059 bool result = ImportGraphic( aSourcePath + rPaths[i] );
3060 if ( !result )
3062 rejected[ rejectedCount ] = rPaths[i];
3063 ++rejectedCount;
3069 if ( rejectedCount != 0 )
3071 OUStringBuffer message;
3072 OUString fPath;
3073 if (rejectedCount > 1)
3074 fPath = rPaths[0].copy(8) + "/";
3075 for ( sal_Int32 i = 0; i < rejectedCount; ++i )
3077 message.append(fPath).append(rejected[i]).append("\n");
3080 SvxIconChangeDialog aDialog(m_xDialog.get(), message.makeStringAndClear());
3081 aDialog.run();
3085 bool SvxIconSelectorDialog::ImportGraphic( const OUString& aURL )
3087 bool result = false;
3089 uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
3090 aMediaProps[0].Name = "URL";
3092 uno::Reference< graphic::XGraphic > xGraphic;
3093 css::awt::Size aSize;
3094 aMediaProps[0].Value <<= aURL;
3097 uno::Reference< beans::XPropertySet > props =
3098 m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
3100 uno::Any a = props->getPropertyValue("SizePixel");
3102 xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
3103 if ( xGraphic.is() )
3105 bool bOK = true;
3107 a >>= aSize;
3108 if ( 0 == aSize.Width || 0 == aSize.Height )
3109 bOK = false;
3111 Image aImage( xGraphic );
3113 if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
3115 BitmapEx aBitmap = aImage.GetBitmapEx();
3116 BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
3117 aImage = Image( aBitmapex);
3119 if ( bOK && !!aImage )
3121 m_aGraphics.push_back(Graphic(aImage.GetBitmapEx()).GetXGraphic());
3122 m_xTbSymbol->InsertItem(m_aGraphics.size(), aImage, aURL);
3124 uno::Sequence<OUString> aImportURL { aURL };
3125 uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 );
3126 aImportGraph[ 0 ] = xGraphic;
3127 m_xImportedImageManager->insertImages( SvxConfigPageHelper::GetImageType(), aImportURL, aImportGraph );
3128 if ( m_xImportedImageManager->isModified() )
3130 m_xImportedImageManager->store();
3133 result = true;
3135 else
3137 SAL_WARN("cui.customize", "could not create Image from XGraphic");
3140 else
3142 SAL_WARN("cui.customize", "could not get query XGraphic");
3145 catch( uno::Exception const & )
3147 TOOLS_WARN_EXCEPTION("cui.customize", "Caught exception importing XGraphic");
3149 return result;
3152 /*******************************************************************************
3154 * The SvxIconChangeDialog class added for issue83555
3156 *******************************************************************************/
3157 SvxIconChangeDialog::SvxIconChangeDialog(weld::Window *pWindow, const OUString& rMessage)
3158 : MessageDialogController(pWindow, "cui/ui/iconchangedialog.ui", "IconChange", "grid")
3159 , m_xLineEditDescription(m_xBuilder->weld_text_view("addrTextview"))
3161 m_xLineEditDescription->set_size_request(m_xLineEditDescription->get_approximate_digit_width() * 48,
3162 m_xLineEditDescription->get_text_height() * 8);
3163 m_xLineEditDescription->set_text(rMessage);
3166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */