1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
28 #include <vcl/button.hxx>
29 #include <vcl/commandinfoprovider.hxx>
30 #include <vcl/edit.hxx>
31 #include <vcl/event.hxx>
32 #include <vcl/help.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/toolbox.hxx>
35 #include <vcl/weld.hxx>
36 #include <vcl/decoview.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/settings.hxx>
40 #include <sfx2/sfxhelp.hxx>
41 #include <sfx2/app.hxx>
42 #include <sfx2/sfxdlg.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/viewsh.hxx>
45 #include <sfx2/msg.hxx>
46 #include <sfx2/msgpool.hxx>
47 #include <sfx2/minfitem.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/request.hxx>
50 #include <sfx2/filedlghelper.hxx>
51 #include <sfx2/sfxsids.hrc>
52 #include <svl/stritem.hxx>
53 #include <tools/diagnose_ex.h>
54 #include <toolkit/helper/vclunohelper.hxx>
57 #include <strings.hrc>
61 #include <SvxMenuConfigPage.hxx>
62 #include <SvxToolbarConfigPage.hxx>
63 #include <SvxConfigPageHelper.hxx>
64 #include "eventdlg.hxx"
65 #include <dialmgr.hxx>
67 #include <unotools/configmgr.hxx>
68 #include <com/sun/star/container/XNameContainer.hpp>
69 #include <com/sun/star/embed/ElementModes.hpp>
70 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
71 #include <com/sun/star/frame/UnknownModuleException.hpp>
72 #include <com/sun/star/frame/XFrames.hpp>
73 #include <com/sun/star/frame/XLayoutManager.hpp>
74 #include <com/sun/star/frame/FrameSearchFlag.hpp>
75 #include <com/sun/star/frame/XController.hpp>
76 #include <com/sun/star/frame/Desktop.hpp>
77 #include <com/sun/star/frame/theUICommandDescription.hpp>
78 #include <com/sun/star/graphic/GraphicProvider.hpp>
79 #include <com/sun/star/io/IOException.hpp>
80 #include <com/sun/star/lang/IllegalAccessException.hpp>
81 #include <com/sun/star/ui/ItemType.hpp>
82 #include <com/sun/star/ui/ItemStyle.hpp>
83 #include <com/sun/star/ui/ImageManager.hpp>
84 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
85 #include <com/sun/star/ui/XUIConfiguration.hpp>
86 #include <com/sun/star/ui/XUIConfigurationListener.hpp>
87 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
88 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
89 #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
90 #include <com/sun/star/ui/XModuleUIConfigurationManager.hpp>
91 #include <com/sun/star/ui/XUIElement.hpp>
92 #include <com/sun/star/ui/UIElementType.hpp>
93 #include <com/sun/star/ui/ImageType.hpp>
94 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
95 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
96 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
97 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
98 #include <com/sun/star/util/thePathSettings.hpp>
99 #include <comphelper/documentinfo.hxx>
100 #include <comphelper/propertysequence.hxx>
101 #include <comphelper/processfactory.hxx>
103 #include <dlgname.hxx>
105 namespace uno
= com::sun::star::uno
;
106 namespace frame
= com::sun::star::frame
;
107 namespace lang
= com::sun::star::lang
;
108 namespace container
= com::sun::star::container
;
109 namespace beans
= com::sun::star::beans
;
110 namespace graphic
= com::sun::star::graphic
;
112 #if OSL_DEBUG_LEVEL > 1
114 void printPropertySet(
115 const OUString
& prefix
,
116 const uno::Reference
< beans::XPropertySet
>& xPropSet
)
118 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo
=
119 xPropSet
->getPropertySetInfo();
121 uno::Sequence
< beans::Property
> aPropDetails
=
122 xPropSetInfo
->getProperties();
124 SAL_WARN("cui", "printPropertySet: " << aPropDetails
.getLength() << " properties" );
126 for ( sal_Int32 i
= 0; i
< aPropDetails
.getLength(); ++i
)
131 uno::Any a
= xPropSet
->getPropertyValue( aPropDetails
[i
].Name
);
135 SAL_WARN("cui", prefix
<< ": Got property: " << aPropDetails
[i
].Name
<< tmp
);
137 else if ( ( a
>>= ival
) )
139 SAL_WARN("cui", prefix
<< ": Got property: " << aPropDetails
[i
].Name
<< " = " << ival
);
143 SAL_WARN("cui", prefix
<< ": Got property: " << aPropDetails
[i
].Name
<< " of type " << a
.getValueTypeName());
148 void printProperties(
149 const OUString
& prefix
,
150 const uno::Sequence
< beans::PropertyValue
>& aProp
)
152 for ( sal_Int32 i
= 0; i
< aProp
.getLength(); ++i
)
156 aProp
[i
].Value
>>= tmp
;
158 SAL_WARN("cui", prefix
<< ": Got property: " << aProp
[i
].Name
<< " = " << tmp
);
162 void printEntries(SvxEntries
* entries
)
164 for (auto const& entry
: *entries
)
166 SAL_WARN("cui", "printEntries: " << entry
->GetName());
173 SvxConfigPage::CanConfig( const OUString
& aModuleId
)
175 return !(aModuleId
== "com.sun.star.script.BasicIDE" || aModuleId
== "com.sun.star.frame.Bibliography");
178 static VclPtr
<SfxTabPage
> CreateSvxMenuConfigPage( TabPageParent pParent
, const SfxItemSet
* rSet
)
180 return VclPtr
<SvxMenuConfigPage
>::Create(pParent
, *rSet
);
183 static VclPtr
<SfxTabPage
> CreateSvxContextMenuConfigPage( TabPageParent pParent
, const SfxItemSet
* rSet
)
185 return VclPtr
<SvxMenuConfigPage
>::Create(pParent
, *rSet
, false);
188 static VclPtr
<SfxTabPage
> CreateKeyboardConfigPage( TabPageParent pParent
, const SfxItemSet
* rSet
)
190 return VclPtr
<SfxAcceleratorConfigPage
>::Create(pParent
, *rSet
);
193 static VclPtr
<SfxTabPage
> CreateSvxToolbarConfigPage( TabPageParent pParent
, const SfxItemSet
* rSet
)
195 return VclPtr
<SvxToolbarConfigPage
>::Create(pParent
, *rSet
);
198 static VclPtr
<SfxTabPage
> CreateSvxEventConfigPage( TabPageParent pParent
, const SfxItemSet
* rSet
)
200 return VclPtr
<SvxEventConfigPage
>::Create(pParent
, *rSet
, SvxEventConfigPage::EarlyInit());
203 /******************************************************************************
205 * SvxConfigDialog is the configuration dialog which is brought up from the
206 * Tools menu. It includes tabs for customizing menus, toolbars, events and
209 *****************************************************************************/
210 SvxConfigDialog::SvxConfigDialog(weld::Window
* pParent
, const SfxItemSet
* pInSet
)
211 : SfxTabDialogController(pParent
, "cui/ui/customizedialog.ui", "CustomizeDialog", pInSet
)
213 SvxConfigPageHelper::InitImageType();
215 AddTabPage("menus", CreateSvxMenuConfigPage
, nullptr);
216 AddTabPage("toolbars", CreateSvxToolbarConfigPage
, nullptr);
217 AddTabPage("contextmenus", CreateSvxContextMenuConfigPage
, nullptr);
218 AddTabPage("keyboard", CreateKeyboardConfigPage
, nullptr);
219 AddTabPage("events", CreateSvxEventConfigPage
, nullptr);
221 const SfxPoolItem
* pItem
=
222 pInSet
->GetItem( pInSet
->GetPool()->GetWhich( SID_CONFIG
) );
226 OUString text
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
228 if (text
.startsWith( ITEM_TOOLBAR_URL
) )
230 SetCurPageId("toolbars");
235 void SvxConfigDialog::SetFrame(const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
239 if (!SvxConfigPageHelper::showKeyConfigTabPage( xFrame
))
240 RemoveTabPage("keyboard");
243 void SvxConfigDialog::PageCreated(const OString
&rId
, SfxTabPage
& rPage
)
245 if (rId
== "menus" || rId
== "keyboard" ||
246 rId
== "toolbars" || rId
== "contextmenus")
248 rPage
.SetFrame(m_xFrame
);
250 else if (rId
== "events")
252 dynamic_cast< SvxEventConfigPage
& >( rPage
).LateInit( m_xFrame
);
256 /******************************************************************************
258 * The SaveInData class is used to hold data for entries in the Save In
259 * ListBox controls in the menu and toolbar tabs
261 ******************************************************************************/
263 // Initialize static variable which holds default XImageManager
264 uno::Reference
< css::ui::XImageManager
>* SaveInData::xDefaultImgMgr
= nullptr;
266 SaveInData::SaveInData(
267 const uno::Reference
< css::ui::XUIConfigurationManager
>& xCfgMgr
,
268 const uno::Reference
< css::ui::XUIConfigurationManager
>& xParentCfgMgr
,
269 const OUString
& aModuleId
,
273 bDocConfig( isDocConfig
),
275 m_xCfgMgr( xCfgMgr
),
276 m_xParentCfgMgr( xParentCfgMgr
)
278 m_aSeparatorSeq
.realloc( 1 );
279 m_aSeparatorSeq
[0].Name
= ITEM_DESCRIPTOR_TYPE
;
280 m_aSeparatorSeq
[0].Value
<<= css::ui::ItemType::SEPARATOR_LINE
;
284 uno::Reference
< css::ui::XUIConfigurationPersistence
>
285 xDocPersistence( GetConfigManager(), uno::UNO_QUERY
);
287 bReadOnly
= xDocPersistence
->isReadOnly();
290 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
292 uno::Reference
< container::XNameAccess
> xNameAccess(
293 css::frame::theUICommandDescription::get(xContext
) );
295 xNameAccess
->getByName( aModuleId
) >>= m_xCommandToLabelMap
;
297 if ( !m_xImgMgr
.is() )
299 m_xImgMgr
.set( GetConfigManager()->getImageManager(), uno::UNO_QUERY
);
302 if ( !IsDocConfig() )
304 // If this is not a document configuration then it is the settings
305 // for the module (writer, calc, impress etc.) Use this as the default
306 // XImageManager instance
307 xDefaultImgMgr
= &m_xImgMgr
;
311 // If this is a document configuration then use the module image manager
313 if ( m_xParentCfgMgr
.is() )
315 m_xParentImgMgr
.set( m_xParentCfgMgr
->getImageManager(), uno::UNO_QUERY
);
316 xDefaultImgMgr
= &m_xParentImgMgr
;
321 uno::Reference
<graphic::XGraphic
> SaveInData::GetImage(const OUString
& rCommandURL
)
323 uno::Reference
< graphic::XGraphic
> xGraphic
=
324 SvxConfigPageHelper::GetGraphic( m_xImgMgr
, rCommandURL
);
326 if (!xGraphic
.is() && xDefaultImgMgr
!= nullptr && (*xDefaultImgMgr
).is())
328 xGraphic
= SvxConfigPageHelper::GetGraphic( (*xDefaultImgMgr
), rCommandURL
);
334 bool SaveInData::PersistChanges(
335 const uno::Reference
< uno::XInterface
>& xManager
)
341 if ( xManager
.is() && !IsReadOnly() )
343 uno::Reference
< css::ui::XUIConfigurationPersistence
>
344 xConfigPersistence( xManager
, uno::UNO_QUERY
);
346 if ( xConfigPersistence
->isModified() )
348 xConfigPersistence
->store();
352 catch ( css::io::IOException
& )
360 /******************************************************************************
362 * The MenuSaveInData class extends SaveInData and provides menu specific
363 * load and store functionality.
365 ******************************************************************************/
367 // Initialize static variable which holds default Menu data
368 MenuSaveInData
* MenuSaveInData::pDefaultData
= nullptr;
370 MenuSaveInData::MenuSaveInData(
371 const uno::Reference
< css::ui::XUIConfigurationManager
>& cfgmgr
,
372 const uno::Reference
< css::ui::XUIConfigurationManager
>& xParentCfgMgr
,
373 const OUString
& aModuleId
,
376 SaveInData( cfgmgr
, xParentCfgMgr
, aModuleId
, isDocConfig
),
379 m_aDescriptorContainer(
380 ITEM_DESCRIPTOR_CONTAINER
)
384 OUString
url( ITEM_MENUBAR_URL
);
385 m_xMenuSettings
= GetConfigManager()->getSettings( url
, false );
387 catch ( container::NoSuchElementException
& )
389 // will use menu settings for the module
392 // If this is not a document configuration then it is the settings
393 // for the module (writer, calc, impress etc.). These settings should
394 // be set as the default to be used for SaveIn locations that do not
395 // have custom settings
396 if ( !IsDocConfig() )
398 SetDefaultData( this );
402 MenuSaveInData::~MenuSaveInData()
407 MenuSaveInData::GetEntries()
409 if ( pRootEntry
== nullptr )
411 pRootEntry
.reset( new SvxConfigEntry( "MainMenus", OUString(), true, /*bParentData*/false) );
413 if ( m_xMenuSettings
.is() )
415 LoadSubMenus( m_xMenuSettings
, OUString(), pRootEntry
.get(), false );
417 else if ( GetDefaultData() != nullptr )
419 // If the doc has no config settings use module config settings
420 LoadSubMenus( GetDefaultData()->m_xMenuSettings
, OUString(), pRootEntry
.get(), false );
424 return pRootEntry
->GetEntries();
428 MenuSaveInData::SetEntries( std::unique_ptr
<SvxEntries
> pNewEntries
)
430 pRootEntry
->SetEntries( std::move(pNewEntries
) );
433 void SaveInData::LoadSubMenus( const uno::Reference
< container::XIndexAccess
>& xMenuSettings
,
434 const OUString
& rBaseTitle
, SvxConfigEntry
const * pParentData
, bool bContextMenu
)
436 SvxEntries
* pEntries
= pParentData
->GetEntries();
438 // Don't access non existing menu configuration!
439 if ( !xMenuSettings
.is() )
442 for ( sal_Int32 nIndex
= 0; nIndex
< xMenuSettings
->getCount(); ++nIndex
)
444 uno::Reference
< container::XIndexAccess
> xSubMenu
;
445 OUString aCommandURL
;
448 sal_uInt16
nType( css::ui::ItemType::DEFAULT
);
451 bool bItem
= SvxConfigPageHelper::GetMenuItemData( xMenuSettings
, nIndex
,
452 aCommandURL
, aLabel
, nType
, nStyle
, xSubMenu
);
456 bool bIsUserDefined
= true;
458 if ( nType
== css::ui::ItemType::DEFAULT
)
463 a
= m_xCommandToLabelMap
->getByName( aCommandURL
);
464 bIsUserDefined
= false;
466 catch ( container::NoSuchElementException
& )
468 bIsUserDefined
= true;
471 bool bUseDefaultLabel
= false;
472 // If custom label not set retrieve it from the command
474 if ( aLabel
.isEmpty() )
476 bUseDefaultLabel
= true;
477 uno::Sequence
< beans::PropertyValue
> aPropSeq
;
478 if ( a
>>= aPropSeq
)
481 for ( sal_Int32 i
= 0; i
< aPropSeq
.getLength(); ++i
)
485 if ( aPropSeq
[i
].Name
== "PopupLabel" )
487 aPropSeq
[i
].Value
>>= aLabel
;
490 else if ( aPropSeq
[i
].Name
== "Label" )
492 aPropSeq
[i
].Value
>>= aMenuLabel
;
495 else if ( aPropSeq
[i
].Name
== "Label" )
497 aPropSeq
[i
].Value
>>= aLabel
;
501 if ( aLabel
.isEmpty() )
506 SvxConfigEntry
* pEntry
= new SvxConfigEntry(
507 aLabel
, aCommandURL
, xSubMenu
.is(), /*bParentData*/false );
509 pEntry
->SetStyle( nStyle
);
510 pEntry
->SetUserDefined( bIsUserDefined
);
511 if ( !bUseDefaultLabel
)
512 pEntry
->SetName( aLabel
);
514 pEntries
->push_back( pEntry
);
519 OUString
subMenuTitle( rBaseTitle
);
521 if ( !subMenuTitle
.isEmpty() )
523 subMenuTitle
+= aMenuSeparatorStr
;
530 subMenuTitle
+= SvxConfigPageHelper::stripHotKey( aLabel
);
532 LoadSubMenus( xSubMenu
, subMenuTitle
, pEntry
, bContextMenu
);
537 SvxConfigEntry
* pEntry
= new SvxConfigEntry
;
538 pEntry
->SetUserDefined( bIsUserDefined
);
539 pEntries
->push_back( pEntry
);
545 bool MenuSaveInData::Apply()
551 // Apply new menu bar structure to our settings container
552 m_xMenuSettings
.set( GetConfigManager()->createSettings(), uno::UNO_QUERY
);
554 uno::Reference
< container::XIndexContainer
> xIndexContainer (
555 m_xMenuSettings
, uno::UNO_QUERY
);
557 uno::Reference
< lang::XSingleComponentFactory
> xFactory (
558 m_xMenuSettings
, uno::UNO_QUERY
);
560 Apply( xIndexContainer
, xFactory
);
564 if ( GetConfigManager()->hasSettings( m_aMenuResourceURL
) )
566 GetConfigManager()->replaceSettings(
567 m_aMenuResourceURL
, m_xMenuSettings
);
571 GetConfigManager()->insertSettings(
572 m_aMenuResourceURL
, m_xMenuSettings
);
575 catch ( css::uno::Exception
& )
577 css::uno::Any
ex( cppu::getCaughtException() );
578 SAL_WARN("cui.customize", "caught some other exception saving settings " << exceptionToString(ex
));
581 SetModified( false );
583 result
= PersistChanges( GetConfigManager() );
589 void MenuSaveInData::Apply(
590 uno::Reference
< container::XIndexContainer
> const & rMenuBar
,
591 uno::Reference
< lang::XSingleComponentFactory
>& rFactory
)
593 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
595 for (auto const& entryData
: *GetEntries())
597 uno::Sequence
< beans::PropertyValue
> aPropValueSeq
=
598 SvxConfigPageHelper::ConvertSvxConfigEntry(entryData
);
600 uno::Reference
< container::XIndexContainer
> xSubMenuBar(
601 rFactory
->createInstanceWithContext( xContext
),
604 sal_Int32 nIndex
= aPropValueSeq
.getLength();
605 aPropValueSeq
.realloc( nIndex
+ 1 );
606 aPropValueSeq
[nIndex
].Name
= m_aDescriptorContainer
;
607 aPropValueSeq
[nIndex
].Value
<<= xSubMenuBar
;
608 rMenuBar
->insertByIndex(
609 rMenuBar
->getCount(), uno::Any( aPropValueSeq
));
610 ApplyMenu( xSubMenuBar
, rFactory
, entryData
);
614 void SaveInData::ApplyMenu(
615 uno::Reference
< container::XIndexContainer
> const & rMenuBar
,
616 uno::Reference
< lang::XSingleComponentFactory
>& rFactory
,
617 SvxConfigEntry
* pMenuData
)
619 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
621 for (auto const& entry
: *pMenuData
->GetEntries())
623 if (entry
->IsPopup())
625 uno::Sequence
< beans::PropertyValue
> aPropValueSeq
=
626 SvxConfigPageHelper::ConvertSvxConfigEntry(entry
);
628 uno::Reference
< container::XIndexContainer
> xSubMenuBar(
629 rFactory
->createInstanceWithContext( xContext
),
632 sal_Int32 nIndex
= aPropValueSeq
.getLength();
633 aPropValueSeq
.realloc( nIndex
+ 1 );
634 aPropValueSeq
[nIndex
].Name
= ITEM_DESCRIPTOR_CONTAINER
;
635 aPropValueSeq
[nIndex
].Value
<<= xSubMenuBar
;
637 rMenuBar
->insertByIndex(
638 rMenuBar
->getCount(), uno::Any( aPropValueSeq
));
640 ApplyMenu( xSubMenuBar
, rFactory
, entry
);
641 entry
->SetModified( false );
643 else if (entry
->IsSeparator())
645 rMenuBar
->insertByIndex(
646 rMenuBar
->getCount(), uno::Any( m_aSeparatorSeq
));
650 uno::Sequence
< beans::PropertyValue
> aPropValueSeq
=
651 SvxConfigPageHelper::ConvertSvxConfigEntry(entry
);
652 rMenuBar
->insertByIndex(
653 rMenuBar
->getCount(), uno::Any( aPropValueSeq
));
656 pMenuData
->SetModified( false );
660 MenuSaveInData::Reset()
664 GetConfigManager()->removeSettings( m_aMenuResourceURL
);
666 catch ( const css::uno::Exception
& )
669 PersistChanges( GetConfigManager() );
675 m_xMenuSettings
= GetConfigManager()->getSettings(
676 m_aMenuResourceURL
, false );
678 catch ( container::NoSuchElementException
& )
680 // will use default settings
684 ContextMenuSaveInData::ContextMenuSaveInData(
685 const css::uno::Reference
< css::ui::XUIConfigurationManager
>& xCfgMgr
,
686 const css::uno::Reference
< css::ui::XUIConfigurationManager
>& xParentCfgMgr
,
687 const OUString
& aModuleId
, bool bIsDocConfig
)
688 : SaveInData( xCfgMgr
, xParentCfgMgr
, aModuleId
, bIsDocConfig
)
690 css::uno::Reference
< css::uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
691 css::uno::Reference
< css::container::XNameAccess
> xConfig( css::ui::theWindowStateConfiguration::get( xContext
) );
692 xConfig
->getByName( aModuleId
) >>= m_xPersistentWindowState
;
695 ContextMenuSaveInData::~ContextMenuSaveInData()
699 OUString
ContextMenuSaveInData::GetUIName( const OUString
& rResourceURL
)
701 if ( m_xPersistentWindowState
.is() )
703 css::uno::Sequence
< css::beans::PropertyValue
> aProps
;
706 m_xPersistentWindowState
->getByName( rResourceURL
) >>= aProps
;
708 catch ( const css::uno::Exception
& )
711 for ( const auto& aProp
: aProps
)
713 if ( aProp
.Name
== ITEM_DESCRIPTOR_UINAME
)
716 aProp
.Value
>>= aResult
;
724 SvxEntries
* ContextMenuSaveInData::GetEntries()
728 std::unordered_map
< OUString
, bool > aMenuInfo
;
730 m_pRootEntry
.reset( new SvxConfigEntry( "ContextMenus", OUString(), true, /*bParentData*/false ) );
731 css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > aElementsInfo
;
734 aElementsInfo
= GetConfigManager()->getUIElementsInfo( css::ui::UIElementType::POPUPMENU
);
736 catch ( const css::lang::IllegalArgumentException
& )
739 for ( const auto& aElement
: aElementsInfo
)
742 for ( const auto& aElementProp
: aElement
)
744 if ( aElementProp
.Name
== ITEM_DESCRIPTOR_RESOURCEURL
)
746 aElementProp
.Value
>>= aUrl
;
751 css::uno::Reference
< css::container::XIndexAccess
> xPopupMenu
;
754 xPopupMenu
= GetConfigManager()->getSettings( aUrl
, false );
756 catch ( const css::uno::Exception
& )
759 if ( xPopupMenu
.is() )
761 // insert into std::unordered_map to filter duplicates from the parent
762 aMenuInfo
.emplace( aUrl
, true );
764 OUString aUIMenuName
= GetUIName( aUrl
);
765 if ( aUIMenuName
.isEmpty() )
766 // Menus without UI name aren't supposed to be customized.
769 SvxConfigEntry
* pEntry
= new SvxConfigEntry( aUIMenuName
, aUrl
, true, /*bParentData*/false );
771 m_pRootEntry
->GetEntries()->push_back( pEntry
);
772 LoadSubMenus( xPopupMenu
, aUIMenuName
, pEntry
, true );
776 // Retrieve also the parent menus, to make it possible to configure module menus and save them into the document.
777 css::uno::Reference
< css::ui::XUIConfigurationManager
> xParentCfgMgr
= GetParentConfigManager();
778 css::uno::Sequence
< css::uno::Sequence
< css::beans::PropertyValue
> > aParentElementsInfo
;
781 if ( xParentCfgMgr
.is() )
782 aParentElementsInfo
= xParentCfgMgr
->getUIElementsInfo( css::ui::UIElementType::POPUPMENU
);
784 catch ( const css::lang::IllegalArgumentException
& )
787 for ( const auto& aElement
: aParentElementsInfo
)
790 for ( const auto& aElementProp
: aElement
)
792 if ( aElementProp
.Name
== ITEM_DESCRIPTOR_RESOURCEURL
)
794 aElementProp
.Value
>>= aUrl
;
799 css::uno::Reference
< css::container::XIndexAccess
> xPopupMenu
;
802 if ( aMenuInfo
.find( aUrl
) == aMenuInfo
.end() )
803 xPopupMenu
= xParentCfgMgr
->getSettings( aUrl
, false );
805 catch ( const css::uno::Exception
& )
808 if ( xPopupMenu
.is() )
810 OUString aUIMenuName
= GetUIName( aUrl
);
811 if ( aUIMenuName
.isEmpty() )
814 SvxConfigEntry
* pEntry
= new SvxConfigEntry( aUIMenuName
, aUrl
, true, true );
816 m_pRootEntry
->GetEntries()->push_back( pEntry
);
817 LoadSubMenus( xPopupMenu
, aUIMenuName
, pEntry
, true );
820 std::sort( m_pRootEntry
->GetEntries()->begin(), m_pRootEntry
->GetEntries()->end(), SvxConfigPageHelper::EntrySort
);
822 return m_pRootEntry
->GetEntries();
825 void ContextMenuSaveInData::SetEntries( std::unique_ptr
<SvxEntries
> pNewEntries
)
827 m_pRootEntry
->SetEntries( std::move(pNewEntries
) );
830 bool ContextMenuSaveInData::HasURL( const OUString
& rURL
)
832 SvxEntries
* pEntries
= GetEntries();
833 for ( const auto& pEntry
: *pEntries
)
834 if ( pEntry
->GetCommand() == rURL
)
840 bool ContextMenuSaveInData::HasSettings()
842 return m_pRootEntry
&& !m_pRootEntry
->GetEntries()->empty();
845 bool ContextMenuSaveInData::Apply()
850 SvxEntries
* pEntries
= GetEntries();
851 for ( const auto& pEntry
: *pEntries
)
853 if ( pEntry
->IsModified() || SvxConfigPageHelper::SvxConfigEntryModified( pEntry
) )
855 css::uno::Reference
< css::container::XIndexContainer
> xIndexContainer( GetConfigManager()->createSettings(), css::uno::UNO_QUERY
);
856 css::uno::Reference
< css::lang::XSingleComponentFactory
> xFactory( xIndexContainer
, css::uno::UNO_QUERY
);
857 ApplyMenu( xIndexContainer
, xFactory
, pEntry
);
859 const OUString
& aUrl
= pEntry
->GetCommand();
862 if ( GetConfigManager()->hasSettings( aUrl
) )
863 GetConfigManager()->replaceSettings( aUrl
, xIndexContainer
);
865 GetConfigManager()->insertSettings( aUrl
, xIndexContainer
);
867 catch ( const css::uno::Exception
& )
871 SetModified( false );
872 return PersistChanges( GetConfigManager() );
875 void ContextMenuSaveInData::Reset()
877 SvxEntries
* pEntries
= GetEntries();
878 for ( const auto& pEntry
: *pEntries
)
882 GetConfigManager()->removeSettings( pEntry
->GetCommand() );
884 catch ( const css::uno::Exception
& e
)
886 SAL_WARN("cui.customize", "Exception caught while resetting context menus: " << e
);
889 PersistChanges( GetConfigManager() );
890 m_pRootEntry
.reset();
893 void ContextMenuSaveInData::ResetContextMenu( const SvxConfigEntry
* pEntry
)
897 GetConfigManager()->removeSettings( pEntry
->GetCommand() );
899 catch ( const css::uno::Exception
& e
)
901 SAL_WARN("cui.customize", "Exception caught while resetting context menu: " << e
);
903 PersistChanges( GetConfigManager() );
904 m_pRootEntry
.reset();
907 void SvxMenuEntriesListBox::CreateDropDown()
909 int nWidth
= m_xControl
->get_text_height() / 2;
910 m_xDropDown
->SetOutputSizePixel(Size(nWidth
, nWidth
));
911 DecorationView
aDecoView(m_xDropDown
.get());
912 aDecoView
.DrawSymbol(tools::Rectangle(Point(0, 0), Size(nWidth
, nWidth
)),
913 SymbolType::SPIN_RIGHT
, m_xDropDown
->GetTextColor(),
914 DrawSymbolFlags::NONE
);
917 /******************************************************************************
919 * SvxMenuEntriesListBox is the listbox in which the menu items for a
920 * particular menu are shown. We have a custom listbox because we need
921 * to add drag'n'drop support from the Macro Selector and within the
924 *****************************************************************************/
925 SvxMenuEntriesListBox::SvxMenuEntriesListBox(std::unique_ptr
<weld::TreeView
> xControl
, SvxConfigPage
* pPg
)
926 : m_xControl(std::move(xControl
))
927 , m_xDropDown(m_xControl
->create_virtual_device())
931 m_xControl
->connect_key_press(LINK(this, SvxMenuEntriesListBox
, KeyInputHdl
));
934 SvxMenuEntriesListBox::~SvxMenuEntriesListBox()
938 IMPL_LINK(SvxMenuEntriesListBox
, KeyInputHdl
, const KeyEvent
&, rKeyEvent
, bool)
940 vcl::KeyCode keycode
= rKeyEvent
.GetKeyCode();
942 // support DELETE for removing the current entry
943 if ( keycode
== KEY_DELETE
)
945 pPage
->DeleteSelectedContent();
947 // support CTRL+UP and CTRL+DOWN for moving selected entries
948 else if ( keycode
.GetCode() == KEY_UP
&& keycode
.IsMod1() )
950 pPage
->MoveEntry( true );
952 else if ( keycode
.GetCode() == KEY_DOWN
&& keycode
.IsMod1() )
954 pPage
->MoveEntry( false );
958 return false; // pass on to default handler
963 /******************************************************************************
965 * SvxConfigPage is the abstract base class on which the Menu and Toolbar
966 * configuration tabpages are based. It includes methods which are common to
967 * both tabpages to add, delete, move and rename items etc.
969 *****************************************************************************/
970 SvxConfigPage::SvxConfigPage(TabPageParent pParent
, const SfxItemSet
& rSet
)
971 : SfxTabPage(pParent
, "cui/ui/menuassignpage.ui", "MenuAssignPage", &rSet
)
972 , m_aUpdateDataTimer("UpdateDataTimer")
973 , bInitialised(false)
974 , pCurrentSaveInData(nullptr)
975 , m_xSearchEdit(m_xBuilder
->weld_entry("searchEntry"))
976 , m_xCommandCategoryListBox(new CommandCategoryListBox(m_xBuilder
->weld_combo_box("commandcategorylist")))
977 , m_xFunctions(new CuiConfigFunctionListBox(m_xBuilder
->weld_tree_view("functions")))
978 , m_xDescriptionFieldLb(m_xBuilder
->weld_label("descriptionlabel"))
979 , m_xDescriptionField(m_xBuilder
->weld_text_view("desc"))
980 , m_xTopLevelListBox(m_xBuilder
->weld_combo_box("toplevellist"))
981 , m_xMoveUpButton(m_xBuilder
->weld_button("up"))
982 , m_xMoveDownButton(m_xBuilder
->weld_button("down"))
983 , m_xSaveInListBox(m_xBuilder
->weld_combo_box("savein"))
984 , m_xInsertBtn(m_xBuilder
->weld_menu_button("insert"))
985 , m_xModifyBtn(m_xBuilder
->weld_menu_button("modify"))
986 , m_xResetBtn(m_xBuilder
->weld_button("defaultsbtn"))
987 , m_xAddCommandButton(m_xBuilder
->weld_button("add"))
988 , m_xRemoveCommandButton(m_xBuilder
->weld_button("remove"))
990 m_xTopLevelListBox
->connect_changed(LINK(this, SvxMenuConfigPage
, SelectElementHdl
));
992 weld::TreeView
& rTreeView
= m_xFunctions
->get_widget();
993 Size
aSize(rTreeView
.get_approximate_digit_width() * 40, rTreeView
.get_height_rows(8));
994 m_xFunctions
->set_size_request(aSize
.Width(), aSize
.Height());
995 m_xDescriptionField
->set_size_request(aSize
.Width(), m_xDescriptionField
->get_height_rows(3));
997 m_aUpdateDataTimer
.SetInvokeHandler(LINK(this, SvxConfigPage
, ImplUpdateDataHdl
));
998 m_aUpdateDataTimer
.SetDebugName( "SvxConfigPage UpdateDataTimer" );
999 m_aUpdateDataTimer
.SetTimeout(EDIT_UPDATEDATA_TIMEOUT
);
1001 m_xSearchEdit
->connect_changed(LINK(this, SvxConfigPage
, SearchUpdateHdl
));
1002 m_xSearchEdit
->connect_focus_out(LINK(this, SvxConfigPage
, FocusOut_Impl
));
1004 rTreeView
.connect_row_activated(LINK(this, SvxConfigPage
, FunctionDoubleClickHdl
));
1005 rTreeView
.connect_changed(LINK(this, SvxConfigPage
, SelectFunctionHdl
));
1008 IMPL_LINK_NOARG(SvxConfigPage
, SelectElementHdl
, weld::ComboBox
&, void)
1013 SvxConfigPage::~SvxConfigPage()
1018 void SvxConfigPage::Reset( const SfxItemSet
* )
1020 // If we haven't initialised our XMultiServiceFactory reference
1021 // then Reset is being called at the opening of the dialog.
1023 // Load menu configuration data for the module of the currently
1024 // selected document, for the currently selected document, and for
1025 // all other open documents of the same module type
1026 if ( !bInitialised
)
1029 uno::Reference
< css::ui::XUIConfigurationManager
> xCfgMgr
;
1030 uno::Reference
< css::ui::XUIConfigurationManager
> xDocCfgMgr
;
1032 uno::Reference
< uno::XComponentContext
> xContext(
1033 ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW
);
1035 m_xFrame
= GetFrame();
1036 OUString aModuleId
= GetFrameWithDefaultAndIdentify( m_xFrame
);
1038 // replace %MODULENAME in the label with the correct module name
1039 uno::Reference
< css::frame::XModuleManager2
> xModuleManager(
1040 css::frame::ModuleManager::create( xContext
));
1041 OUString aModuleName
= SvxConfigPageHelper::GetUIModuleName( aModuleId
, xModuleManager
);
1043 uno::Reference
< css::ui::XModuleUIConfigurationManagerSupplier
>
1044 xModuleCfgSupplier( css::ui::theModuleUIConfigurationManagerSupplier::get(xContext
) );
1046 // Set up data for module specific menus
1047 SaveInData
* pModuleData
= nullptr;
1052 xModuleCfgSupplier
->getUIConfigurationManager( aModuleId
);
1054 pModuleData
= CreateSaveInData( xCfgMgr
,
1055 uno::Reference
< css::ui::XUIConfigurationManager
>(),
1059 catch ( container::NoSuchElementException
& )
1063 if ( pModuleData
!= nullptr )
1065 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pModuleData
)));
1066 m_xSaveInListBox
->append(sId
, utl::ConfigManager::getProductName() + " " + aModuleName
);
1069 // try to retrieve the document based ui configuration manager
1071 uno::Reference
< frame::XController
> xController
=
1072 m_xFrame
->getController();
1073 if ( CanConfig( aModuleId
) && xController
.is() )
1075 uno::Reference
< frame::XModel
> xModel( xController
->getModel() );
1078 uno::Reference
< css::ui::XUIConfigurationManagerSupplier
>
1079 xCfgSupplier( xModel
, uno::UNO_QUERY
);
1081 if ( xCfgSupplier
.is() )
1083 xDocCfgMgr
= xCfgSupplier
->getUIConfigurationManager();
1085 aTitle
= ::comphelper::DocumentInfo::getDocumentTitle( xModel
);
1089 SaveInData
* pDocData
= nullptr;
1090 if ( xDocCfgMgr
.is() )
1092 pDocData
= CreateSaveInData( xDocCfgMgr
, xCfgMgr
, aModuleId
, true );
1094 if ( !pDocData
->IsReadOnly() )
1096 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pDocData
)));
1097 m_xSaveInListBox
->append(sId
, aTitle
);
1101 // if an item to select has been passed in (eg. the ResourceURL for a
1102 // toolbar) then try to select the SaveInData entry that has that item
1103 bool bURLToSelectFound
= false;
1104 if ( !m_aURLToSelect
.isEmpty() )
1106 if ( pDocData
&& pDocData
->HasURL( m_aURLToSelect
) )
1108 m_xSaveInListBox
->set_active(nPos
);
1109 pCurrentSaveInData
= pDocData
;
1110 bURLToSelectFound
= true;
1112 else if ( pModuleData
&& pModuleData
->HasURL( m_aURLToSelect
) )
1114 m_xSaveInListBox
->set_active(0);
1115 pCurrentSaveInData
= pModuleData
;
1116 bURLToSelectFound
= true;
1120 if ( !bURLToSelectFound
)
1122 // if the document has menu configuration settings select it
1123 // it the SaveIn listbox, otherwise select the module data
1124 if ( pDocData
!= nullptr && pDocData
->HasSettings() )
1126 m_xSaveInListBox
->set_active(nPos
);
1127 pCurrentSaveInData
= pDocData
;
1131 m_xSaveInListBox
->set_active(0);
1132 pCurrentSaveInData
= pModuleData
;
1137 DBG_ASSERT( pCurrentSaveInData
, "SvxConfigPage::Reset(): no SaveInData" );
1140 if ( CanConfig( aModuleId
) )
1142 // Load configuration for other open documents which have
1144 uno::Sequence
< uno::Reference
< frame::XFrame
> > aFrameList
;
1147 uno::Reference
< frame::XDesktop2
> xFramesSupplier
= frame::Desktop::create(
1150 uno::Reference
< frame::XFrames
> xFrames
=
1151 xFramesSupplier
->getFrames();
1153 aFrameList
= xFrames
->queryFrames(
1154 frame::FrameSearchFlag::ALL
& ~frame::FrameSearchFlag::SELF
);
1157 catch( const uno::Exception
& )
1159 DBG_UNHANDLED_EXCEPTION("cui.customize");
1162 for ( sal_Int32 i
= 0; i
< aFrameList
.getLength(); ++i
)
1164 uno::Reference
< frame::XFrame
> xf
= aFrameList
[i
];
1166 if ( xf
.is() && xf
!= m_xFrame
)
1170 aCheckId
= xModuleManager
->identify( xf
);
1171 } catch(const uno::Exception
&)
1172 { aCheckId
.clear(); }
1174 if ( aModuleId
== aCheckId
)
1176 // try to get the document based ui configuration manager
1178 uno::Reference
< frame::XController
> xController_
=
1179 xf
->getController();
1181 if ( xController_
.is() )
1183 uno::Reference
< frame::XModel
> xModel(
1184 xController_
->getModel() );
1189 css::ui::XUIConfigurationManagerSupplier
>
1190 xCfgSupplier( xModel
, uno::UNO_QUERY
);
1192 if ( xCfgSupplier
.is() )
1195 xCfgSupplier
->getUIConfigurationManager();
1197 aTitle2
= ::comphelper::DocumentInfo::getDocumentTitle( xModel
);
1201 if ( xDocCfgMgr
.is() )
1203 SaveInData
* pData
= CreateSaveInData( xDocCfgMgr
, xCfgMgr
, aModuleId
, true );
1205 if ( pData
&& !pData
->IsReadOnly() )
1207 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pData
)));
1208 m_xSaveInListBox
->append(sId
, aTitle2
);
1216 m_xSaveInListBox
->connect_changed(
1217 LINK( this, SvxConfigPage
, SelectSaveInLocation
) );
1219 bInitialised
= true;
1225 if ( QueryReset() == RET_YES
)
1227 // Reset menu configuration for currently selected SaveInData
1228 GetSaveInData()->Reset();
1235 OUString
SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference
< frame::XFrame
>& _inout_rxFrame
)
1240 uno::Reference
< uno::XComponentContext
> xContext(
1241 ::comphelper::getProcessComponentContext() );
1243 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(
1246 if ( !_inout_rxFrame
.is() )
1247 _inout_rxFrame
= xDesktop
->getActiveFrame();
1249 if ( !_inout_rxFrame
.is() )
1251 _inout_rxFrame
= xDesktop
->getCurrentFrame();
1254 if ( !_inout_rxFrame
.is() && SfxViewFrame::Current() )
1255 _inout_rxFrame
= SfxViewFrame::Current()->GetFrame().GetFrameInterface();
1257 if ( !_inout_rxFrame
.is() )
1259 SAL_WARN( "cui.customize", "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" );
1263 uno::Reference
< css::frame::XModuleManager2
> xModuleManager(
1264 css::frame::ModuleManager::create( xContext
) );
1268 sModuleID
= xModuleManager
->identify( _inout_rxFrame
);
1270 catch ( const frame::UnknownModuleException
& )
1275 catch( const uno::Exception
& )
1277 DBG_UNHANDLED_EXCEPTION("cui.customize");
1283 OUString
SvxConfigPage::GetScriptURL() const
1287 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xFunctions
->get_selected_id().toInt64());
1290 if ( ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
) ||
1291 ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
) ||
1292 ( pData
->nKind
== SfxCfgKind::GROUP_STYLES
) )
1294 result
= pData
->sCommand
;
1301 OUString
SvxConfigPage::GetSelectedDisplayName()
1303 return m_xFunctions
->get_selected_text();
1306 bool SvxConfigPage::FillItemSet( SfxItemSet
* )
1308 bool result
= false;
1310 for (int i
= 0, nCount
= m_xSaveInListBox
->get_count(); i
< nCount
; ++i
)
1313 reinterpret_cast<SaveInData
*>(m_xSaveInListBox
->get_id(i
).toInt64());
1315 result
= pData
->Apply();
1320 IMPL_LINK_NOARG(SvxConfigPage
, SelectSaveInLocation
, weld::ComboBox
&, void)
1322 pCurrentSaveInData
= reinterpret_cast<SaveInData
*>(m_xSaveInListBox
->get_active_id().toInt64());
1326 void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry
const * pToSelect
)
1328 int nSelectionPos
= m_xTopLevelListBox
->get_active();
1329 m_xTopLevelListBox
->clear();
1331 if ( GetSaveInData() && GetSaveInData()->GetEntries() )
1333 for (auto const& entryData
: *GetSaveInData()->GetEntries())
1335 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(entryData
)));
1336 m_xTopLevelListBox
->append(sId
, SvxConfigPageHelper::stripHotKey(entryData
->GetName()));
1338 if (entryData
== pToSelect
)
1339 nSelectionPos
= m_xTopLevelListBox
->get_count() - 1;
1341 AddSubMenusToUI( SvxConfigPageHelper::stripHotKey( entryData
->GetName() ), entryData
);
1347 DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" );
1348 DBG_ASSERT( GetSaveInData()->GetEntries() ,
1349 "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" );
1353 nSelectionPos
= (nSelectionPos
!= -1 && nSelectionPos
< m_xTopLevelListBox
->get_count()) ?
1354 nSelectionPos
: m_xTopLevelListBox
->get_count() - 1;
1356 m_xTopLevelListBox
->set_active(nSelectionPos
);
1360 void SvxConfigPage::AddSubMenusToUI(
1361 const OUString
& rBaseTitle
, SvxConfigEntry
const * pParentData
)
1363 for (auto const& entryData
: *pParentData
->GetEntries())
1365 if (entryData
->IsPopup())
1367 OUString subMenuTitle
= rBaseTitle
+ aMenuSeparatorStr
+ SvxConfigPageHelper::stripHotKey(entryData
->GetName());
1369 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(entryData
)));
1370 m_xTopLevelListBox
->append(sId
, subMenuTitle
);
1372 AddSubMenusToUI( subMenuTitle
, entryData
);
1377 SvxEntries
* SvxConfigPage::FindParentForChild(
1378 SvxEntries
* pRootEntries
, SvxConfigEntry
* pChildData
)
1380 for (auto const& entryData
: *pRootEntries
)
1383 if (entryData
== pChildData
)
1385 return pRootEntries
;
1387 else if (entryData
->IsPopup())
1389 SvxEntries
* result
=
1390 FindParentForChild( entryData
->GetEntries(), pChildData
);
1392 if ( result
!= nullptr )
1401 int SvxConfigPage::AddFunction(int nTarget
, bool bFront
, bool bAllowDuplicates
)
1403 OUString aURL
= GetScriptURL();
1404 SvxConfigEntry
* pParent
= GetTopLevelSelection();
1406 if ( aURL
.isEmpty() || pParent
== nullptr )
1411 OUString aDisplayName
;
1412 OUString aModuleId
= vcl::CommandInfoProvider::GetModuleIdentifier( m_xFrame
);
1414 if ( typeid(*pCurrentSaveInData
) == typeid(ContextMenuSaveInData
) )
1415 aDisplayName
= vcl::CommandInfoProvider::GetPopupLabelForCommand( aURL
, aModuleId
);
1416 else if ( typeid(*pCurrentSaveInData
) == typeid(MenuSaveInData
) )
1417 aDisplayName
= vcl::CommandInfoProvider::GetMenuLabelForCommand( aURL
, aModuleId
);
1419 aDisplayName
= vcl::CommandInfoProvider::GetLabelForCommand( aURL
, aModuleId
);
1421 SvxConfigEntry
* pNewEntryData
=
1422 new SvxConfigEntry( aDisplayName
, aURL
, false, /*bParentData*/false );
1423 pNewEntryData
->SetUserDefined();
1425 if ( aDisplayName
.isEmpty() )
1426 pNewEntryData
->SetName( GetSelectedDisplayName() );
1428 // check that this function is not already in the menu
1429 if ( !bAllowDuplicates
)
1431 for (auto const& entry
: *pParent
->GetEntries())
1433 if ( entry
->GetCommand() == pNewEntryData
->GetCommand() )
1435 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetDialogFrameWeld(),
1436 VclMessageType::Info
, VclButtonsType::Ok
, CuiResId(RID_SVXSTR_MNUCFG_ALREADY_INCLUDED
)));
1438 delete pNewEntryData
;
1444 return InsertEntry(pNewEntryData
, nTarget
, bFront
);
1447 int SvxConfigPage::InsertEntry(
1448 SvxConfigEntry
* pNewEntryData
,
1452 SvxConfigEntry
* pTopLevelSelection
= GetTopLevelSelection();
1454 if (pTopLevelSelection
== nullptr)
1457 // Grab the entries list for the currently selected menu
1458 SvxEntries
* pEntries
= pTopLevelSelection
->GetEntries();
1462 nTarget
!= -1 ? nTarget
: m_xContentsListBox
->get_selected_index();
1464 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pNewEntryData
)));
1468 pEntries
->insert( pEntries
->begin(), pNewEntryData
);
1469 m_xContentsListBox
->insert(0, sId
);
1472 else if (nCurEntry
== -1 || nCurEntry
== m_xContentsListBox
->n_children() - 1)
1474 pEntries
->push_back( pNewEntryData
);
1475 m_xContentsListBox
->insert(-1, sId
);
1476 nNewEntry
= m_xContentsListBox
->n_children() - 1;
1480 SvxConfigEntry
* pEntryData
=
1481 reinterpret_cast<SvxConfigEntry
*>(m_xContentsListBox
->get_id(nCurEntry
).toInt64());
1483 SvxEntries::iterator iter
= pEntries
->begin();
1484 SvxEntries::const_iterator end
= pEntries
->end();
1486 // Advance the iterator to the data for currently selected entry
1487 sal_uInt16 nPos
= 0;
1488 while (*iter
!= pEntryData
&& ++iter
!= end
)
1493 // Now step past it to the entry after the currently selected one
1497 // Now add the new entry to the UI and to the parent's list
1500 pEntries
->insert( iter
, pNewEntryData
);
1501 m_xContentsListBox
->insert(nPos
, sId
);
1506 if (nNewEntry
!= -1)
1508 m_xContentsListBox
->select(nNewEntry
);
1509 m_xContentsListBox
->scroll_to_row(nNewEntry
);
1511 GetSaveInData()->SetModified();
1512 GetTopLevelSelection()->SetModified();
1518 void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry
* pNewEntryData
, int nPos
, int nStartCol
)
1520 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(pNewEntryData
)));
1522 m_xContentsListBox
->set_id(nPos
, sId
);
1524 if (pNewEntryData
->IsSeparator())
1526 m_xContentsListBox
->set_text(nPos
, "----------------------------------", nStartCol
+ 1);
1530 auto xImage
= GetSaveInData()->GetImage(pNewEntryData
->GetCommand());
1532 m_xContentsListBox
->set_image(nPos
, xImage
, nStartCol
);
1533 OUString aName
= SvxConfigPageHelper::stripHotKey( pNewEntryData
->GetName() );
1534 m_xContentsListBox
->set_text(nPos
, aName
, nStartCol
+ 1);
1537 if (nStartCol
== 0) // menus
1539 if (pNewEntryData
->IsPopup() || pNewEntryData
->GetStyle() & css::ui::ItemStyle::DROP_DOWN
)
1540 m_xContentsListBox
->set_dropdown(nPos
, nStartCol
+ 2);
1542 m_xContentsListBox
->set_image(nPos
, nullptr, nStartCol
+ 2);
1546 IMPL_LINK(SvxConfigPage
, MoveHdl
, weld::Button
&, rButton
, void)
1548 MoveEntry(&rButton
== m_xMoveUpButton
.get());
1551 IMPL_LINK_NOARG(SvxConfigPage
, FunctionDoubleClickHdl
, weld::TreeView
&, void)
1553 if (m_xAddCommandButton
->get_sensitive())
1554 m_xAddCommandButton
->clicked();
1557 IMPL_LINK_NOARG(SvxConfigPage
, SelectFunctionHdl
, weld::TreeView
&, void)
1559 // Store the tooltip of the description field at first run
1560 static const OUString sDescTooltip
= m_xDescriptionField
->get_tooltip_text();
1562 // GetScriptURL() returns a non-empty string if a
1563 // valid command is selected on the left box
1564 bool bIsValidCommand
= !GetScriptURL().isEmpty();
1566 // Enable/disable Add and Remove buttons depending on current selection
1567 if (bIsValidCommand
)
1569 m_xAddCommandButton
->set_sensitive(true);
1570 m_xRemoveCommandButton
->set_sensitive(true);
1572 m_xDescriptionField
->set_text(m_xFunctions
->GetHelpText(false));
1577 m_xAddCommandButton
->set_sensitive(false);
1578 m_xRemoveCommandButton
->set_sensitive(false);
1580 m_xDescriptionField
->set_text("");
1583 // Disable the description field and its label if the local help is not installed
1584 // And inform the user via tooltips
1585 if ( !SfxHelp::IsHelpInstalled() )
1587 m_xDescriptionField
->set_sensitive(false);
1588 m_xDescriptionFieldLb
->set_sensitive(false);
1589 m_xDescriptionField
->set_tooltip_text( sDescTooltip
);
1590 m_xDescriptionFieldLb
->set_tooltip_text( sDescTooltip
);
1594 m_xDescriptionField
->set_sensitive(true);
1595 m_xDescriptionFieldLb
->set_sensitive(true);
1596 m_xDescriptionField
->set_tooltip_text("");
1597 m_xDescriptionFieldLb
->set_tooltip_text("");
1601 IMPL_LINK_NOARG(SvxConfigPage
, ImplUpdateDataHdl
, Timer
*, void)
1603 OUString
aSearchTerm(m_xSearchEdit
->get_text());
1604 m_xCommandCategoryListBox
->categorySelected(m_xFunctions
.get(), aSearchTerm
, GetSaveInData());
1607 IMPL_LINK_NOARG(SvxConfigPage
, SearchUpdateHdl
, weld::Entry
&, void)
1609 m_aUpdateDataTimer
.Start();
1612 IMPL_LINK_NOARG(SvxConfigPage
, FocusOut_Impl
, weld::Widget
&, void)
1614 if (m_aUpdateDataTimer
.IsActive())
1616 m_aUpdateDataTimer
.Stop();
1617 m_aUpdateDataTimer
.Invoke();
1621 void SvxConfigPage::MoveEntry(bool bMoveUp
)
1623 weld::TreeView
& rTreeView
= m_xContentsListBox
->get_widget();
1625 int nSourceEntry
= rTreeView
.get_selected_index();
1626 int nTargetEntry
= -1;
1629 if (nSourceEntry
== -1)
1636 // Move Up is just a Move Down with the source and target reversed
1637 nTargetEntry
= nSourceEntry
;
1638 nSourceEntry
= nTargetEntry
- 1;
1639 nToSelect
= nSourceEntry
;
1643 nTargetEntry
= nSourceEntry
+ 1;
1644 nToSelect
= nTargetEntry
;
1647 if (MoveEntryData(nSourceEntry
, nTargetEntry
))
1649 rTreeView
.swap(nSourceEntry
, nTargetEntry
);
1650 rTreeView
.select(nToSelect
);
1651 rTreeView
.scroll_to_row(nToSelect
);
1653 UpdateButtonStates();
1657 bool SvxConfigPage::MoveEntryData(int nSourceEntry
, int nTargetEntry
)
1660 if (nSourceEntry
== -1 || nTargetEntry
== -1)
1665 // Grab the entries list for the currently selected menu
1666 SvxEntries
* pEntries
= GetTopLevelSelection()->GetEntries();
1668 SvxConfigEntry
* pSourceData
=
1669 reinterpret_cast<SvxConfigEntry
*>(m_xContentsListBox
->get_id(nSourceEntry
).toInt64());
1671 SvxConfigEntry
* pTargetData
=
1672 reinterpret_cast<SvxConfigEntry
*>(m_xContentsListBox
->get_id(nTargetEntry
).toInt64());
1674 if ( pSourceData
!= nullptr && pTargetData
!= nullptr )
1676 // remove the source entry from our list
1677 SvxConfigPageHelper::RemoveEntry( pEntries
, pSourceData
);
1679 SvxEntries::iterator iter
= pEntries
->begin();
1680 SvxEntries::const_iterator end
= pEntries
->end();
1682 // advance the iterator to the position of the target entry
1683 while (*iter
!= pTargetData
&& ++iter
!= end
) ;
1685 // insert the source entry at the position after the target
1686 pEntries
->insert( ++iter
, pSourceData
);
1688 GetSaveInData()->SetModified();
1689 GetTopLevelSelection()->SetModified();
1697 SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog(
1698 weld::Window
* pParent
, SvxEntries
* entries
,
1699 SvxConfigEntry
const * selection
, bool bCreateMenu
)
1700 : GenericDialogController(pParent
, "cui/ui/movemenu.ui", "MoveMenuDialog")
1701 , m_xMenuBox(m_xBuilder
->weld_widget("namebox"))
1702 , m_xMenuNameEdit(m_xBuilder
->weld_entry("menuname"))
1703 , m_xMenuListBox(m_xBuilder
->weld_tree_view("menulist"))
1704 , m_xMoveUpButton(m_xBuilder
->weld_button("up"))
1705 , m_xMoveDownButton(m_xBuilder
->weld_button("down"))
1707 m_xMenuListBox
->set_size_request(-1, m_xMenuListBox
->get_height_rows(12));
1709 // Copy the entries list passed in
1710 if ( entries
!= nullptr )
1712 mpEntries
.reset( new SvxEntries
);
1713 for (auto const& entry
: *entries
)
1715 m_xMenuListBox
->append(OUString::number(reinterpret_cast<sal_uInt64
>(entry
)),
1716 SvxConfigPageHelper::stripHotKey(entry
->GetName()));
1717 mpEntries
->push_back(entry
);
1718 if (entry
== selection
)
1720 m_xMenuListBox
->select(m_xMenuListBox
->n_children() - 1);
1727 // Generate custom name for new menu
1728 OUString prefix
= CuiResId( RID_SVXSTR_NEW_MENU
);
1730 OUString newname
= SvxConfigPageHelper::generateCustomName( prefix
, entries
);
1731 OUString newurl
= SvxConfigPageHelper::generateCustomMenuURL( mpEntries
.get() );
1733 SvxConfigEntry
* pNewEntryData
=
1734 new SvxConfigEntry( newname
, newurl
, true, /*bParentData*/false );
1735 pNewEntryData
->SetName( newname
);
1736 pNewEntryData
->SetUserDefined();
1737 pNewEntryData
->SetMain();
1739 m_sNewMenuEntryId
= OUString::number(reinterpret_cast<sal_uInt64
>(pNewEntryData
));
1740 m_xMenuListBox
->append(m_sNewMenuEntryId
,
1741 SvxConfigPageHelper::stripHotKey(pNewEntryData
->GetName()));
1742 m_xMenuListBox
->select(m_xMenuListBox
->n_children() - 1);
1745 mpEntries
->push_back(pNewEntryData
);
1747 m_xMenuNameEdit
->set_text(newname
);
1748 m_xMenuNameEdit
->connect_changed(LINK(this, SvxMainMenuOrganizerDialog
, ModifyHdl
));
1752 // hide name label and textfield
1755 m_xDialog
->set_title(CuiResId(RID_SVXSTR_MOVE_MENU
));
1758 m_xMenuListBox
->connect_changed(LINK(this, SvxMainMenuOrganizerDialog
, SelectHdl
));
1760 m_xMoveUpButton
->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog
, MoveHdl
));
1761 m_xMoveDownButton
->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog
, MoveHdl
));
1763 UpdateButtonStates();
1766 SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog()
1770 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog
, ModifyHdl
, weld::Entry
&, void)
1772 // if the Edit control is empty do not change the name
1773 if (m_xMenuNameEdit
->get_text().isEmpty())
1778 SvxConfigEntry
* pNewEntryData
= reinterpret_cast<SvxConfigEntry
*>(m_sNewMenuEntryId
.toUInt64());
1779 pNewEntryData
->SetName(m_xMenuNameEdit
->get_text());
1781 const int nNewMenuPos
= m_xMenuListBox
->find_id(m_sNewMenuEntryId
);
1782 const int nOldSelection
= m_xMenuListBox
->get_selected_index();
1783 m_xMenuListBox
->remove(nNewMenuPos
);
1784 m_xMenuListBox
->insert(nNewMenuPos
, pNewEntryData
->GetName(), &m_sNewMenuEntryId
, nullptr, nullptr);
1785 m_xMenuListBox
->select(nOldSelection
);
1788 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog
, SelectHdl
, weld::TreeView
&, void)
1790 UpdateButtonStates();
1793 void SvxMainMenuOrganizerDialog::UpdateButtonStates()
1795 // Disable Up and Down buttons depending on current selection
1796 const int nSelected
= m_xMenuListBox
->get_selected_index();
1797 m_xMoveUpButton
->set_sensitive(nSelected
> 0);
1798 m_xMoveDownButton
->set_sensitive(nSelected
!= -1 && nSelected
< m_xMenuListBox
->n_children() - 1);
1801 IMPL_LINK( SvxMainMenuOrganizerDialog
, MoveHdl
, weld::Button
&, rButton
, void )
1803 int nSourceEntry
= m_xMenuListBox
->get_selected_index();
1804 if (nSourceEntry
== -1)
1809 if (&rButton
== m_xMoveDownButton
.get())
1811 nTargetEntry
= nSourceEntry
+ 1;
1815 // Move Up is just a Move Down with the source and target reversed
1816 nTargetEntry
= nSourceEntry
- 1;
1819 OUString sId
= m_xMenuListBox
->get_id(nSourceEntry
);
1820 OUString sEntry
= m_xMenuListBox
->get_text(nSourceEntry
);
1821 m_xMenuListBox
->remove(nSourceEntry
);
1822 m_xMenuListBox
->insert(nTargetEntry
, sEntry
, &sId
, nullptr, nullptr);
1823 m_xMenuListBox
->select(nTargetEntry
);
1825 std::swap(mpEntries
->at(nSourceEntry
), mpEntries
->at(nTargetEntry
));
1827 UpdateButtonStates();
1830 SvxConfigEntry
* SvxMainMenuOrganizerDialog::GetSelectedEntry()
1832 const int nSelected(m_xMenuListBox
->get_selected_index());
1833 if (nSelected
== -1)
1835 return reinterpret_cast<SvxConfigEntry
*>(m_xMenuListBox
->get_id(nSelected
).toUInt64());
1838 SvxConfigEntry::SvxConfigEntry( const OUString
& rDisplayName
,
1839 const OUString
& rCommandURL
, bool bPopup
, bool bParentData
)
1841 , aLabel(rDisplayName
)
1842 , aCommand(rCommandURL
)
1844 , bStrEdited( false )
1845 , bIsUserDefined( false )
1847 , bIsParentData( bParentData
)
1848 , bIsModified( false )
1849 , bIsVisible( true )
1854 mpEntries
.reset( new SvxEntries
);
1858 SvxConfigEntry::~SvxConfigEntry()
1862 for (auto const& entry
: *mpEntries
)
1869 bool SvxConfigEntry::IsMovable()
1871 return !IsPopup() || IsMain();
1874 bool SvxConfigEntry::IsDeletable()
1876 return !IsMain() || IsUserDefined();
1879 bool SvxConfigEntry::IsRenamable()
1881 return !IsMain() || IsUserDefined();
1884 ToolbarSaveInData::ToolbarSaveInData(
1885 const uno::Reference
< css::ui::XUIConfigurationManager
>& xCfgMgr
,
1886 const uno::Reference
< css::ui::XUIConfigurationManager
>& xParentCfgMgr
,
1887 const OUString
& aModuleId
,
1890 SaveInData ( xCfgMgr
, xParentCfgMgr
, aModuleId
, docConfig
),
1891 m_aDescriptorContainer ( ITEM_DESCRIPTOR_CONTAINER
)
1894 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1895 // Initialize the m_xPersistentWindowState variable which is used
1896 // to get the default properties of system toolbars such as name
1897 uno::Reference
< container::XNameAccess
> xPWSS
= css::ui::theWindowStateConfiguration::get( xContext
);
1899 xPWSS
->getByName( aModuleId
) >>= m_xPersistentWindowState
;
1902 ToolbarSaveInData::~ToolbarSaveInData()
1906 sal_Int32
ToolbarSaveInData::GetSystemStyle( const OUString
& rResourceURL
)
1908 sal_Int32 result
= 0;
1910 if ( rResourceURL
.startsWith( "private" ) &&
1911 m_xPersistentWindowState
.is() &&
1912 m_xPersistentWindowState
->hasByName( rResourceURL
) )
1916 uno::Sequence
< beans::PropertyValue
> aProps
;
1917 uno::Any
a( m_xPersistentWindowState
->getByName( rResourceURL
) );
1921 for ( sal_Int32 i
= 0; i
< aProps
.getLength(); ++i
)
1923 if ( aProps
[ i
].Name
== ITEM_DESCRIPTOR_STYLE
)
1925 aProps
[i
].Value
>>= result
;
1931 catch ( uno::Exception
& )
1933 // do nothing, a default value is returned
1940 void ToolbarSaveInData::SetSystemStyle(
1941 const uno::Reference
< frame::XFrame
>& xFrame
,
1942 const OUString
& rResourceURL
,
1945 // change the style using the API
1946 SetSystemStyle( rResourceURL
, nStyle
);
1948 // this code is a temporary hack as the UI is not updating after
1949 // changing the toolbar style via the API
1950 uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
1951 vcl::Window
*window
= nullptr;
1953 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY
);
1954 if ( xPropSet
.is() )
1956 uno::Any a
= xPropSet
->getPropertyValue( "LayoutManager" );
1957 a
>>= xLayoutManager
;
1960 if ( xLayoutManager
.is() )
1962 uno::Reference
< css::ui::XUIElement
> xUIElement
=
1963 xLayoutManager
->getElement( rResourceURL
);
1965 // check reference before we call getRealInterface. The layout manager
1966 // can only provide references for elements that have been created
1967 // before. It's possible that the current element is not available.
1968 uno::Reference
< css::awt::XWindow
> xWindow
;
1969 if ( xUIElement
.is() )
1970 xWindow
.set( xUIElement
->getRealInterface(), uno::UNO_QUERY
);
1972 window
= VCLUnoHelper::GetWindow( xWindow
).get();
1975 if ( window
!= nullptr && window
->GetType() == WindowType::TOOLBOX
)
1977 ToolBox
* toolbox
= static_cast<ToolBox
*>(window
);
1981 toolbox
->SetButtonType( ButtonType::SYMBOLONLY
);
1983 else if ( nStyle
== 1 )
1985 toolbox
->SetButtonType( ButtonType::TEXT
);
1989 toolbox
->SetButtonType( ButtonType::SYMBOLTEXT
);
1994 void ToolbarSaveInData::SetSystemStyle(
1995 const OUString
& rResourceURL
,
1998 if ( rResourceURL
.startsWith( "private" ) &&
1999 m_xPersistentWindowState
.is() &&
2000 m_xPersistentWindowState
->hasByName( rResourceURL
) )
2004 uno::Sequence
< beans::PropertyValue
> aProps
;
2006 uno::Any
a( m_xPersistentWindowState
->getByName( rResourceURL
) );
2010 for ( sal_Int32 i
= 0; i
< aProps
.getLength(); ++i
)
2012 if ( aProps
[ i
].Name
== ITEM_DESCRIPTOR_STYLE
)
2014 aProps
[ i
].Value
<<= nStyle
;
2020 uno::Reference
< container::XNameReplace
>
2021 xNameReplace( m_xPersistentWindowState
, uno::UNO_QUERY
);
2023 xNameReplace
->replaceByName( rResourceURL
, uno::Any( aProps
) );
2025 catch ( uno::Exception
& )
2027 // do nothing, a default value is returned
2028 SAL_WARN("cui.customize", "Exception setting toolbar style");
2033 OUString
ToolbarSaveInData::GetSystemUIName( const OUString
& rResourceURL
)
2037 if ( rResourceURL
.startsWith( "private" ) &&
2038 m_xPersistentWindowState
.is() &&
2039 m_xPersistentWindowState
->hasByName( rResourceURL
) )
2043 uno::Sequence
< beans::PropertyValue
> aProps
;
2044 uno::Any
a( m_xPersistentWindowState
->getByName( rResourceURL
) );
2048 for ( sal_Int32 i
= 0; i
< aProps
.getLength(); ++i
)
2050 if ( aProps
[ i
].Name
== ITEM_DESCRIPTOR_UINAME
)
2052 aProps
[ i
].Value
>>= result
;
2057 catch ( uno::Exception
& )
2059 // do nothing, an empty UIName will be returned
2063 if ( rResourceURL
.startsWith( ".uno" ) &&
2064 m_xCommandToLabelMap
.is() &&
2065 m_xCommandToLabelMap
->hasByName( rResourceURL
) )
2070 a
= m_xCommandToLabelMap
->getByName( rResourceURL
);
2072 uno::Sequence
< beans::PropertyValue
> aPropSeq
;
2073 if ( a
>>= aPropSeq
)
2075 for ( sal_Int32 i
= 0; i
< aPropSeq
.getLength(); ++i
)
2077 if ( aPropSeq
[i
].Name
== ITEM_DESCRIPTOR_LABEL
)
2079 aPropSeq
[i
].Value
>>= result
;
2084 catch ( uno::Exception
& )
2086 // not a system command name
2093 SvxEntries
* ToolbarSaveInData::GetEntries()
2095 typedef std::unordered_map
<OUString
, bool > ToolbarInfo
;
2097 ToolbarInfo aToolbarInfo
;
2099 if ( pRootEntry
== nullptr )
2102 pRootEntry
.reset( new SvxConfigEntry( "MainToolbars", OUString(), true, /*bParentData*/false) );
2104 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > info
=
2105 GetConfigManager()->getUIElementsInfo(
2106 css::ui::UIElementType::TOOLBAR
);
2108 for ( sal_Int32 i
= 0; i
< info
.getLength(); ++i
)
2110 uno::Sequence
< beans::PropertyValue
> props
= info
[ i
];
2113 OUString systemname
;
2116 for ( sal_Int32 j
= 0; j
< props
.getLength(); ++j
)
2118 if ( props
[ j
].Name
== ITEM_DESCRIPTOR_RESOURCEURL
)
2120 props
[ j
].Value
>>= url
;
2121 systemname
= url
.copy( url
.lastIndexOf( '/' ) + 1 );
2123 else if ( props
[ j
].Name
== ITEM_DESCRIPTOR_UINAME
)
2125 props
[ j
].Value
>>= uiname
;
2131 uno::Reference
< container::XIndexAccess
> xToolbarSettings
=
2132 GetConfigManager()->getSettings( url
, false );
2134 if ( uiname
.isEmpty() )
2136 // try to get the name from m_xPersistentWindowState
2137 uiname
= GetSystemUIName( url
);
2139 if ( uiname
.isEmpty() )
2141 uiname
= systemname
;
2145 SvxConfigEntry
* pEntry
= new SvxConfigEntry(
2146 uiname
, url
, true, /*bParentData*/false );
2149 pEntry
->SetStyle( GetSystemStyle( url
) );
2152 // insert into std::unordered_map to filter duplicates from the parent
2153 aToolbarInfo
.emplace( systemname
, true );
2155 OUString
custom(CUSTOM_TOOLBAR_STR
);
2156 if ( systemname
.startsWith( custom
) )
2158 pEntry
->SetUserDefined();
2162 pEntry
->SetUserDefined( false );
2165 pRootEntry
->GetEntries()->push_back( pEntry
);
2167 LoadToolbar( xToolbarSettings
, pEntry
);
2169 catch ( container::NoSuchElementException
& )
2171 // TODO, handle resourceURL with no settings
2175 uno::Reference
< css::ui::XUIConfigurationManager
> xParentCfgMgr
= GetParentConfigManager();
2176 if ( xParentCfgMgr
.is() )
2178 // Retrieve also the parent toolbars to make it possible
2179 // to configure module toolbars and save them into the document
2181 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > info_
=
2182 xParentCfgMgr
->getUIElementsInfo(
2183 css::ui::UIElementType::TOOLBAR
);
2185 for ( sal_Int32 i
= 0; i
< info_
.getLength(); ++i
)
2187 uno::Sequence
< beans::PropertyValue
> props
= info_
[ i
];
2190 OUString systemname
;
2193 for ( sal_Int32 j
= 0; j
< props
.getLength(); ++j
)
2195 if ( props
[ j
].Name
== ITEM_DESCRIPTOR_RESOURCEURL
)
2197 props
[ j
].Value
>>= url
;
2198 systemname
= url
.copy( url
.lastIndexOf( '/' ) + 1 );
2200 else if ( props
[ j
].Name
== ITEM_DESCRIPTOR_UINAME
)
2202 props
[ j
].Value
>>= uiname
;
2206 // custom toolbars of the parent are not visible in the document layer
2207 OUString
custom(CUSTOM_TOOLBAR_STR
);
2208 if ( systemname
.startsWith( custom
) )
2211 // check if toolbar is already in the document layer
2212 ToolbarInfo::const_iterator pIter
= aToolbarInfo
.find( systemname
);
2213 if ( pIter
== aToolbarInfo
.end() )
2215 aToolbarInfo
.emplace( systemname
, true );
2219 uno::Reference
< container::XIndexAccess
> xToolbarSettings
=
2220 xParentCfgMgr
->getSettings( url
, false );
2222 if ( uiname
.isEmpty() )
2224 // try to get the name from m_xPersistentWindowState
2225 uiname
= GetSystemUIName( url
);
2227 if ( uiname
.isEmpty() )
2229 uiname
= systemname
;
2233 SvxConfigEntry
* pEntry
= new SvxConfigEntry(
2234 uiname
, url
, true, true );
2237 pEntry
->SetStyle( GetSystemStyle( url
) );
2239 if ( systemname
.startsWith( custom
) )
2241 pEntry
->SetUserDefined();
2245 pEntry
->SetUserDefined( false );
2248 pRootEntry
->GetEntries()->push_back( pEntry
);
2250 LoadToolbar( xToolbarSettings
, pEntry
);
2252 catch ( container::NoSuchElementException
& )
2254 // TODO, handle resourceURL with no settings
2260 std::sort( GetEntries()->begin(), GetEntries()->end(), SvxConfigPageHelper::EntrySort
);
2263 return pRootEntry
->GetEntries();
2267 ToolbarSaveInData::SetEntries( std::unique_ptr
<SvxEntries
> pNewEntries
)
2269 pRootEntry
->SetEntries( std::move(pNewEntries
) );
2273 ToolbarSaveInData::HasURL( const OUString
& rURL
)
2275 for (auto const& entry
: *GetEntries())
2277 if (entry
->GetCommand() == rURL
)
2279 return !entry
->IsParentData();
2285 bool ToolbarSaveInData::HasSettings()
2287 // return true if there is at least one toolbar entry
2288 return !GetEntries()->empty();
2291 void ToolbarSaveInData::Reset()
2293 // reset each toolbar by calling removeSettings for its toolbar URL
2294 for (auto const& entry
: *GetEntries())
2298 const OUString
& url
= entry
->GetCommand();
2299 GetConfigManager()->removeSettings( url
);
2301 catch ( uno::Exception
& )
2303 // error occurred removing the settings
2304 // TODO - add error dialog in future?
2308 // persist changes to toolbar storage
2309 PersistChanges( GetConfigManager() );
2311 // now delete the root SvxConfigEntry the next call to GetEntries()
2312 // causes it to be reinitialised
2315 // reset all icons to default
2318 GetImageManager()->reset();
2319 PersistChanges( GetImageManager() );
2321 catch ( uno::Exception
& )
2323 SAL_WARN("cui.customize", "Error resetting all icons when resetting toolbars");
2327 bool ToolbarSaveInData::Apply()
2329 // toolbar changes are instantly applied
2333 void ToolbarSaveInData::ApplyToolbar(
2334 uno::Reference
< container::XIndexContainer
> const & rToolbarBar
,
2335 uno::Reference
< lang::XSingleComponentFactory
>& rFactory
,
2336 SvxConfigEntry
const * pToolbarData
)
2338 uno::Reference
<uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
2340 for (auto const& entry
: *pToolbarData
->GetEntries())
2342 if (entry
->IsPopup())
2344 uno::Sequence
< beans::PropertyValue
> aPropValueSeq
=
2345 SvxConfigPageHelper::ConvertToolbarEntry(entry
);
2347 uno::Reference
< container::XIndexContainer
> xSubMenuBar(
2348 rFactory
->createInstanceWithContext( xContext
),
2351 sal_Int32 nIndex
= aPropValueSeq
.getLength();
2352 aPropValueSeq
.realloc( nIndex
+ 1 );
2353 aPropValueSeq
[nIndex
].Name
= m_aDescriptorContainer
;
2354 aPropValueSeq
[nIndex
].Value
<<= xSubMenuBar
;
2355 rToolbarBar
->insertByIndex(
2356 rToolbarBar
->getCount(), uno::Any( aPropValueSeq
));
2358 ApplyToolbar(xSubMenuBar
, rFactory
, entry
);
2360 else if (entry
->IsSeparator())
2362 rToolbarBar
->insertByIndex(
2363 rToolbarBar
->getCount(), uno::Any( m_aSeparatorSeq
));
2367 uno::Sequence
< beans::PropertyValue
> aPropValueSeq
=
2368 SvxConfigPageHelper::ConvertToolbarEntry(entry
);
2370 rToolbarBar
->insertByIndex(
2371 rToolbarBar
->getCount(), uno::Any( aPropValueSeq
));
2376 void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry
* pToolbar
)
2378 // Apply new toolbar structure to our settings container
2379 uno::Reference
< container::XIndexAccess
> xSettings(
2380 GetConfigManager()->createSettings(), uno::UNO_QUERY
);
2382 uno::Reference
< container::XIndexContainer
> xIndexContainer (
2383 xSettings
, uno::UNO_QUERY
);
2385 uno::Reference
< lang::XSingleComponentFactory
> xFactory (
2386 xSettings
, uno::UNO_QUERY
);
2388 ApplyToolbar( xIndexContainer
, xFactory
, pToolbar
);
2390 uno::Reference
< beans::XPropertySet
> xProps(
2391 xSettings
, uno::UNO_QUERY
);
2393 if ( pToolbar
->IsUserDefined() )
2395 xProps
->setPropertyValue(
2396 ITEM_DESCRIPTOR_UINAME
,
2397 uno::Any( pToolbar
->GetName() ) );
2402 if ( GetConfigManager()->hasSettings( pToolbar
->GetCommand() ) )
2404 GetConfigManager()->replaceSettings(
2405 pToolbar
->GetCommand(), xSettings
);
2409 GetConfigManager()->insertSettings(
2410 pToolbar
->GetCommand(), xSettings
);
2411 if ( pToolbar
->IsParentData() )
2412 pToolbar
->SetParentData( false );
2415 catch ( css::uno::Exception
const & )
2417 css::uno::Any
ex( cppu::getCaughtException() );
2418 SAL_WARN("cui.customize", "caught exception saving settings " << exceptionToString(ex
));
2421 PersistChanges( GetConfigManager() );
2424 void ToolbarSaveInData::CreateToolbar( SvxConfigEntry
* pToolbar
)
2426 // show the new toolbar in the UI also
2427 uno::Reference
< container::XIndexAccess
>
2428 xSettings( GetConfigManager()->createSettings(), uno::UNO_QUERY
);
2430 uno::Reference
< beans::XPropertySet
>
2431 xPropertySet( xSettings
, uno::UNO_QUERY
);
2433 xPropertySet
->setPropertyValue(
2434 ITEM_DESCRIPTOR_UINAME
,
2435 uno::Any( pToolbar
->GetName() ) );
2439 GetConfigManager()->insertSettings( pToolbar
->GetCommand(), xSettings
);
2441 catch ( css::uno::Exception
const & )
2443 css::uno::Any
ex( cppu::getCaughtException() );
2444 SAL_WARN("cui.customize", "caught exception saving settings " << exceptionToString(ex
));
2447 GetEntries()->push_back( pToolbar
);
2449 PersistChanges( GetConfigManager() );
2452 void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry
* pToolbar
)
2456 OUString url
= pToolbar
->GetCommand();
2457 GetConfigManager()->removeSettings( url
);
2458 SvxConfigPageHelper::RemoveEntry( GetEntries(), pToolbar
);
2461 PersistChanges( GetConfigManager() );
2463 // remove the persistent window state data
2464 css::uno::Reference
< css::container::XNameContainer
> xNameContainer(
2465 m_xPersistentWindowState
, css::uno::UNO_QUERY_THROW
);
2467 xNameContainer
->removeByName( url
);
2469 catch ( uno::Exception
& )
2471 // error occurred removing the settings
2475 void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry
* pToolbar
)
2477 OUString url
= pToolbar
->GetCommand();
2479 // Restore of toolbar is done by removing it from
2480 // its configuration manager and then getting it again
2481 bool bParentToolbar
= pToolbar
->IsParentData();
2483 // Cannot restore parent toolbar
2484 if ( bParentToolbar
)
2489 GetConfigManager()->removeSettings( url
);
2490 pToolbar
->GetEntries()->clear();
2491 PersistChanges( GetConfigManager() );
2493 catch ( uno::Exception
& )
2495 // if an error occurs removing the settings then just return
2499 // Now reload the toolbar settings
2502 uno::Reference
< container::XIndexAccess
> xToolbarSettings
;
2503 if ( IsDocConfig() )
2505 xToolbarSettings
= GetParentConfigManager()->getSettings( url
, false );
2506 pToolbar
->SetParentData();
2509 xToolbarSettings
= GetConfigManager()->getSettings( url
, false );
2511 LoadToolbar( xToolbarSettings
, pToolbar
);
2513 // After reloading, ensure that the icon is reset of each entry
2515 uno::Sequence
< OUString
> aURLSeq( 1 );
2516 for (auto const& entry
: *pToolbar
->GetEntries())
2518 aURLSeq
[ 0 ] = entry
->GetCommand();
2522 GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq
);
2524 catch ( uno::Exception
& )
2526 SAL_WARN("cui.customize", "Error restoring icon when resetting toolbar");
2529 PersistChanges( GetImageManager() );
2531 catch ( container::NoSuchElementException
& )
2533 // cannot find the resource URL after removing it
2534 // so no entry will appear in the toolbar list
2538 void ToolbarSaveInData::LoadToolbar(
2539 const uno::Reference
< container::XIndexAccess
>& xToolbarSettings
,
2540 SvxConfigEntry
const * pParentData
)
2542 SvxEntries
* pEntries
= pParentData
->GetEntries();
2544 for ( sal_Int32 nIndex
= 0; nIndex
< xToolbarSettings
->getCount(); ++nIndex
)
2546 OUString aCommandURL
;
2551 sal_uInt16
nType( css::ui::ItemType::DEFAULT
);
2553 bool bItem
= SvxConfigPageHelper::GetToolbarItemData( xToolbarSettings
, nIndex
, aCommandURL
,
2554 aLabel
, nType
, bIsVisible
, nStyle
);
2558 bool bIsUserDefined
= true;
2560 if ( nType
== css::ui::ItemType::DEFAULT
)
2565 a
= m_xCommandToLabelMap
->getByName( aCommandURL
);
2566 bIsUserDefined
= false;
2568 catch ( container::NoSuchElementException
& )
2570 bIsUserDefined
= true;
2573 bool bUseDefaultLabel
= false;
2574 // If custom label not set retrieve it from the command
2576 if ( aLabel
.isEmpty() )
2578 bUseDefaultLabel
= true;
2579 uno::Sequence
< beans::PropertyValue
> aPropSeq
;
2580 if ( a
>>= aPropSeq
)
2582 for ( sal_Int32 i
= 0; i
< aPropSeq
.getLength(); ++i
)
2584 if ( aPropSeq
[i
].Name
== "Name" )
2586 aPropSeq
[i
].Value
>>= aLabel
;
2593 SvxConfigEntry
* pEntry
= new SvxConfigEntry(
2594 aLabel
, aCommandURL
, false, /*bParentData*/false );
2596 pEntry
->SetUserDefined( bIsUserDefined
);
2597 pEntry
->SetVisible( bIsVisible
);
2598 pEntry
->SetStyle( nStyle
);
2600 if ( !bUseDefaultLabel
)
2601 pEntry
->SetName( aLabel
);
2603 pEntries
->push_back( pEntry
);
2607 SvxConfigEntry
* pEntry
= new SvxConfigEntry
;
2608 pEntry
->SetUserDefined( bIsUserDefined
);
2609 pEntries
->push_back( pEntry
);
2615 SvxNewToolbarDialog::SvxNewToolbarDialog(weld::Window
* pWindow
, const OUString
& rName
)
2616 : GenericDialogController(pWindow
, "cui/ui/newtoolbardialog.ui", "NewToolbarDialog")
2617 , m_xEdtName(m_xBuilder
->weld_entry("edit"))
2618 , m_xBtnOK(m_xBuilder
->weld_button("ok"))
2619 , m_xSaveInListBox(m_xBuilder
->weld_combo_box("savein"))
2621 m_xEdtName
->set_text(rName
);
2622 m_xEdtName
->select_region(0, -1);
2625 SvxNewToolbarDialog::~SvxNewToolbarDialog()
2629 /*******************************************************************************
2631 * The SvxIconSelectorDialog class
2633 *******************************************************************************/
2634 SvxIconSelectorDialog::SvxIconSelectorDialog(weld::Window
*pWindow
,
2635 const uno::Reference
< css::ui::XImageManager
>& rXImageManager
,
2636 const uno::Reference
< css::ui::XImageManager
>& rXParentImageManager
)
2637 : GenericDialogController(pWindow
, "cui/ui/iconselectordialog.ui", "IconSelector")
2638 , m_xImageManager(rXImageManager
)
2639 , m_xParentImageManager(rXParentImageManager
)
2640 , m_xTbSymbol(new SvtValueSet(m_xBuilder
->weld_scrolled_window("symbolswin")))
2641 , m_xTbSymbolWin(new weld::CustomWeld(*m_xBuilder
, "symbolsToolbar", *m_xTbSymbol
))
2642 , m_xFtNote(m_xBuilder
->weld_label("noteLabel"))
2643 , m_xBtnImport(m_xBuilder
->weld_button("importButton"))
2644 , m_xBtnDelete(m_xBuilder
->weld_button("deleteButton"))
2646 typedef std::unordered_map
< OUString
, bool > ImageInfo
;
2648 m_nExpectedSize
= 16;
2649 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE
)
2650 m_nExpectedSize
= 24;
2651 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32
)
2652 m_nExpectedSize
= 32;
2654 if ( m_nExpectedSize
!= 16 )
2656 m_xFtNote
->set_label(SvxConfigPageHelper::replaceSixteen(m_xFtNote
->get_label(), m_nExpectedSize
));
2659 m_xTbSymbol
->SetStyle(m_xTbSymbol
->GetStyle() | WB_ITEMBORDER
| WB_VSCROLL
);
2660 m_xTbSymbol
->SetColCount(11);
2661 m_xTbSymbol
->SetLineCount(5);
2662 m_xTbSymbol
->SetItemWidth(m_nExpectedSize
);
2663 m_xTbSymbol
->SetItemHeight(m_nExpectedSize
);
2664 m_xTbSymbol
->SetExtraSpacing(6);
2665 Size
aSize(m_xTbSymbol
->CalcWindowSizePixel(Size(m_nExpectedSize
, m_nExpectedSize
), 11, 5));
2666 m_xTbSymbol
->set_size_request(aSize
.Width(), aSize
.Height());
2668 uno::Reference
< uno::XComponentContext
> xComponentContext
=
2669 ::comphelper::getProcessComponentContext();
2671 m_xGraphProvider
.set( graphic::GraphicProvider::create( xComponentContext
) );
2673 uno::Reference
< css::util::XPathSettings
> xPathSettings
=
2674 css::util::thePathSettings::get( xComponentContext
);
2677 OUString aDirectory
= xPathSettings
->getUserConfig();
2679 sal_Int32 aCount
= aDirectory
.getLength();
2683 sal_Unicode aChar
= aDirectory
[ aCount
-1 ];
2691 m_xBtnImport
->set_sensitive(false);
2694 aDirectory
+= "soffice.cfg/import";
2696 uno::Reference
< lang::XSingleServiceFactory
> xStorageFactory(
2697 css::embed::FileSystemStorageFactory::create( xComponentContext
) );
2699 uno::Sequence
< uno::Any
> aArgs( 2 );
2700 aArgs
[ 0 ] <<= aDirectory
;
2701 aArgs
[ 1 ] <<= css::embed::ElementModes::READWRITE
;
2703 uno::Reference
< css::embed::XStorage
> xStorage(
2704 xStorageFactory
->createInstanceWithArguments( aArgs
), uno::UNO_QUERY
);
2706 uno::Sequence
<uno::Any
> aProp(comphelper::InitAnyPropertySequence(
2708 {"UserConfigStorage", uno::Any(xStorage
)},
2709 {"OpenMode", uno::Any(css::embed::ElementModes::READWRITE
)}
2711 m_xImportedImageManager
= css::ui::ImageManager::create( xComponentContext
);
2712 m_xImportedImageManager
->initialize(aProp
);
2714 ImageInfo aImageInfo1
;
2715 uno::Sequence
< OUString
> names
;
2716 if ( m_xImportedImageManager
.is() )
2718 names
= m_xImportedImageManager
->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2719 for ( sal_Int32 n
= 0; n
< names
.getLength(); ++n
)
2720 aImageInfo1
.emplace( names
[n
], false );
2723 uno::Sequence
< OUString
> name( 1 );
2724 for (auto const& elem
: aImageInfo1
)
2726 name
[ 0 ] = elem
.first
;
2727 uno::Sequence
< uno::Reference
< graphic::XGraphic
> > graphics
= m_xImportedImageManager
->getImages( SvxConfigPageHelper::GetImageType(), name
);
2728 if ( graphics
.getLength() > 0 )
2730 m_aGraphics
.push_back(graphics
[0]);
2731 Image
img(graphics
[0]);
2732 m_xTbSymbol
->InsertItem(m_aGraphics
.size(), img
, elem
.first
);
2736 ImageInfo aImageInfo
;
2738 if ( m_xParentImageManager
.is() )
2740 names
= m_xParentImageManager
->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2741 for ( sal_Int32 n
= 0; n
< names
.getLength(); ++n
)
2742 aImageInfo
.emplace( names
[n
], false );
2745 names
= m_xImageManager
->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2746 for ( sal_Int32 n
= 0; n
< names
.getLength(); ++n
)
2748 ImageInfo::iterator pIter
= aImageInfo
.find( names
[n
] );
2749 if ( pIter
!= aImageInfo
.end() )
2750 pIter
->second
= true;
2752 aImageInfo
.emplace( names
[n
], true );
2755 // large growth factor, expecting many entries
2756 for (auto const& elem
: aImageInfo
)
2758 name
[ 0 ] = elem
.first
;
2760 uno::Sequence
< uno::Reference
< graphic::XGraphic
> > graphics
;
2764 graphics
= m_xImageManager
->getImages( SvxConfigPageHelper::GetImageType(), name
);
2766 graphics
= m_xParentImageManager
->getImages( SvxConfigPageHelper::GetImageType(), name
);
2768 catch ( uno::Exception
& )
2770 // can't get sequence for this name so it will not be
2771 // added to the list
2774 if ( graphics
.getLength() > 0 )
2776 Image
img(graphics
[0]);
2777 if (!img
.GetBitmapEx().IsEmpty())
2779 m_aGraphics
.push_back(graphics
[0]);
2780 m_xTbSymbol
->InsertItem(m_aGraphics
.size(), img
, elem
.first
);
2785 m_xBtnDelete
->set_sensitive( false );
2786 m_xTbSymbol
->SetSelectHdl( LINK(this, SvxIconSelectorDialog
, SelectHdl
) );
2787 m_xBtnImport
->connect_clicked( LINK(this, SvxIconSelectorDialog
, ImportHdl
) );
2788 m_xBtnDelete
->connect_clicked( LINK(this, SvxIconSelectorDialog
, DeleteHdl
) );
2791 SvxIconSelectorDialog::~SvxIconSelectorDialog()
2795 uno::Reference
< graphic::XGraphic
> SvxIconSelectorDialog::GetSelectedIcon()
2797 uno::Reference
<graphic::XGraphic
> result
;
2799 sal_uInt16 nId
= m_xTbSymbol
->GetSelectedItemId();
2803 result
= m_aGraphics
[nId
- 1];
2809 IMPL_LINK_NOARG(SvxIconSelectorDialog
, SelectHdl
, SvtValueSet
*, void)
2811 sal_uInt16 nId
= m_xTbSymbol
->GetSelectedItemId();
2815 m_xBtnDelete
->set_sensitive(false);
2819 OUString aSelImageText
= m_xTbSymbol
->GetItemText(nId
);
2820 if (m_xImportedImageManager
->hasImage(SvxConfigPageHelper::GetImageType(), aSelImageText
))
2822 m_xBtnDelete
->set_sensitive(true);
2826 m_xBtnDelete
->set_sensitive(false);
2830 IMPL_LINK_NOARG(SvxIconSelectorDialog
, ImportHdl
, weld::Button
&, void)
2832 sfx2::FileDialogHelper
aImportDialog(
2833 css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW
,
2834 FileDialogFlags::Graphic
| FileDialogFlags::MultiSelection
, m_xDialog
.get());
2836 // disable the link checkbox in the dialog
2837 uno::Reference
< css::ui::dialogs::XFilePickerControlAccess
>
2838 xController( aImportDialog
.GetFilePicker(), uno::UNO_QUERY
);
2839 if ( xController
.is() )
2841 xController
->enableControl(
2842 css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK
,
2846 aImportDialog
.SetCurrentFilter(
2847 "PNG - Portable Network Graphic");
2849 if ( ERRCODE_NONE
== aImportDialog
.Execute() )
2851 uno::Sequence
< OUString
> paths
= aImportDialog
.GetMPath();
2852 ImportGraphics ( paths
);
2856 IMPL_LINK_NOARG(SvxIconSelectorDialog
, DeleteHdl
, weld::Button
&, void)
2858 OUString message
= CuiResId( RID_SVXSTR_DELETE_ICON_CONFIRM
);
2860 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(m_xDialog
.get(),
2861 VclMessageType::Warning
, VclButtonsType::OkCancel
,
2863 if (xWarn
->run() == RET_OK
)
2865 sal_uInt16 nId
= m_xTbSymbol
->GetSelectedItemId();
2867 OUString aSelImageText
= m_xTbSymbol
->GetItemText( nId
);
2868 uno::Sequence
< OUString
> URLs
{ aSelImageText
};
2869 m_xTbSymbol
->RemoveItem(nId
);
2870 m_xImportedImageManager
->removeImages( SvxConfigPageHelper::GetImageType(), URLs
);
2871 uno::Reference
< css::ui::XUIConfigurationPersistence
>
2872 xConfigPersistence( m_xImportedImageManager
, uno::UNO_QUERY
);
2873 if ( xConfigPersistence
.is() && xConfigPersistence
->isModified() )
2875 xConfigPersistence
->store();
2880 bool SvxIconSelectorDialog::ReplaceGraphicItem(
2881 const OUString
& aURL
)
2883 uno::Sequence
< OUString
> URLs(1);
2884 uno::Sequence
< uno::Reference
<graphic::XGraphic
> > aImportGraph( 1 );
2885 uno::Reference
< css::ui::XUIConfigurationPersistence
>
2886 xConfigPer( m_xImportedImageManager
, uno::UNO_QUERY
);
2888 uno::Reference
< graphic::XGraphic
> xGraphic
;
2889 uno::Sequence
< beans::PropertyValue
> aMediaProps( 1 );
2890 aMediaProps
[0].Name
= "URL";
2891 aMediaProps
[0].Value
<<= aURL
;
2893 css::awt::Size aSize
;
2897 xGraphic
= m_xGraphProvider
->queryGraphic( aMediaProps
);
2899 uno::Reference
< beans::XPropertySet
> props
=
2900 m_xGraphProvider
->queryGraphicDescriptor( aMediaProps
);
2901 uno::Any a
= props
->getPropertyValue( "SizePixel" );
2903 if (0 == aSize
.Width
|| 0 == aSize
.Height
)
2908 catch ( uno::Exception
& )
2913 bool bResult( false );
2914 size_t nCount
= m_xTbSymbol
->GetItemCount();
2915 for (size_t n
= 0; n
< nCount
; ++n
)
2917 sal_uInt16 nId
= m_xTbSymbol
->GetItemId( n
);
2919 if ( m_xTbSymbol
->GetItemText( nId
) == aURL
)
2923 // replace/insert image with provided URL
2924 size_t nPos
= nId
- 1;
2925 assert(nPos
== m_xTbSymbol
->GetItemPos(nId
));
2926 m_xTbSymbol
->RemoveItem(nId
);
2927 aMediaProps
[0].Value
<<= aURL
;
2929 Image
aImage( xGraphic
);
2930 if ( bOK
&& ((aSize
.Width
!= m_nExpectedSize
) || (aSize
.Height
!= m_nExpectedSize
)) )
2932 BitmapEx aBitmap
= aImage
.GetBitmapEx();
2933 BitmapEx aBitmapex
= BitmapEx::AutoScaleBitmap(aBitmap
, m_nExpectedSize
);
2934 aImage
= Image( aBitmapex
);
2936 m_xTbSymbol
->InsertItem(nId
, aImage
, aURL
, nPos
); //modify
2938 m_aGraphics
[nPos
] = Graphic(aImage
.GetBitmapEx()).GetXGraphic();
2941 aImportGraph
[ 0 ] = xGraphic
;
2942 m_xImportedImageManager
->replaceImages( SvxConfigPageHelper::GetImageType(), URLs
, aImportGraph
);
2943 xConfigPer
->store();
2948 catch ( css::uno::Exception
& )
2960 OUString
ReplaceIconName(const OUString
& rMessage
)
2963 OUString message
= CuiResId( RID_SVXSTR_REPLACE_ICON_WARNING
);
2964 OUString
placeholder("%ICONNAME" );
2965 sal_Int32 pos
= message
.indexOf( placeholder
);
2968 name
= message
.replaceAt(
2969 pos
, placeholder
.getLength(), rMessage
);
2974 class SvxIconReplacementDialog
2977 std::unique_ptr
<weld::MessageDialog
> m_xQueryBox
;
2979 SvxIconReplacementDialog(weld::Window
*pParent
, const OUString
& rMessage
, bool bYestoAll
)
2980 : m_xQueryBox(Application::CreateMessageDialog(pParent
, VclMessageType::Warning
, VclButtonsType::NONE
, ReplaceIconName(rMessage
)))
2982 m_xQueryBox
->set_title(CuiResId(RID_SVXSTR_REPLACE_ICON_CONFIRM
));
2983 m_xQueryBox
->add_button(Button::GetStandardText(StandardButtonType::Yes
), 2);
2985 m_xQueryBox
->add_button(CuiResId(RID_SVXSTR_YESTOALL
), 5);
2986 m_xQueryBox
->add_button(Button::GetStandardText(StandardButtonType::No
), 4);
2987 m_xQueryBox
->add_button(Button::GetStandardText(StandardButtonType::Cancel
), 6);
2988 m_xQueryBox
->set_default_response(2);
2990 short run() { return m_xQueryBox
->run(); }
2994 void SvxIconSelectorDialog::ImportGraphics(
2995 const uno::Sequence
< OUString
>& rPaths
)
2997 uno::Sequence
< OUString
> rejected( rPaths
.getLength() );
2998 sal_Int32 rejectedCount
= 0;
3004 if ( rPaths
.getLength() == 1 )
3006 if ( m_xImportedImageManager
->hasImage( SvxConfigPageHelper::GetImageType(), rPaths
[0] ) )
3008 aIndex
= rPaths
[0].lastIndexOf( '/' );
3009 aIconName
= rPaths
[0].copy( aIndex
+1 );
3010 SvxIconReplacementDialog
aDlg(m_xDialog
.get(), aIconName
, false);
3014 ReplaceGraphicItem( rPaths
[0] );
3019 if ( !ImportGraphic( rPaths
[0] ) )
3021 rejected
[0] = rPaths
[0];
3028 OUString
aSourcePath( rPaths
[0] );
3029 if ( rPaths
[0].lastIndexOf( '/' ) != rPaths
[0].getLength() -1 )
3030 aSourcePath
= rPaths
[0] + "/";
3032 for ( sal_Int32 i
= 1; i
< rPaths
.getLength(); ++i
)
3034 OUString aPath
= aSourcePath
+ rPaths
[i
];
3035 if ( m_xImportedImageManager
->hasImage( SvxConfigPageHelper::GetImageType(), aPath
) )
3037 aIndex
= rPaths
[i
].lastIndexOf( '/' );
3038 aIconName
= rPaths
[i
].copy( aIndex
+1 );
3039 SvxIconReplacementDialog
aDlg(m_xDialog
.get(), aIconName
, true);
3043 ReplaceGraphicItem( aPath
);
3045 else if ( ret
== 5 )
3047 for ( sal_Int32 k
= i
; k
< rPaths
.getLength(); ++k
)
3049 aPath
= aSourcePath
+ rPaths
[k
];
3050 bool bHasReplaced
= ReplaceGraphicItem( aPath
);
3052 if ( !bHasReplaced
)
3054 bool result
= ImportGraphic( aPath
);
3057 rejected
[ rejectedCount
] = rPaths
[i
];
3067 bool result
= ImportGraphic( aSourcePath
+ rPaths
[i
] );
3070 rejected
[ rejectedCount
] = rPaths
[i
];
3077 if ( rejectedCount
!= 0 )
3079 OUStringBuffer message
;
3081 if (rejectedCount
> 1)
3082 fPath
= rPaths
[0].copy(8) + "/";
3083 for ( sal_Int32 i
= 0; i
< rejectedCount
; ++i
)
3085 message
.append(fPath
).append(rejected
[i
]).append("\n");
3088 SvxIconChangeDialog
aDialog(m_xDialog
.get(), message
.makeStringAndClear());
3093 bool SvxIconSelectorDialog::ImportGraphic( const OUString
& aURL
)
3095 bool result
= false;
3097 uno::Sequence
< beans::PropertyValue
> aMediaProps( 1 );
3098 aMediaProps
[0].Name
= "URL";
3100 uno::Reference
< graphic::XGraphic
> xGraphic
;
3101 css::awt::Size aSize
;
3102 aMediaProps
[0].Value
<<= aURL
;
3105 uno::Reference
< beans::XPropertySet
> props
=
3106 m_xGraphProvider
->queryGraphicDescriptor( aMediaProps
);
3108 uno::Any a
= props
->getPropertyValue("SizePixel");
3110 xGraphic
= m_xGraphProvider
->queryGraphic( aMediaProps
);
3111 if ( xGraphic
.is() )
3116 if ( 0 == aSize
.Width
|| 0 == aSize
.Height
)
3119 Image
aImage( xGraphic
);
3121 if ( bOK
&& ((aSize
.Width
!= m_nExpectedSize
) || (aSize
.Height
!= m_nExpectedSize
)) )
3123 BitmapEx aBitmap
= aImage
.GetBitmapEx();
3124 BitmapEx aBitmapex
= BitmapEx::AutoScaleBitmap(aBitmap
, m_nExpectedSize
);
3125 aImage
= Image( aBitmapex
);
3127 if ( bOK
&& !!aImage
)
3129 m_aGraphics
.push_back(Graphic(aImage
.GetBitmapEx()).GetXGraphic());
3130 m_xTbSymbol
->InsertItem(m_aGraphics
.size(), aImage
, aURL
);
3132 uno::Sequence
<OUString
> aImportURL
{ aURL
};
3133 uno::Sequence
< uno::Reference
<graphic::XGraphic
> > aImportGraph( 1 );
3134 aImportGraph
[ 0 ] = xGraphic
;
3135 m_xImportedImageManager
->insertImages( SvxConfigPageHelper::GetImageType(), aImportURL
, aImportGraph
);
3136 uno::Reference
< css::ui::XUIConfigurationPersistence
>
3137 xConfigPersistence( m_xImportedImageManager
, uno::UNO_QUERY
);
3139 if ( xConfigPersistence
.is() && xConfigPersistence
->isModified() )
3141 xConfigPersistence
->store();
3148 SAL_WARN("cui.customize", "could not create Image from XGraphic");
3153 SAL_WARN("cui.customize", "could not get query XGraphic");
3156 catch( uno::Exception
const & )
3158 css::uno::Any
ex( cppu::getCaughtException() );
3159 SAL_WARN("cui.customize", "Caught exception importing XGraphic: " << exceptionToString(ex
));
3164 /*******************************************************************************
3166 * The SvxIconChangeDialog class added for issue83555
3168 *******************************************************************************/
3169 SvxIconChangeDialog::SvxIconChangeDialog(weld::Window
*pWindow
, const OUString
& rMessage
)
3170 : MessageDialogController(pWindow
, "cui/ui/iconchangedialog.ui", "IconChange", "grid")
3171 , m_xLineEditDescription(m_xBuilder
->weld_text_view("addrTextview"))
3173 m_xLineEditDescription
->set_size_request(m_xLineEditDescription
->get_approximate_digit_width() * 48,
3174 m_xLineEditDescription
->get_text_height() * 8);
3175 m_xLineEditDescription
->set_text(rMessage
);
3178 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */