1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <cassert>
24 #include <stdlib.h>
25 #include <typeinfo>
26
27 #include <utility>
28 #include <vcl/stdtext.hxx>
29 #include <vcl/commandinfoprovider.hxx>
30 #include <vcl/event.hxx>
31 #include <vcl/graph.hxx>
32 #include <vcl/graphicfilter.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
39 #include <sfx2/minfitem.hxx>
40 #include <sfx2/sfxhelp.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/filedlghelper.hxx>
43 #include <sfx2/sfxsids.hrc>
44 #include <svl/stritem.hxx>
45 #include <rtl/ustrbuf.hxx>
46 #include <tools/debug.hxx>
47 #include <comphelper/diagnose_ex.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49
50 #include <algorithm>
51 #include <strings.hrc>
52
53 #include <acccfg.hxx>
54 #include <cfg.hxx>
55 #include <CustomNotebookbarGenerator.hxx>
56 #include <SvxMenuConfigPage.hxx>
57 #include <SvxToolbarConfigPage.hxx>
58 #include <SvxNotebookbarConfigPage.hxx>
59 #include <SvxConfigPageHelper.hxx>
60 #include "eventdlg.hxx"
61 #include <dialmgr.hxx>
62
63 #include <unotools/configmgr.hxx>
64 #include <com/sun/star/container/XNameContainer.hpp>
65 #include <com/sun/star/embed/ElementModes.hpp>
66 #include <com/sun/star/embed/FileSystemStorageFactory.hpp>
67 #include <com/sun/star/frame/ModuleManager.hpp>
68 #include <com/sun/star/frame/XFrames.hpp>
69 #include <com/sun/star/frame/XLayoutManager.hpp>
70 #include <com/sun/star/frame/FrameSearchFlag.hpp>
71 #include <com/sun/star/frame/XController.hpp>
72 #include <com/sun/star/frame/Desktop.hpp>
73 #include <com/sun/star/frame/theUICommandDescription.hpp>
74 #include <com/sun/star/graphic/GraphicProvider.hpp>
75 #include <com/sun/star/io/IOException.hpp>
76 #include <com/sun/star/ui/ItemType.hpp>
77 #include <com/sun/star/ui/ItemStyle.hpp>
78 #include <com/sun/star/ui/ImageManager.hpp>
79 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
80 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
81 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
82 #include <com/sun/star/ui/XUIElement.hpp>
83 #include <com/sun/star/ui/UIElementType.hpp>
84 #include <com/sun/star/ui/ImageType.hpp>
85 #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
86 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
87 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
88 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
89 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
90 #include <com/sun/star/util/thePathSettings.hpp>
91 #include <comphelper/documentinfo.hxx>
92 #include <comphelper/propertysequence.hxx>
93 #include <comphelper/propertyvalue.hxx>
94 #include <comphelper/processfactory.hxx>
95 #include <config_features.h>
96
97 namespace uno = com::sun::star::uno;
98 namespace frame = com::sun::star::frame;
99 namespace lang = com::sun::star::lang;
100 namespace container = com::sun::star::container;
101 namespace beans = com::sun::star::beans;
102 namespace graphic = com::sun::star::graphic;
103
104 #if OSL_DEBUG_LEVEL > 1
105
printPropertySet(const OUString & prefix,const uno::Reference<beans::XPropertySet> & xPropSet)106 void printPropertySet(
107 const OUString& prefix,
108 const uno::Reference< beans::XPropertySet >& xPropSet )
109 {
110 uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
111 xPropSet->getPropertySetInfo();
112
113 const uno::Sequence< beans::Property >& aPropDetails =
114 xPropSetInfo->getProperties();
115
116 SAL_WARN("cui", "printPropertySet: " << aPropDetails.getLength() << " properties" );
117
118 for ( beans::Property const & aPropDetail : aPropDetails )
119 {
120 OUString tmp;
121 sal_Int32 ival;
122
123 uno::Any a = xPropSet->getPropertyValue( aPropDetail.Name );
124
125 if ( a >>= tmp )
126 {
127 SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << tmp);
128 }
129 else if ( ( a >>= ival ) )
130 {
131 SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << " = " << ival);
132 }
133 else
134 {
135 SAL_WARN("cui", prefix << ": Got property: " << aPropDetail.Name << " of type " << a.getValueTypeName());
136 }
137 }
138 }
139
printProperties(const OUString & prefix,const uno::Sequence<beans::PropertyValue> & aProp)140 void printProperties(
141 const OUString& prefix,
142 const uno::Sequence< beans::PropertyValue >& aProp )
143 {
144 for (beans::PropertyValue const & aPropVal : aProp)
145 {
146 OUString tmp;
147
148 aPropVal.Value >>= tmp;
149
150 SAL_WARN("cui", prefix << ": Got property: " << aPropVal.Name << " = " << tmp);
151 }
152 }
153
printEntries(SvxEntries * entries)154 void printEntries(SvxEntries* entries)
155 {
156 for (auto const& entry : *entries)
157 {
158 SAL_WARN("cui", "printEntries: " << entry->GetName());
159 }
160 }
161
162 #endif
163
164 bool
CanConfig(std::u16string_view aModuleId)165 SvxConfigPage::CanConfig( std::u16string_view aModuleId )
166 {
167 return aModuleId != u"com.sun.star.script.BasicIDE" && aModuleId != u"com.sun.star.frame.Bibliography";
168 }
169
CreateSvxMenuConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)170 static std::unique_ptr<SfxTabPage> CreateSvxMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
171 {
172 return std::make_unique<SvxMenuConfigPage>(pPage, pController, *rSet);
173 }
174
CreateSvxContextMenuConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)175 static std::unique_ptr<SfxTabPage> CreateSvxContextMenuConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
176 {
177 return std::make_unique<SvxMenuConfigPage>(pPage, pController, *rSet, false);
178 }
179
CreateKeyboardConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)180 static std::unique_ptr<SfxTabPage> CreateKeyboardConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
181 {
182 return std::make_unique<SfxAcceleratorConfigPage>(pPage, pController, *rSet);
183 }
184
CreateSvxNotebookbarConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)185 static std::unique_ptr<SfxTabPage> CreateSvxNotebookbarConfigPage(weld::Container* pPage, weld::DialogController* pController,
186 const SfxItemSet* rSet)
187 {
188 return std::make_unique<SvxNotebookbarConfigPage>(pPage, pController, *rSet);
189 }
190
CreateSvxToolbarConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)191 static std::unique_ptr<SfxTabPage> CreateSvxToolbarConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
192 {
193 return std::make_unique<SvxToolbarConfigPage>(pPage, pController, *rSet);
194 }
195
CreateSvxEventConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rSet)196 static std::unique_ptr<SfxTabPage> CreateSvxEventConfigPage( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet )
197 {
198 return std::make_unique<SvxEventConfigPage>(pPage, pController, *rSet, SvxEventConfigPage::EarlyInit());
199 }
200
201 /******************************************************************************
202 *
203 * SvxConfigDialog is the configuration dialog which is brought up from the
204 * Tools menu. It includes tabs for customizing menus, toolbars, events and
205 * key bindings.
206 *
207 *****************************************************************************/
SvxConfigDialog(weld::Window * pParent,const SfxItemSet * pInSet)208 SvxConfigDialog::SvxConfigDialog(weld::Window * pParent, const SfxItemSet* pInSet)
209 : SfxTabDialogController(pParent, u"cui/ui/customizedialog.ui"_ustr, u"CustomizeDialog"_ustr, pInSet)
210 {
211 SvxConfigPageHelper::InitImageType();
212
213 AddTabPage(u"menus"_ustr, CreateSvxMenuConfigPage, nullptr);
214 AddTabPage(u"toolbars"_ustr, CreateSvxToolbarConfigPage, nullptr);
215 AddTabPage(u"notebookbar"_ustr, CreateSvxNotebookbarConfigPage, nullptr);
216 AddTabPage(u"contextmenus"_ustr, CreateSvxContextMenuConfigPage, nullptr);
217 AddTabPage(u"keyboard"_ustr, CreateKeyboardConfigPage, nullptr);
218 AddTabPage(u"events"_ustr, CreateSvxEventConfigPage, nullptr);
219
220 if (const SfxPoolItem* pItem = pInSet->GetItem(SID_CONFIG))
221 {
222 OUString text = static_cast<const SfxStringItem*>(pItem)->GetValue();
223 if (text.startsWith( ITEM_TOOLBAR_URL ) )
224 SetCurPageId(u"toolbars"_ustr);
225 else if (text.startsWith( ITEM_EVENT_URL) )
226 SetCurPageId(u"events"_ustr);
227 }
228 #if HAVE_FEATURE_SCRIPTING
229 else if (pInSet->GetItemIfSet(SID_MACROINFO))
230 {
231 // for the "assign" button in the Basic Macros chooser automatically switch
232 // to the keyboard tab in which this macro will be pre-selected for assigning
233 // to a keystroke
234 SetCurPageId(u"keyboard"_ustr);
235 }
236 #endif
237 }
238
ActivatePage(const OUString & rPage)239 void SvxConfigDialog::ActivatePage(const OUString& rPage)
240 {
241 SfxTabDialogController::ActivatePage(rPage);
242 GetResetButton()->set_visible(rPage != "keyboard");
243 }
244
SetFrame(const css::uno::Reference<css::frame::XFrame> & xFrame)245 void SvxConfigDialog::SetFrame(const css::uno::Reference<css::frame::XFrame>& xFrame)
246 {
247 m_xFrame = xFrame;
248 OUString aModuleId = SvxConfigPage::GetFrameWithDefaultAndIdentify(m_xFrame);
249
250 if (aModuleId != "com.sun.star.text.TextDocument" &&
251 aModuleId != "com.sun.star.sheet.SpreadsheetDocument" &&
252 aModuleId != "com.sun.star.presentation.PresentationDocument" &&
253 aModuleId != "com.sun.star.drawing.DrawingDocument")
254 RemoveTabPage(u"notebookbar"_ustr);
255
256 if (aModuleId == "com.sun.star.frame.StartModule")
257 RemoveTabPage(u"keyboard"_ustr);
258 }
259
PageCreated(const OUString & rId,SfxTabPage & rPage)260 void SvxConfigDialog::PageCreated(const OUString &rId, SfxTabPage& rPage)
261 {
262 if (rId == "menus" || rId == "keyboard" || rId == "notebookbar"
263 || rId == "toolbars" || rId == "contextmenus")
264 {
265 rPage.SetFrame(m_xFrame);
266 }
267 else if (rId == "events")
268 {
269 dynamic_cast< SvxEventConfigPage& >( rPage ).LateInit( m_xFrame );
270 }
271 }
272
273 /******************************************************************************
274 *
275 * The SaveInData class is used to hold data for entries in the Save In
276 * ListBox controls in the menu and toolbar tabs
277 *
278 ******************************************************************************/
279
280 // Initialize static variable which holds default XImageManager
281 uno::Reference< css::ui::XImageManager>* SaveInData::xDefaultImgMgr = nullptr;
282
SaveInData(uno::Reference<css::ui::XUIConfigurationManager> xCfgMgr,uno::Reference<css::ui::XUIConfigurationManager> xParentCfgMgr,const OUString & aModuleId,bool isDocConfig)283 SaveInData::SaveInData(
284 uno::Reference< css::ui::XUIConfigurationManager > xCfgMgr,
285 uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr,
286 const OUString& aModuleId,
287 bool isDocConfig )
288 :
289 bModified( false ),
290 bDocConfig( isDocConfig ),
291 bReadOnly( false ),
292 m_xCfgMgr(std::move( xCfgMgr )),
293 m_xParentCfgMgr(std::move( xParentCfgMgr )),
294 m_aSeparatorSeq{ comphelper::makePropertyValue(ITEM_DESCRIPTOR_TYPE,
295 css::ui::ItemType::SEPARATOR_LINE) }
296 {
297 if ( bDocConfig )
298 {
299 uno::Reference< css::ui::XUIConfigurationPersistence >
300 xDocPersistence( GetConfigManager(), uno::UNO_QUERY );
301
302 bReadOnly = xDocPersistence->isReadOnly();
303 }
304
305 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
306
307 uno::Reference< container::XNameAccess > xNameAccess(
308 css::frame::theUICommandDescription::get(xContext) );
309
310 xNameAccess->getByName( aModuleId ) >>= m_xCommandToLabelMap;
311
312 if ( !m_xImgMgr.is() )
313 {
314 m_xImgMgr.set( GetConfigManager()->getImageManager(), uno::UNO_QUERY );
315 }
316
317 if ( !IsDocConfig() )
318 {
319 // If this is not a document configuration then it is the settings
320 // for the module (writer, calc, impress etc.) Use this as the default
321 // XImageManager instance
322 xDefaultImgMgr = &m_xImgMgr;
323 }
324 else
325 {
326 // If this is a document configuration then use the module image manager
327 // as default.
328 if ( m_xParentCfgMgr.is() )
329 {
330 m_xParentImgMgr.set( m_xParentCfgMgr->getImageManager(), uno::UNO_QUERY );
331 xDefaultImgMgr = &m_xParentImgMgr;
332 }
333 }
334 }
335
GetImage(const OUString & rCommandURL)336 uno::Reference<graphic::XGraphic> SaveInData::GetImage(const OUString& rCommandURL)
337 {
338 uno::Reference< graphic::XGraphic > xGraphic =
339 SvxConfigPageHelper::GetGraphic( m_xImgMgr, rCommandURL );
340
341 if (!xGraphic.is() && xDefaultImgMgr != nullptr && (*xDefaultImgMgr).is())
342 {
343 xGraphic = SvxConfigPageHelper::GetGraphic( (*xDefaultImgMgr), rCommandURL );
344 }
345
346 return xGraphic;
347 }
348
PersistChanges(const uno::Reference<uno::XInterface> & xManager)349 bool SaveInData::PersistChanges(
350 const uno::Reference< uno::XInterface >& xManager )
351 {
352 bool result = true;
353
354 try
355 {
356 if ( xManager.is() && !IsReadOnly() )
357 {
358 uno::Reference< css::ui::XUIConfigurationPersistence >
359 xConfigPersistence( xManager, uno::UNO_QUERY );
360
361 if ( xConfigPersistence->isModified() )
362 {
363 xConfigPersistence->store();
364 }
365 }
366 }
367 catch ( css::io::IOException& )
368 {
369 result = false;
370 }
371
372 return result;
373 }
374
375 /******************************************************************************
376 *
377 * The MenuSaveInData class extends SaveInData and provides menu specific
378 * load and store functionality.
379 *
380 ******************************************************************************/
381
382 // Initialize static variable which holds default Menu data
383 MenuSaveInData* MenuSaveInData::pDefaultData = nullptr;
384
MenuSaveInData(const uno::Reference<css::ui::XUIConfigurationManager> & cfgmgr,const uno::Reference<css::ui::XUIConfigurationManager> & xParentCfgMgr,const OUString & aModuleId,bool isDocConfig)385 MenuSaveInData::MenuSaveInData(
386 const uno::Reference< css::ui::XUIConfigurationManager >& cfgmgr,
387 const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
388 const OUString& aModuleId,
389 bool isDocConfig )
390 :
391 SaveInData( cfgmgr, xParentCfgMgr, aModuleId, isDocConfig ),
392 m_aMenuResourceURL(
393 ITEM_MENUBAR_URL ),
394 m_aDescriptorContainer(
395 ITEM_DESCRIPTOR_CONTAINER )
396 {
397 try
398 {
399 m_xMenuSettings = GetConfigManager()->getSettings( ITEM_MENUBAR_URL, false );
400 }
401 catch ( container::NoSuchElementException& )
402 {
403 // will use menu settings for the module
404 }
405
406 // If this is not a document configuration then it is the settings
407 // for the module (writer, calc, impress etc.). These settings should
408 // be set as the default to be used for SaveIn locations that do not
409 // have custom settings
410 if ( !IsDocConfig() )
411 {
412 SetDefaultData( this );
413 }
414 }
415
~MenuSaveInData()416 MenuSaveInData::~MenuSaveInData()
417 {
418 }
419
420 SvxEntries*
GetEntries()421 MenuSaveInData::GetEntries()
422 {
423 if ( pRootEntry == nullptr )
424 {
425 pRootEntry.reset( new SvxConfigEntry( u"MainMenus"_ustr, OUString(), true, /*bParentData*/false) );
426
427 if ( m_xMenuSettings.is() )
428 {
429 LoadSubMenus( m_xMenuSettings, OUString(), pRootEntry.get(), false );
430 }
431 else if ( GetDefaultData() != nullptr )
432 {
433 // If the doc has no config settings use module config settings
434 LoadSubMenus( GetDefaultData()->m_xMenuSettings, OUString(), pRootEntry.get(), false );
435 }
436 }
437
438 return pRootEntry->GetEntries();
439 }
440
441 void
SetEntries(std::unique_ptr<SvxEntries> pNewEntries)442 MenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
443 {
444 pRootEntry->SetEntries( std::move(pNewEntries) );
445 }
446
LoadSubMenus(const uno::Reference<container::XIndexAccess> & xMenuSettings,const OUString & rBaseTitle,SvxConfigEntry const * pParentData,bool bContextMenu)447 void SaveInData::LoadSubMenus( const uno::Reference< container::XIndexAccess >& xMenuSettings,
448 const OUString& rBaseTitle, SvxConfigEntry const * pParentData, bool bContextMenu )
449 {
450 SvxEntries* pEntries = pParentData->GetEntries();
451
452 // Don't access non existing menu configuration!
453 if ( !xMenuSettings.is() )
454 return;
455
456 for ( sal_Int32 nIndex = 0; nIndex < xMenuSettings->getCount(); ++nIndex )
457 {
458 uno::Reference< container::XIndexAccess > xSubMenu;
459 OUString aCommandURL;
460 OUString aLabel;
461
462 sal_uInt16 nType( css::ui::ItemType::DEFAULT );
463 sal_Int32 nStyle(0);
464
465 bool bItem = SvxConfigPageHelper::GetMenuItemData( xMenuSettings, nIndex,
466 aCommandURL, aLabel, nType, nStyle, xSubMenu );
467
468 if ( bItem )
469 {
470 bool bIsUserDefined = true;
471
472 if ( nType == css::ui::ItemType::DEFAULT )
473 {
474 uno::Any a;
475 try
476 {
477 a = m_xCommandToLabelMap->getByName( aCommandURL );
478 bIsUserDefined = false;
479 }
480 catch ( container::NoSuchElementException& )
481 {
482 bIsUserDefined = true;
483 }
484
485 bool bUseDefaultLabel = false;
486 // If custom label not set retrieve it from the command
487 // to info service
488 if ( aLabel.isEmpty() )
489 {
490 bUseDefaultLabel = true;
491 uno::Sequence< beans::PropertyValue > aPropSeq;
492 if ( a >>= aPropSeq )
493 {
494 OUString aMenuLabel;
495 for (const beans::PropertyValue& prop : aPropSeq)
496 {
497 if ( bContextMenu )
498 {
499 if ( prop.Name == "PopupLabel" )
500 {
501 prop.Value >>= aLabel;
502 break;
503 }
504 else if ( prop.Name == "Label" )
505 {
506 prop.Value >>= aMenuLabel;
507 }
508 }
509 else if ( prop.Name == "Label" )
510 {
511 prop.Value >>= aLabel;
512 break;
513 }
514 }
515 if ( aLabel.isEmpty() )
516 aLabel = aMenuLabel;
517 }
518 }
519
520 SvxConfigEntry* pEntry = new SvxConfigEntry(
521 aLabel, aCommandURL, xSubMenu.is(), /*bParentData*/false );
522
523 pEntry->SetStyle( nStyle );
524 pEntry->SetUserDefined( bIsUserDefined );
525 if ( !bUseDefaultLabel )
526 pEntry->SetName( aLabel );
527
528 pEntries->push_back( pEntry );
529
530 if ( xSubMenu.is() )
531 {
532 // popup menu
533 OUString subMenuTitle( rBaseTitle );
534
535 if ( !subMenuTitle.isEmpty() )
536 {
537 subMenuTitle += aMenuSeparatorStr;
538 }
539 else
540 {
541 pEntry->SetMain();
542 }
543
544 subMenuTitle += SvxConfigPageHelper::stripHotKey( aLabel );
545
546 LoadSubMenus( xSubMenu, subMenuTitle, pEntry, bContextMenu );
547 }
548 }
549 else
550 {
551 SvxConfigEntry* pEntry = new SvxConfigEntry;
552 pEntry->SetUserDefined( bIsUserDefined );
553 pEntries->push_back( pEntry );
554 }
555 }
556 }
557 }
558
Apply()559 bool MenuSaveInData::Apply()
560 {
561 bool result = false;
562
563 if ( IsModified() )
564 {
565 // Apply new menu bar structure to our settings container
566 m_xMenuSettings = GetConfigManager()->createSettings();
567
568 uno::Reference< container::XIndexContainer > xIndexContainer (
569 m_xMenuSettings, uno::UNO_QUERY );
570
571 uno::Reference< lang::XSingleComponentFactory > xFactory (
572 m_xMenuSettings, uno::UNO_QUERY );
573
574 Apply( xIndexContainer, xFactory );
575
576 try
577 {
578 if ( GetConfigManager()->hasSettings( m_aMenuResourceURL ) )
579 {
580 GetConfigManager()->replaceSettings(
581 m_aMenuResourceURL, m_xMenuSettings );
582 }
583 else
584 {
585 GetConfigManager()->insertSettings(
586 m_aMenuResourceURL, m_xMenuSettings );
587 }
588 }
589 catch ( css::uno::Exception& )
590 {
591 TOOLS_WARN_EXCEPTION("cui.customize", "caught some other exception saving settings");
592 }
593
594 SetModified( false );
595
596 result = PersistChanges( GetConfigManager() );
597 }
598
599 return result;
600 }
601
Apply(uno::Reference<container::XIndexContainer> const & rMenuBar,uno::Reference<lang::XSingleComponentFactory> & rFactory)602 void MenuSaveInData::Apply(
603 uno::Reference< container::XIndexContainer > const & rMenuBar,
604 uno::Reference< lang::XSingleComponentFactory >& rFactory )
605 {
606 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
607
608 for (auto const& entryData : *GetEntries())
609 {
610 uno::Sequence< beans::PropertyValue > aPropValueSeq =
611 SvxConfigPageHelper::ConvertSvxConfigEntry(entryData);
612
613 uno::Reference< container::XIndexContainer > xSubMenuBar(
614 rFactory->createInstanceWithContext( xContext ),
615 uno::UNO_QUERY );
616
617 sal_Int32 nIndex = aPropValueSeq.getLength();
618 aPropValueSeq.realloc( nIndex + 1 );
619 auto pPropValueSeq = aPropValueSeq.getArray();
620 pPropValueSeq[nIndex].Name = m_aDescriptorContainer;
621 pPropValueSeq[nIndex].Value <<= xSubMenuBar;
622 rMenuBar->insertByIndex(
623 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
624 ApplyMenu( xSubMenuBar, rFactory, entryData );
625 }
626 }
627
ApplyMenu(uno::Reference<container::XIndexContainer> const & rMenuBar,uno::Reference<lang::XSingleComponentFactory> & rFactory,SvxConfigEntry * pMenuData)628 void SaveInData::ApplyMenu(
629 uno::Reference< container::XIndexContainer > const & rMenuBar,
630 uno::Reference< lang::XSingleComponentFactory >& rFactory,
631 SvxConfigEntry* pMenuData )
632 {
633 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
634
635 for (auto const& entry : *pMenuData->GetEntries())
636 {
637 if (entry->IsPopup())
638 {
639 uno::Sequence< beans::PropertyValue > aPropValueSeq =
640 SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
641
642 uno::Reference< container::XIndexContainer > xSubMenuBar(
643 rFactory->createInstanceWithContext( xContext ),
644 uno::UNO_QUERY );
645
646 sal_Int32 nIndex = aPropValueSeq.getLength();
647 aPropValueSeq.realloc( nIndex + 1 );
648 auto pPropValueSeq = aPropValueSeq.getArray();
649 pPropValueSeq[nIndex].Name = ITEM_DESCRIPTOR_CONTAINER;
650 pPropValueSeq[nIndex].Value <<= xSubMenuBar;
651
652 rMenuBar->insertByIndex(
653 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
654
655 ApplyMenu( xSubMenuBar, rFactory, entry );
656 entry->SetModified( false );
657 }
658 else if (entry->IsSeparator())
659 {
660 rMenuBar->insertByIndex(
661 rMenuBar->getCount(), uno::Any( m_aSeparatorSeq ));
662 }
663 else
664 {
665 uno::Sequence< beans::PropertyValue > aPropValueSeq =
666 SvxConfigPageHelper::ConvertSvxConfigEntry(entry);
667 rMenuBar->insertByIndex(
668 rMenuBar->getCount(), uno::Any( aPropValueSeq ));
669 }
670 }
671 pMenuData->SetModified( false );
672 }
673
674 void
Reset()675 MenuSaveInData::Reset()
676 {
677 try
678 {
679 GetConfigManager()->removeSettings( m_aMenuResourceURL );
680 }
681 catch ( const css::uno::Exception& )
682 {}
683
684 PersistChanges( GetConfigManager() );
685
686 pRootEntry.reset();
687
688 try
689 {
690 m_xMenuSettings = GetConfigManager()->getSettings(
691 m_aMenuResourceURL, false );
692 }
693 catch ( container::NoSuchElementException& )
694 {
695 // will use default settings
696 }
697 }
698
ContextMenuSaveInData(const css::uno::Reference<css::ui::XUIConfigurationManager> & xCfgMgr,const css::uno::Reference<css::ui::XUIConfigurationManager> & xParentCfgMgr,const OUString & aModuleId,bool bIsDocConfig)699 ContextMenuSaveInData::ContextMenuSaveInData(
700 const css::uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr,
701 const css::uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr,
702 const OUString& aModuleId, bool bIsDocConfig )
703 : SaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bIsDocConfig )
704 {
705 css::uno::Reference< css::uno::XComponentContext > xContext( comphelper::getProcessComponentContext() );
706 css::uno::Reference< css::container::XNameAccess > xConfig( css::ui::theWindowStateConfiguration::get( xContext ) );
707 xConfig->getByName( aModuleId ) >>= m_xPersistentWindowState;
708 }
709
~ContextMenuSaveInData()710 ContextMenuSaveInData::~ContextMenuSaveInData()
711 {
712 }
713
GetUIName(const OUString & rResourceURL)714 OUString ContextMenuSaveInData::GetUIName( const OUString& rResourceURL )
715 {
716 if ( m_xPersistentWindowState.is() )
717 {
718 css::uno::Sequence< css::beans::PropertyValue > aProps;
719 try
720 {
721 m_xPersistentWindowState->getByName( rResourceURL ) >>= aProps;
722 }
723 catch ( const css::uno::Exception& )
724 {}
725
726 for (const auto& aProp : aProps)
727 {
728 if ( aProp.Name == ITEM_DESCRIPTOR_UINAME )
729 {
730 OUString aResult;
731 aProp.Value >>= aResult;
732 return aResult;
733 }
734 }
735 }
736 return OUString();
737 }
738
GetEntries()739 SvxEntries* ContextMenuSaveInData::GetEntries()
740 {
741 if ( !m_pRootEntry )
742 {
743 std::unordered_map< OUString, bool > aMenuInfo;
744
745 m_pRootEntry.reset( new SvxConfigEntry( u"ContextMenus"_ustr, OUString(), true, /*bParentData*/false ) );
746 css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aElementsInfo;
747 try
748 {
749 aElementsInfo = GetConfigManager()->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
750 }
751 catch ( const css::lang::IllegalArgumentException& )
752 {}
753
754 for (const auto& aElement : aElementsInfo)
755 {
756 OUString aUrl;
757 for ( const auto& aElementProp : aElement )
758 {
759 if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
760 {
761 aElementProp.Value >>= aUrl;
762 break;
763 }
764 }
765
766 css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
767 try
768 {
769 xPopupMenu = GetConfigManager()->getSettings( aUrl, false );
770 }
771 catch ( const css::uno::Exception& )
772 {}
773
774 if ( xPopupMenu.is() )
775 {
776 // insert into std::unordered_map to filter duplicates from the parent
777 aMenuInfo.emplace( aUrl, true );
778
779 OUString aUIMenuName = GetUIName( aUrl );
780 if ( aUIMenuName.isEmpty() )
781 // Menus without UI name aren't supposed to be customized.
782 continue;
783
784 SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, /*bParentData*/false );
785 pEntry->SetMain();
786 m_pRootEntry->GetEntries()->push_back( pEntry );
787 LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
788 }
789 }
790
791 // Retrieve also the parent menus, to make it possible to configure module menus and save them into the document.
792 css::uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
793 css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aParentElementsInfo;
794 try
795 {
796 if ( xParentCfgMgr.is() )
797 aParentElementsInfo = xParentCfgMgr->getUIElementsInfo( css::ui::UIElementType::POPUPMENU );
798 }
799 catch ( const css::lang::IllegalArgumentException& )
800 {}
801
802 for (const auto& aElement : aParentElementsInfo)
803 {
804 OUString aUrl;
805 for ( const auto& aElementProp : aElement )
806 {
807 if ( aElementProp.Name == ITEM_DESCRIPTOR_RESOURCEURL )
808 {
809 aElementProp.Value >>= aUrl;
810 break;
811 }
812 }
813
814 css::uno::Reference< css::container::XIndexAccess > xPopupMenu;
815 try
816 {
817 if ( aMenuInfo.find( aUrl ) == aMenuInfo.end() )
818 xPopupMenu = xParentCfgMgr->getSettings( aUrl, false );
819 }
820 catch ( const css::uno::Exception& )
821 {}
822
823 if ( xPopupMenu.is() )
824 {
825 OUString aUIMenuName = GetUIName( aUrl );
826 if ( aUIMenuName.isEmpty() )
827 continue;
828
829 SvxConfigEntry* pEntry = new SvxConfigEntry( aUIMenuName, aUrl, true, true );
830 pEntry->SetMain();
831 m_pRootEntry->GetEntries()->push_back( pEntry );
832 LoadSubMenus( xPopupMenu, aUIMenuName, pEntry, true );
833 }
834 }
835 std::sort( m_pRootEntry->GetEntries()->begin(), m_pRootEntry->GetEntries()->end(), SvxConfigPageHelper::EntrySort );
836 }
837 return m_pRootEntry->GetEntries();
838 }
839
SetEntries(std::unique_ptr<SvxEntries> pNewEntries)840 void ContextMenuSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
841 {
842 m_pRootEntry->SetEntries( std::move(pNewEntries) );
843 }
844
HasURL(const OUString & rURL)845 bool ContextMenuSaveInData::HasURL( const OUString& rURL )
846 {
847 SvxEntries* pEntries = GetEntries();
848 for ( const auto& pEntry : *pEntries )
849 if ( pEntry->GetCommand() == rURL )
850 return true;
851
852 return false;
853 }
854
HasSettings()855 bool ContextMenuSaveInData::HasSettings()
856 {
857 return m_pRootEntry && !m_pRootEntry->GetEntries()->empty();
858 }
859
Apply()860 bool ContextMenuSaveInData::Apply()
861 {
862 if ( !IsModified() )
863 return false;
864
865 SvxEntries* pEntries = GetEntries();
866 for ( const auto& pEntry : *pEntries )
867 {
868 if ( pEntry->IsModified() || SvxConfigPageHelper::SvxConfigEntryModified( pEntry ) )
869 {
870 css::uno::Reference< css::container::XIndexContainer > xIndexContainer = GetConfigManager()->createSettings();
871 css::uno::Reference< css::lang::XSingleComponentFactory > xFactory( xIndexContainer, css::uno::UNO_QUERY );
872 ApplyMenu( xIndexContainer, xFactory, pEntry );
873
874 const OUString& aUrl = pEntry->GetCommand();
875 try
876 {
877 if ( GetConfigManager()->hasSettings( aUrl ) )
878 GetConfigManager()->replaceSettings( aUrl, xIndexContainer );
879 else
880 GetConfigManager()->insertSettings( aUrl, xIndexContainer );
881 }
882 catch ( const css::uno::Exception& )
883 {}
884 }
885 }
886 SetModified( false );
887 return PersistChanges( GetConfigManager() );
888 }
889
Reset()890 void ContextMenuSaveInData::Reset()
891 {
892 SvxEntries* pEntries = GetEntries();
893 for ( const auto& pEntry : *pEntries )
894 {
895 try
896 {
897 GetConfigManager()->removeSettings( pEntry->GetCommand() );
898 }
899 catch ( const css::uno::Exception& )
900 {
901 TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menus");
902 }
903 }
904 PersistChanges( GetConfigManager() );
905 m_pRootEntry.reset();
906 }
907
ResetContextMenu(const SvxConfigEntry * pEntry)908 void ContextMenuSaveInData::ResetContextMenu( const SvxConfigEntry* pEntry )
909 {
910 try
911 {
912 GetConfigManager()->removeSettings( pEntry->GetCommand() );
913 }
914 catch ( const css::uno::Exception& )
915 {
916 TOOLS_WARN_EXCEPTION("cui.customize", "Exception caught while resetting context menu");
917 }
918 PersistChanges( GetConfigManager() );
919 m_pRootEntry.reset();
920 }
921
CreateDropDown()922 void SvxMenuEntriesListBox::CreateDropDown()
923 {
924 int nWidth = (m_xControl->get_text_height() * 3) / 4;
925 m_xDropDown->SetOutputSizePixel(Size(nWidth, nWidth));
926 DecorationView aDecoView(m_xDropDown.get());
927 aDecoView.DrawSymbol(tools::Rectangle(Point(0, 0), Size(nWidth, nWidth)),
928 SymbolType::SPIN_RIGHT, m_xDropDown->GetTextColor(),
929 DrawSymbolFlags::NONE);
930 }
931
932 /******************************************************************************
933 *
934 * SvxMenuEntriesListBox is the listbox in which the menu items for a
935 * particular menu are shown. We have a custom listbox because we need
936 * to add drag'n'drop support from the Macro Selector and within the
937 * listbox
938 *
939 *****************************************************************************/
SvxMenuEntriesListBox(std::unique_ptr<weld::TreeView> xControl,SvxConfigPage * pPg)940 SvxMenuEntriesListBox::SvxMenuEntriesListBox(std::unique_ptr<weld::TreeView> xControl, SvxConfigPage* pPg)
941 : m_xControl(std::move(xControl))
942 , m_xDropDown(m_xControl->create_virtual_device())
943 , m_pPage(pPg)
944 {
945 m_xControl->enable_toggle_buttons(weld::ColumnToggleType::Check);
946 CreateDropDown();
947 m_xControl->connect_key_press(LINK(this, SvxMenuEntriesListBox, KeyInputHdl));
948 m_xControl->connect_query_tooltip(LINK(this, SvxMenuEntriesListBox, QueryTooltip));
949 }
950
~SvxMenuEntriesListBox()951 SvxMenuEntriesListBox::~SvxMenuEntriesListBox()
952 {
953 }
954
IMPL_LINK(SvxMenuEntriesListBox,KeyInputHdl,const KeyEvent &,rKeyEvent,bool)955 IMPL_LINK(SvxMenuEntriesListBox, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
956 {
957 vcl::KeyCode keycode = rKeyEvent.GetKeyCode();
958
959 // support DELETE for removing the current entry
960 if ( keycode == KEY_DELETE )
961 {
962 m_pPage->DeleteSelectedContent();
963 }
964 // support CTRL+UP and CTRL+DOWN for moving selected entries
965 else if ( keycode.GetCode() == KEY_UP && keycode.IsMod1() )
966 {
967 m_pPage->MoveEntry( true );
968 }
969 else if ( keycode.GetCode() == KEY_DOWN && keycode.IsMod1() )
970 {
971 m_pPage->MoveEntry( false );
972 }
973 else
974 {
975 return false; // pass on to default handler
976 }
977 return true;
978 }
979
IMPL_LINK(SvxMenuEntriesListBox,QueryTooltip,const weld::TreeIter &,rIter,OUString)980 IMPL_LINK(SvxMenuEntriesListBox, QueryTooltip, const weld::TreeIter&, rIter, OUString)
981 {
982 SvxConfigEntry *pEntry = weld::fromId<SvxConfigEntry*>(m_xControl->get_id(rIter));
983 if (!pEntry || pEntry->GetCommand().isEmpty())
984 return OUString();
985 const OUString sCommand(pEntry->GetCommand());
986 OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(m_pPage->GetFrame()));
987 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(sCommand, aModuleName);
988 OUString sTooltipLabel = vcl::CommandInfoProvider::GetTooltipForCommand(sCommand, aProperties,
989 m_pPage->GetFrame());
990 return CuiResId(RID_CUISTR_COMMANDLABEL) + ": " + pEntry->GetName().replaceFirst("~", "") + "\n" +
991 CuiResId(RID_CUISTR_COMMANDNAME) + ": " + sCommand + "\n" +
992 CuiResId(RID_CUISTR_COMMANDTIP) + ": " + sTooltipLabel.replaceFirst("~", "");
993 }
994
995 /******************************************************************************
996 *
997 * SvxConfigPage is the abstract base class on which the Menu and Toolbar
998 * configuration tabpages are based. It includes methods which are common to
999 * both tabpages to add, delete, move and rename items etc.
1000 *
1001 *****************************************************************************/
SvxConfigPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)1002 SvxConfigPage::SvxConfigPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
1003 : SfxTabPage(pPage, pController, u"cui/ui/menuassignpage.ui"_ustr, u"MenuAssignPage"_ustr, &rSet)
1004 , m_aUpdateDataTimer( "SvxConfigPage UpdateDataTimer" )
1005 , bInitialised(false)
1006 , pCurrentSaveInData(nullptr)
1007 , m_xCommandCategoryListBox(new CommandCategoryListBox(m_xBuilder->weld_combo_box(u"commandcategorylist"_ustr)))
1008 , m_xFunctions(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view(u"functions"_ustr)))
1009 , m_xCategoryLabel(m_xBuilder->weld_label(u"categorylabel"_ustr))
1010 , m_xDescriptionFieldLb(m_xBuilder->weld_label(u"descriptionlabel"_ustr))
1011 , m_xDescriptionField(m_xBuilder->weld_text_view(u"desc"_ustr))
1012 , m_xLeftFunctionLabel(m_xBuilder->weld_label(u"leftfunctionlabel"_ustr))
1013 , m_xSearchEdit(m_xBuilder->weld_entry(u"searchEntry"_ustr))
1014 , m_xSearchLabel(m_xBuilder->weld_label(u"searchlabel"_ustr))
1015 , m_xCustomizeLabel(m_xBuilder->weld_label(u"customizelabel"_ustr))
1016 , m_xTopLevelListBox(m_xBuilder->weld_combo_box(u"toplevellist"_ustr))
1017 , m_xMoveUpButton(m_xBuilder->weld_button(u"up"_ustr))
1018 , m_xMoveDownButton(m_xBuilder->weld_button(u"down"_ustr))
1019 , m_xSaveInListBox(m_xBuilder->weld_combo_box(u"savein"_ustr))
1020 , m_xCustomizeBox(m_xBuilder->weld_widget(u"customizebox"_ustr))
1021 , m_xInsertBtn(m_xBuilder->weld_menu_button(u"insert"_ustr))
1022 , m_xModifyBtn(m_xBuilder->weld_menu_button(u"modify"_ustr))
1023 , m_xResetBtn(m_xBuilder->weld_button(u"defaultsbtn"_ustr))
1024 , m_xCommandButtons(m_xBuilder->weld_widget(u"arrowgrid"_ustr))
1025 , m_xAddCommandButton(m_xBuilder->weld_button(u"add"_ustr))
1026 , m_xRemoveCommandButton(m_xBuilder->weld_button(u"remove"_ustr))
1027 {
1028 CustomNotebookbarGenerator::getFileNameAndAppName(m_sAppName, m_sFileName);
1029
1030 m_xTopLevelListBox->connect_changed(LINK(this, SvxConfigPage, SelectElementHdl));
1031
1032 weld::TreeView& rTreeView = m_xFunctions->get_widget();
1033 Size aSize(rTreeView.get_approximate_digit_width() * 40, rTreeView.get_height_rows(8));
1034 m_xFunctions->set_size_request(aSize.Width(), aSize.Height());
1035 m_xDescriptionField->set_size_request(aSize.Width(), m_xDescriptionField->get_height_rows(3));
1036
1037 m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SvxConfigPage, ImplUpdateDataHdl));
1038 m_aUpdateDataTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT);
1039
1040 m_xSearchEdit->connect_changed(LINK(this, SvxConfigPage, SearchUpdateHdl));
1041 m_xSearchEdit->connect_focus_out(LINK(this, SvxConfigPage, FocusOut_Impl));
1042
1043 rTreeView.connect_row_activated(LINK(this, SvxConfigPage, FunctionDoubleClickHdl));
1044 rTreeView.connect_changed(LINK(this, SvxConfigPage, SelectFunctionHdl));
1045 }
1046
IMPL_LINK_NOARG(SvxConfigPage,SelectElementHdl,weld::ComboBox &,void)1047 IMPL_LINK_NOARG(SvxConfigPage, SelectElementHdl, weld::ComboBox&, void)
1048 {
1049 SelectElement();
1050 }
1051
~SvxConfigPage()1052 SvxConfigPage::~SvxConfigPage()
1053 {
1054 int cnt = m_xSaveInListBox->get_count();
1055 for(int i=0; i < cnt; ++i)
1056 {
1057 SaveInData *pData = weld::fromId<SaveInData*>(m_xSaveInListBox->get_id(i));
1058 delete pData;
1059 }
1060 }
1061
Reset(const SfxItemSet *)1062 void SvxConfigPage::Reset( const SfxItemSet* )
1063 {
1064 // If we haven't initialised our XMultiServiceFactory reference
1065 // then Reset is being called at the opening of the dialog.
1066
1067 // Load menu configuration data for the module of the currently
1068 // selected document, for the currently selected document, and for
1069 // all other open documents of the same module type
1070 if ( !bInitialised )
1071 {
1072 sal_Int32 nPos = 0;
1073 uno::Reference < css::ui::XUIConfigurationManager > xCfgMgr;
1074 uno::Reference < css::ui::XUIConfigurationManager > xDocCfgMgr;
1075
1076 uno::Reference< uno::XComponentContext > xContext(
1077 ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
1078
1079 m_xFrame = GetFrame();
1080 m_aModuleId = GetFrameWithDefaultAndIdentify( m_xFrame );
1081
1082 // replace %MODULENAME in the label with the correct module name
1083 uno::Reference< css::frame::XModuleManager2 > xModuleManager(
1084 css::frame::ModuleManager::create( xContext ));
1085 OUString aModuleName = SvxConfigPageHelper::GetUIModuleName( m_aModuleId, xModuleManager );
1086
1087 uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier >
1088 xModuleCfgSupplier( css::ui::theModuleUIConfigurationManagerSupplier::get(xContext) );
1089
1090 // Set up data for module specific menus
1091 SaveInData* pModuleData = nullptr;
1092
1093 try
1094 {
1095 xCfgMgr =
1096 xModuleCfgSupplier->getUIConfigurationManager( m_aModuleId );
1097
1098 pModuleData = CreateSaveInData( xCfgMgr,
1099 uno::Reference< css::ui::XUIConfigurationManager >(),
1100 m_aModuleId,
1101 false );
1102 }
1103 catch ( container::NoSuchElementException& )
1104 {
1105 }
1106
1107 if ( pModuleData != nullptr )
1108 {
1109 OUString sId(weld::toId(pModuleData));
1110 m_xSaveInListBox->append(sId, utl::ConfigManager::getProductName() + " " + aModuleName);
1111 }
1112
1113 // try to retrieve the document based ui configuration manager
1114 OUString aTitle;
1115 uno::Reference< frame::XController > xController =
1116 m_xFrame->getController();
1117 if ( CanConfig( m_aModuleId ) && xController.is() )
1118 {
1119 uno::Reference< frame::XModel > xModel( xController->getModel() );
1120 if ( xModel.is() )
1121 {
1122 uno::Reference< css::ui::XUIConfigurationManagerSupplier >
1123 xCfgSupplier( xModel, uno::UNO_QUERY );
1124
1125 if ( xCfgSupplier.is() )
1126 {
1127 xDocCfgMgr = xCfgSupplier->getUIConfigurationManager();
1128 }
1129 aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
1130 }
1131 }
1132
1133 SaveInData* pDocData = nullptr;
1134 if ( xDocCfgMgr.is() )
1135 {
1136 pDocData = CreateSaveInData( xDocCfgMgr, xCfgMgr, m_aModuleId, true );
1137
1138 if ( !pDocData->IsReadOnly() )
1139 {
1140 OUString sId(weld::toId(pDocData));
1141 m_xSaveInListBox->append(sId, aTitle);
1142 }
1143 }
1144
1145 // if an item to select has been passed in (eg. the ResourceURL for a
1146 // toolbar) then try to select the SaveInData entry that has that item
1147 bool bURLToSelectFound = false;
1148 if ( !m_aURLToSelect.isEmpty() )
1149 {
1150 if ( pDocData && pDocData->HasURL( m_aURLToSelect ) )
1151 {
1152 m_xSaveInListBox->set_active(nPos);
1153 pCurrentSaveInData = pDocData;
1154 bURLToSelectFound = true;
1155 }
1156 else if ( pModuleData && pModuleData->HasURL( m_aURLToSelect ) )
1157 {
1158 m_xSaveInListBox->set_active(0);
1159 pCurrentSaveInData = pModuleData;
1160 bURLToSelectFound = true;
1161 }
1162 }
1163
1164 if ( !bURLToSelectFound )
1165 {
1166 // if the document has menu configuration settings select it
1167 // it the SaveIn listbox, otherwise select the module data
1168 if ( pDocData != nullptr && pDocData->HasSettings() )
1169 {
1170 m_xSaveInListBox->set_active(nPos);
1171 pCurrentSaveInData = pDocData;
1172 }
1173 else
1174 {
1175 m_xSaveInListBox->set_active(0);
1176 pCurrentSaveInData = pModuleData;
1177 }
1178 }
1179
1180 #ifdef DBG_UTIL
1181 DBG_ASSERT( pCurrentSaveInData, "SvxConfigPage::Reset(): no SaveInData" );
1182 #endif
1183
1184 if ( CanConfig( m_aModuleId ) )
1185 {
1186 // Load configuration for other open documents which have
1187 // same module type
1188 uno::Sequence< uno::Reference< frame::XFrame > > aFrameList;
1189 try
1190 {
1191 uno::Reference< frame::XDesktop2 > xFramesSupplier = frame::Desktop::create(
1192 xContext );
1193
1194 uno::Reference< frame::XFrames > xFrames =
1195 xFramesSupplier->getFrames();
1196
1197 aFrameList = xFrames->queryFrames(
1198 frame::FrameSearchFlag::ALL & ~frame::FrameSearchFlag::SELF );
1199
1200 }
1201 catch( const uno::Exception& )
1202 {
1203 DBG_UNHANDLED_EXCEPTION("cui.customize");
1204 }
1205
1206 for (uno::Reference<frame::XFrame> const& xf : aFrameList)
1207 {
1208 if ( xf.is() && xf != m_xFrame )
1209 {
1210 OUString aCheckId;
1211 try{
1212 aCheckId = xModuleManager->identify( xf );
1213 } catch(const uno::Exception&)
1214 { aCheckId.clear(); }
1215
1216 if ( m_aModuleId == aCheckId )
1217 {
1218 // try to get the document based ui configuration manager
1219 OUString aTitle2;
1220 uno::Reference< frame::XController > xController_ =
1221 xf->getController();
1222
1223 if ( xController_.is() )
1224 {
1225 uno::Reference< frame::XModel > xModel(
1226 xController_->getModel() );
1227
1228 if ( xModel.is() )
1229 {
1230 uno::Reference<
1231 css::ui::XUIConfigurationManagerSupplier >
1232 xCfgSupplier( xModel, uno::UNO_QUERY );
1233
1234 if ( xCfgSupplier.is() )
1235 {
1236 xDocCfgMgr =
1237 xCfgSupplier->getUIConfigurationManager();
1238 }
1239 aTitle2 = ::comphelper::DocumentInfo::getDocumentTitle( xModel );
1240 }
1241 }
1242
1243 if ( xDocCfgMgr.is() )
1244 {
1245 SaveInData* pData = CreateSaveInData( xDocCfgMgr, xCfgMgr, m_aModuleId, true );
1246
1247 if ( pData && !pData->IsReadOnly() )
1248 {
1249 OUString sId(weld::toId(pData));
1250 m_xSaveInListBox->append(sId, aTitle2);
1251 }
1252 }
1253 }
1254 }
1255 }
1256 }
1257
1258 m_xSaveInListBox->connect_changed(
1259 LINK( this, SvxConfigPage, SelectSaveInLocation ) );
1260
1261 bInitialised = true;
1262
1263 Init();
1264 }
1265 else
1266 {
1267 if ( QueryReset() == RET_YES )
1268 {
1269 // Reset menu configuration for currently selected SaveInData
1270 GetSaveInData()->Reset();
1271
1272 Init();
1273 }
1274 }
1275 }
1276
GetFrameWithDefaultAndIdentify(uno::Reference<frame::XFrame> & _inout_rxFrame)1277 OUString SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference< frame::XFrame >& _inout_rxFrame )
1278 {
1279 OUString sModuleID;
1280 try
1281 {
1282 uno::Reference< uno::XComponentContext > xContext(
1283 ::comphelper::getProcessComponentContext() );
1284
1285 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(
1286 xContext );
1287
1288 if ( !_inout_rxFrame.is() )
1289 _inout_rxFrame = xDesktop->getActiveFrame();
1290
1291 if ( !_inout_rxFrame.is() )
1292 {
1293 _inout_rxFrame = xDesktop->getCurrentFrame();
1294 }
1295
1296 if ( !_inout_rxFrame.is())
1297 {
1298 if (SfxViewFrame* pViewFrame = SfxViewFrame::Current())
1299 _inout_rxFrame = pViewFrame->GetFrame().GetFrameInterface();
1300 }
1301
1302 if ( !_inout_rxFrame.is() )
1303 {
1304 SAL_WARN( "cui.customize", "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" );
1305 return sModuleID;
1306 }
1307
1308 sModuleID = vcl::CommandInfoProvider::GetModuleIdentifier(_inout_rxFrame);
1309 }
1310 catch( const uno::Exception& )
1311 {
1312 DBG_UNHANDLED_EXCEPTION("cui.customize");
1313 }
1314
1315 return sModuleID;
1316 }
1317
GetScriptURL() const1318 OUString SvxConfigPage::GetScriptURL() const
1319 {
1320 OUString result;
1321
1322 SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(m_xFunctions->get_selected_id());
1323 if (pData)
1324 {
1325 if ( ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) ||
1326 ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) ||
1327 ( pData->nKind == SfxCfgKind::GROUP_STYLES ) )
1328 {
1329 result = pData->sCommand;
1330 }
1331 }
1332
1333 return result;
1334 }
1335
GetSelectedDisplayName() const1336 OUString SvxConfigPage::GetSelectedDisplayName() const
1337 {
1338 return m_xFunctions->get_selected_text();
1339 }
1340
FillItemSet(SfxItemSet *)1341 bool SvxConfigPage::FillItemSet( SfxItemSet* )
1342 {
1343 bool result = false;
1344
1345 for (int i = 0, nCount = m_xSaveInListBox->get_count(); i < nCount; ++i)
1346 {
1347 OUString sId = m_xSaveInListBox->get_id(i);
1348 if (sId != notebookbarTabScope)
1349 {
1350 SaveInData* pData = weld::fromId<SaveInData*>(sId);
1351 result = pData->Apply();
1352 }
1353 }
1354 return result;
1355 }
1356
IMPL_LINK_NOARG(SvxConfigPage,SelectSaveInLocation,weld::ComboBox &,void)1357 IMPL_LINK_NOARG(SvxConfigPage, SelectSaveInLocation, weld::ComboBox&, void)
1358 {
1359 OUString sId = m_xSaveInListBox->get_active_id();
1360 if (sId != notebookbarTabScope)
1361 pCurrentSaveInData = weld::fromId<SaveInData*>(sId);
1362 Init();
1363 }
1364
ReloadTopLevelListBox(SvxConfigEntry const * pToSelect)1365 void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry const * pToSelect )
1366 {
1367 int nSelectionPos = m_xTopLevelListBox->get_active();
1368 m_xTopLevelListBox->clear();
1369
1370 if ( GetSaveInData() && GetSaveInData()->GetEntries() )
1371 {
1372 for (auto const& entryData : *GetSaveInData()->GetEntries())
1373 {
1374 OUString sId(weld::toId(entryData));
1375 m_xTopLevelListBox->append(sId, SvxConfigPageHelper::stripHotKey(entryData->GetName()));
1376
1377 if (entryData == pToSelect)
1378 nSelectionPos = m_xTopLevelListBox->get_count() - 1;
1379
1380 AddSubMenusToUI( SvxConfigPageHelper::stripHotKey( entryData->GetName() ), entryData );
1381 }
1382 }
1383 #ifdef DBG_UTIL
1384 else
1385 {
1386 DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" );
1387 DBG_ASSERT( GetSaveInData()->GetEntries() ,
1388 "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" );
1389 }
1390 #endif
1391
1392 nSelectionPos = (nSelectionPos != -1 && nSelectionPos < m_xTopLevelListBox->get_count()) ?
1393 nSelectionPos : m_xTopLevelListBox->get_count() - 1;
1394
1395 m_xTopLevelListBox->set_active(nSelectionPos);
1396 SelectElement();
1397 }
1398
AddSubMenusToUI(std::u16string_view rBaseTitle,SvxConfigEntry const * pParentData)1399 void SvxConfigPage::AddSubMenusToUI(
1400 std::u16string_view rBaseTitle, SvxConfigEntry const * pParentData )
1401 {
1402 for (auto const& entryData : *pParentData->GetEntries())
1403 {
1404 if (entryData->IsPopup())
1405 {
1406 OUString subMenuTitle = OUString::Concat(rBaseTitle) + aMenuSeparatorStr + SvxConfigPageHelper::stripHotKey(entryData->GetName());
1407
1408 OUString sId(weld::toId(entryData));
1409 m_xTopLevelListBox->append(sId, subMenuTitle);
1410
1411 AddSubMenusToUI( subMenuTitle, entryData );
1412 }
1413 }
1414 }
1415
FindParentForChild(SvxEntries * pRootEntries,SvxConfigEntry * pChildData)1416 SvxEntries* SvxConfigPage::FindParentForChild(
1417 SvxEntries* pRootEntries, SvxConfigEntry* pChildData )
1418 {
1419 for (auto const& entryData : *pRootEntries)
1420 {
1421
1422 if (entryData == pChildData)
1423 {
1424 return pRootEntries;
1425 }
1426 else if (entryData->IsPopup())
1427 {
1428 SvxEntries* result =
1429 FindParentForChild( entryData->GetEntries(), pChildData );
1430
1431 if ( result != nullptr )
1432 {
1433 return result;
1434 }
1435 }
1436 }
1437 return nullptr;
1438 }
1439
CreateCommandFromSelection(const OUString & aURL)1440 SvxConfigEntry *SvxConfigPage::CreateCommandFromSelection(const OUString &aURL)
1441 {
1442 OUString aDisplayName;
1443
1444 if ( aURL.isEmpty() ) {
1445 return nullptr;
1446 }
1447
1448 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aURL, m_aModuleId);
1449
1450 if ( typeid(*pCurrentSaveInData) == typeid(ContextMenuSaveInData) )
1451 aDisplayName = vcl::CommandInfoProvider::GetPopupLabelForCommand(aProperties);
1452 else if ( typeid(*pCurrentSaveInData) == typeid(MenuSaveInData) )
1453 aDisplayName = vcl::CommandInfoProvider::GetMenuLabelForCommand(aProperties);
1454 else
1455 aDisplayName = vcl::CommandInfoProvider::GetLabelForCommand(aProperties);
1456
1457 SvxConfigEntry* toret =
1458 new SvxConfigEntry( aDisplayName, aURL, false, /*bParentData*/false );
1459
1460 toret->SetUserDefined();
1461
1462 if ( aDisplayName.isEmpty() )
1463 toret->SetName( GetSelectedDisplayName() );
1464
1465 return toret;
1466 }
1467
IsCommandInMenuList(const SvxConfigEntry * pEntryData,const SvxEntries * pEntries)1468 bool SvxConfigPage::IsCommandInMenuList(const SvxConfigEntry *pEntryData,
1469 const SvxEntries *pEntries)
1470 {
1471 bool toret = false;
1472
1473 if ( pEntries != nullptr
1474 && pEntryData != nullptr )
1475 {
1476 for (auto const& entry : *pEntries)
1477 {
1478 if ( entry->GetCommand() == pEntryData->GetCommand() )
1479 {
1480 toret = true;
1481 break;
1482 }
1483 }
1484 }
1485
1486 return toret;
1487 }
1488
AddFunction(int nTarget,bool bAllowDuplicates)1489 int SvxConfigPage::AddFunction(int nTarget, bool bAllowDuplicates)
1490 {
1491 int toret = -1;
1492 OUString aURL = GetScriptURL();
1493 SvxConfigEntry* pParent = GetTopLevelSelection();
1494
1495 if ( aURL.isEmpty() || pParent == nullptr )
1496 {
1497 return -1;
1498 }
1499
1500
1501 SvxConfigEntry * pNewEntryData = CreateCommandFromSelection( aURL );
1502
1503 // check that this function is not already in the menu
1504 if ( !bAllowDuplicates
1505 && IsCommandInMenuList( pNewEntryData, pParent->GetEntries() )
1506 )
1507 {
1508 delete pNewEntryData;
1509 } else {
1510 toret = AppendEntry( pNewEntryData, nTarget );
1511 }
1512
1513 UpdateButtonStates();
1514 return toret;
1515 }
1516
AppendEntry(SvxConfigEntry * pNewEntryData,int nTarget)1517 int SvxConfigPage::AppendEntry(
1518 SvxConfigEntry* pNewEntryData,
1519 int nTarget)
1520 {
1521 SvxConfigEntry* pTopLevelSelection = GetTopLevelSelection();
1522
1523 if (pTopLevelSelection == nullptr)
1524 return -1;
1525
1526 // Grab the entries list for the currently selected menu
1527 SvxEntries* pEntries = pTopLevelSelection->GetEntries();
1528
1529 int nNewEntry = -1;
1530 int nCurEntry =
1531 nTarget != -1 ? nTarget : m_xContentsListBox->get_selected_index();
1532
1533 OUString sId(weld::toId(pNewEntryData));
1534
1535 if (nCurEntry == -1 || nCurEntry == m_xContentsListBox->n_children() - 1)
1536 {
1537 pEntries->push_back( pNewEntryData );
1538 m_xContentsListBox->insert(-1, sId);
1539 nNewEntry = m_xContentsListBox->n_children() - 1;
1540 }
1541 else
1542 {
1543 SvxConfigEntry* pEntryData =
1544 weld::fromId<SvxConfigEntry*>(m_xContentsListBox->get_id(nCurEntry));
1545
1546 SvxEntries::iterator iter = pEntries->begin();
1547 SvxEntries::const_iterator end = pEntries->end();
1548
1549 // Advance the iterator to the data for currently selected entry
1550 sal_uInt16 nPos = 0;
1551 while (*iter != pEntryData && ++iter != end)
1552 {
1553 ++nPos;
1554 }
1555
1556 // Now step past it to the entry after the currently selected one
1557 ++iter;
1558 ++nPos;
1559
1560 // Now add the new entry to the UI and to the parent's list
1561 if ( iter != end )
1562 {
1563 pEntries->insert( iter, pNewEntryData );
1564 m_xContentsListBox->insert(nPos, sId);
1565 nNewEntry = nPos;
1566 }
1567 }
1568
1569 if (nNewEntry != -1)
1570 {
1571 m_xContentsListBox->select(nNewEntry);
1572 m_xContentsListBox->scroll_to_row(nNewEntry);
1573
1574 GetSaveInData()->SetModified();
1575 GetTopLevelSelection()->SetModified();
1576 }
1577
1578 return nNewEntry;
1579 }
1580
1581 namespace
1582 {
TmplInsertEntryIntoUI(SvxConfigEntry * pNewEntryData,weld::TreeView & rTreeView,itertype & rIter,SaveInData * pSaveInData,VirtualDevice & rDropDown,bool bMenu)1583 template<typename itertype> void TmplInsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, itertype& rIter, SaveInData* pSaveInData,
1584 VirtualDevice& rDropDown, bool bMenu)
1585 {
1586 OUString sId(weld::toId(pNewEntryData));
1587
1588 rTreeView.set_id(rIter, sId);
1589
1590 if (pNewEntryData->IsSeparator())
1591 {
1592 rTreeView.set_text(rIter, "----------------------------------", 0);
1593 }
1594 else
1595 {
1596 auto xImage = pSaveInData->GetImage(pNewEntryData->GetCommand());
1597 if (xImage.is())
1598 rTreeView.set_image(rIter, xImage, -1);
1599 OUString aName = SvxConfigPageHelper::stripHotKey( pNewEntryData->GetName() );
1600 rTreeView.set_text(rIter, aName, 0);
1601 }
1602
1603 if (bMenu) // menus
1604 {
1605 if (pNewEntryData->IsPopup() || pNewEntryData->GetStyle() & css::ui::ItemStyle::DROP_DOWN)
1606 rTreeView.set_image(rIter, rDropDown, 1);
1607 else
1608 rTreeView.set_image(rIter, css::uno::Reference<css::graphic::XGraphic>(), 1);
1609 }
1610 }
1611 }
1612
InsertEntryIntoUI(SvxConfigEntry * pNewEntryData,weld::TreeView & rTreeView,int nPos,bool bMenu)1613 void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, int nPos, bool bMenu)
1614 {
1615 TmplInsertEntryIntoUI<int>(pNewEntryData, rTreeView, nPos, GetSaveInData(),
1616 m_xContentsListBox->get_dropdown_image(), bMenu);
1617 }
1618
InsertEntryIntoUI(SvxConfigEntry * pNewEntryData,weld::TreeView & rTreeView,weld::TreeIter & rIter,bool bMenu)1619 void SvxConfigPage::InsertEntryIntoUI(SvxConfigEntry* pNewEntryData, weld::TreeView& rTreeView, weld::TreeIter& rIter, bool bMenu)
1620 {
1621 TmplInsertEntryIntoUI<weld::TreeIter>(pNewEntryData, rTreeView, rIter, GetSaveInData(),
1622 m_xContentsListBox->get_dropdown_image(), bMenu);
1623 }
1624
IMPL_LINK(SvxConfigPage,MoveHdl,weld::Button &,rButton,void)1625 IMPL_LINK(SvxConfigPage, MoveHdl, weld::Button&, rButton, void)
1626 {
1627 MoveEntry(&rButton == m_xMoveUpButton.get());
1628 }
1629
IMPL_LINK_NOARG(SvxConfigPage,FunctionDoubleClickHdl,weld::TreeView &,bool)1630 IMPL_LINK_NOARG(SvxConfigPage, FunctionDoubleClickHdl, weld::TreeView&, bool)
1631 {
1632 if (m_xAddCommandButton->get_sensitive())
1633 m_xAddCommandButton->clicked();
1634 return true;
1635 }
1636
IMPL_LINK_NOARG(SvxConfigPage,SelectFunctionHdl,weld::TreeView &,void)1637 IMPL_LINK_NOARG(SvxConfigPage, SelectFunctionHdl, weld::TreeView&, void)
1638 {
1639 // GetScriptURL() returns a non-empty string if a
1640 // valid command is selected on the left box
1641 OUString aSelectCommand = GetScriptURL();
1642 bool bIsValidCommand = !aSelectCommand.isEmpty();
1643
1644 // Enable/disable Add and Remove buttons depending on current selection
1645 if (bIsValidCommand)
1646 {
1647 m_xAddCommandButton->set_sensitive(true);
1648 m_xRemoveCommandButton->set_sensitive(true);
1649
1650 if (SfxHelp::IsHelpInstalled())
1651 {
1652 m_xDescriptionField->set_text(m_xFunctions->GetCommandHelpText());
1653 }
1654 else
1655 {
1656 SfxGroupInfo_Impl *pData = weld::fromId<SfxGroupInfo_Impl*>(m_xFunctions->get_selected_id());
1657 if (pData)
1658 {
1659 bool bIsExperimental
1660 = vcl::CommandInfoProvider::IsExperimental(pData->sCommand, m_aModuleId);
1661
1662 OUString aExperimental = "\n" + CuiResId(RID_CUISTR_COMMANDEXPERIMENTAL);
1663 OUString aLabel = CuiResId(RID_CUISTR_COMMANDLABEL) + ": " + pData->sLabel + "\n";
1664 OUString aName = CuiResId(RID_CUISTR_COMMANDNAME) + ": " + pData->sCommand + "\n";
1665 OUString aTip = CuiResId(RID_CUISTR_COMMANDTIP) + ": " + pData->sTooltip;
1666 if (bIsExperimental)
1667 m_xDescriptionField->set_text(aLabel + aName + aTip + aExperimental);
1668 else
1669 m_xDescriptionField->set_text(aLabel + aName + aTip);
1670 }
1671 }
1672 }
1673 else
1674 {
1675
1676 m_xAddCommandButton->set_sensitive(false);
1677 m_xRemoveCommandButton->set_sensitive(false);
1678
1679 m_xDescriptionField->set_text(u""_ustr);
1680 }
1681
1682 UpdateButtonStates();
1683 }
1684
IMPL_LINK_NOARG(SvxConfigPage,ImplUpdateDataHdl,Timer *,void)1685 IMPL_LINK_NOARG(SvxConfigPage, ImplUpdateDataHdl, Timer*, void)
1686 {
1687 OUString aSearchTerm(m_xSearchEdit->get_text());
1688 m_xCommandCategoryListBox->categorySelected(m_xFunctions.get(), aSearchTerm, GetSaveInData());
1689 SelectFunctionHdl(m_xFunctions->get_widget());
1690 }
1691
IMPL_LINK_NOARG(SvxConfigPage,SearchUpdateHdl,weld::Entry &,void)1692 IMPL_LINK_NOARG(SvxConfigPage, SearchUpdateHdl, weld::Entry&, void)
1693 {
1694 m_aUpdateDataTimer.Start();
1695 }
1696
IMPL_LINK_NOARG(SvxConfigPage,FocusOut_Impl,weld::Widget &,void)1697 IMPL_LINK_NOARG(SvxConfigPage, FocusOut_Impl, weld::Widget&, void)
1698 {
1699 if (m_aUpdateDataTimer.IsActive())
1700 {
1701 m_aUpdateDataTimer.Stop();
1702 m_aUpdateDataTimer.Invoke();
1703 }
1704 }
1705
MoveEntry(bool bMoveUp)1706 void SvxConfigPage::MoveEntry(bool bMoveUp)
1707 {
1708 weld::TreeView& rTreeView = m_xContentsListBox->get_widget();
1709
1710 int nSourceEntry = rTreeView.get_selected_index();
1711 int nTargetEntry = -1;
1712 int nToSelect = -1;
1713
1714 if (nSourceEntry == -1)
1715 {
1716 return;
1717 }
1718
1719 if ( bMoveUp )
1720 {
1721 // Move Up is just a Move Down with the source and target reversed
1722 nTargetEntry = nSourceEntry;
1723 nSourceEntry = nTargetEntry - 1;
1724 nToSelect = nSourceEntry;
1725 }
1726 else
1727 {
1728 nTargetEntry = nSourceEntry + 1;
1729 nToSelect = nTargetEntry;
1730 }
1731
1732 if (MoveEntryData(nSourceEntry, nTargetEntry))
1733 {
1734 rTreeView.swap(nSourceEntry, nTargetEntry);
1735 rTreeView.select(nToSelect);
1736 rTreeView.scroll_to_row(nToSelect);
1737
1738 UpdateButtonStates();
1739 }
1740 }
1741
MoveEntryData(int nSourceEntry,int nTargetEntry)1742 bool SvxConfigPage::MoveEntryData(int nSourceEntry, int nTargetEntry)
1743 {
1744 //#i53677#
1745 if (nSourceEntry == -1 || nTargetEntry == -1)
1746 {
1747 return false;
1748 }
1749
1750 // Grab the entries list for the currently selected menu
1751 SvxEntries* pEntries = GetTopLevelSelection()->GetEntries();
1752
1753 SvxConfigEntry* pSourceData =
1754 weld::fromId<SvxConfigEntry*>(m_xContentsListBox->get_id(nSourceEntry));
1755
1756 SvxConfigEntry* pTargetData =
1757 weld::fromId<SvxConfigEntry*>(m_xContentsListBox->get_id(nTargetEntry));
1758
1759 if ( pSourceData == nullptr || pTargetData == nullptr )
1760 return false;
1761
1762 // remove the source entry from our list
1763 SvxConfigPageHelper::RemoveEntry( pEntries, pSourceData );
1764
1765 SvxEntries::iterator iter = pEntries->begin();
1766 SvxEntries::const_iterator end = pEntries->end();
1767
1768 // advance the iterator to the position of the target entry
1769 while (*iter != pTargetData && ++iter != end) ;
1770
1771 // insert the source entry at the position after the target
1772 pEntries->insert( ++iter, pSourceData );
1773
1774 GetSaveInData()->SetModified();
1775 GetTopLevelSelection()->SetModified();
1776
1777 return true;
1778 }
1779
SvxMainMenuOrganizerDialog(weld::Window * pParent,SvxEntries * entries,SvxConfigEntry const * selection,bool bCreateMenu)1780 SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog(
1781 weld::Window* pParent, SvxEntries* entries,
1782 SvxConfigEntry const * selection, bool bCreateMenu )
1783 : GenericDialogController(pParent, u"cui/ui/movemenu.ui"_ustr, u"MoveMenuDialog"_ustr)
1784 , m_xMenuBox(m_xBuilder->weld_widget(u"namebox"_ustr))
1785 , m_xMenuNameEdit(m_xBuilder->weld_entry(u"menuname"_ustr))
1786 , m_xMenuListBox(m_xBuilder->weld_tree_view(u"menulist"_ustr))
1787 , m_xMoveUpButton(m_xBuilder->weld_button(u"up"_ustr))
1788 , m_xMoveDownButton(m_xBuilder->weld_button(u"down"_ustr))
1789 {
1790 m_xMenuListBox->set_size_request(-1, m_xMenuListBox->get_height_rows(12));
1791
1792 // Copy the entries list passed in
1793 if ( entries != nullptr )
1794 {
1795 mpEntries.reset( new SvxEntries );
1796 for (auto const& entry : *entries)
1797 {
1798 m_xMenuListBox->append(weld::toId(entry),
1799 SvxConfigPageHelper::stripHotKey(entry->GetName()));
1800 mpEntries->push_back(entry);
1801 if (entry == selection)
1802 {
1803 m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
1804 }
1805 }
1806 }
1807
1808 if ( bCreateMenu )
1809 {
1810 // Generate custom name for new menu
1811 OUString prefix = CuiResId( RID_CUISTR_NEW_MENU );
1812
1813 OUString newname = SvxConfigPageHelper::generateCustomName( prefix, entries );
1814 OUString newurl = SvxConfigPageHelper::generateCustomMenuURL( mpEntries.get() );
1815
1816 SvxConfigEntry* pNewEntryData =
1817 new SvxConfigEntry( newname, newurl, true, /*bParentData*/false );
1818 pNewEntryData->SetName( newname );
1819 pNewEntryData->SetUserDefined();
1820 pNewEntryData->SetMain();
1821
1822 m_sNewMenuEntryId = weld::toId(pNewEntryData);
1823 m_xMenuListBox->append(m_sNewMenuEntryId,
1824 SvxConfigPageHelper::stripHotKey(pNewEntryData->GetName()));
1825 m_xMenuListBox->select(m_xMenuListBox->n_children() - 1);
1826
1827 if (mpEntries)
1828 mpEntries->push_back(pNewEntryData);
1829
1830 m_xMenuNameEdit->set_text(newname);
1831 m_xMenuNameEdit->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, ModifyHdl));
1832 }
1833 else
1834 {
1835 // hide name label and textfield
1836 m_xMenuBox->hide();
1837 // change the title
1838 m_xDialog->set_title(CuiResId(RID_CUISTR_MOVE_MENU));
1839 }
1840
1841 m_xMenuListBox->connect_changed(LINK(this, SvxMainMenuOrganizerDialog, SelectHdl));
1842
1843 m_xMoveUpButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
1844 m_xMoveDownButton->connect_clicked(LINK( this, SvxMainMenuOrganizerDialog, MoveHdl));
1845
1846 UpdateButtonStates();
1847 }
1848
~SvxMainMenuOrganizerDialog()1849 SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog()
1850 {
1851 }
1852
IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog,ModifyHdl,weld::Entry &,void)1853 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, ModifyHdl, weld::Entry&, void)
1854 {
1855 // if the Edit control is empty do not change the name
1856 if (m_xMenuNameEdit->get_text().isEmpty())
1857 {
1858 return;
1859 }
1860
1861 SvxConfigEntry* pNewEntryData = weld::fromId<SvxConfigEntry*>(m_sNewMenuEntryId);
1862 pNewEntryData->SetName(m_xMenuNameEdit->get_text());
1863
1864 const int nNewMenuPos = m_xMenuListBox->find_id(m_sNewMenuEntryId);
1865 const int nOldSelection = m_xMenuListBox->get_selected_index();
1866 m_xMenuListBox->remove(nNewMenuPos);
1867 m_xMenuListBox->insert(nNewMenuPos, pNewEntryData->GetName(), &m_sNewMenuEntryId, nullptr, nullptr);
1868 m_xMenuListBox->select(nOldSelection);
1869 }
1870
IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog,SelectHdl,weld::TreeView &,void)1871 IMPL_LINK_NOARG(SvxMainMenuOrganizerDialog, SelectHdl, weld::TreeView&, void)
1872 {
1873 UpdateButtonStates();
1874 }
1875
UpdateButtonStates()1876 void SvxMainMenuOrganizerDialog::UpdateButtonStates()
1877 {
1878 // Disable Up and Down buttons depending on current selection
1879 const int nSelected = m_xMenuListBox->get_selected_index();
1880 m_xMoveUpButton->set_sensitive(nSelected > 0);
1881 m_xMoveDownButton->set_sensitive(nSelected != -1 && nSelected < m_xMenuListBox->n_children() - 1);
1882 }
1883
IMPL_LINK(SvxMainMenuOrganizerDialog,MoveHdl,weld::Button &,rButton,void)1884 IMPL_LINK( SvxMainMenuOrganizerDialog, MoveHdl, weld::Button&, rButton, void )
1885 {
1886 int nSourceEntry = m_xMenuListBox->get_selected_index();
1887 if (nSourceEntry == -1)
1888 return;
1889
1890 int nTargetEntry;
1891
1892 if (&rButton == m_xMoveDownButton.get())
1893 {
1894 nTargetEntry = nSourceEntry + 1;
1895 }
1896 else
1897 {
1898 // Move Up is just a Move Down with the source and target reversed
1899 nTargetEntry = nSourceEntry - 1;
1900 }
1901
1902 OUString sId = m_xMenuListBox->get_id(nSourceEntry);
1903 OUString sEntry = m_xMenuListBox->get_text(nSourceEntry);
1904 m_xMenuListBox->remove(nSourceEntry);
1905 m_xMenuListBox->insert(nTargetEntry, sEntry, &sId, nullptr, nullptr);
1906 m_xMenuListBox->select(nTargetEntry);
1907
1908 std::swap(mpEntries->at(nSourceEntry), mpEntries->at(nTargetEntry));
1909
1910 UpdateButtonStates();
1911 }
1912
GetSelectedEntry()1913 SvxConfigEntry* SvxMainMenuOrganizerDialog::GetSelectedEntry()
1914 {
1915 const int nSelected(m_xMenuListBox->get_selected_index());
1916 if (nSelected == -1)
1917 return nullptr;
1918 return weld::fromId<SvxConfigEntry*>(m_xMenuListBox->get_id(nSelected));
1919 }
1920
SvxConfigEntry(OUString aDisplayName,OUString aCommandURL,bool bPopup,bool bParentData)1921 SvxConfigEntry::SvxConfigEntry( OUString aDisplayName,
1922 OUString aCommandURL, bool bPopup, bool bParentData )
1923 : nId( 1 )
1924 , aLabel(std::move(aDisplayName))
1925 , aCommand(std::move(aCommandURL))
1926 , bPopUp(bPopup)
1927 , bStrEdited( false )
1928 , bIsUserDefined( false )
1929 , bIsMain( false )
1930 , bIsParentData( bParentData )
1931 , bIsModified( false )
1932 , bIsVisible( true )
1933 , nStyle( 0 )
1934 {
1935 if (bPopUp)
1936 {
1937 mpEntries.reset( new SvxEntries );
1938 }
1939 }
1940
~SvxConfigEntry()1941 SvxConfigEntry::~SvxConfigEntry()
1942 {
1943 if (mpEntries)
1944 {
1945 for (auto const& entry : *mpEntries)
1946 {
1947 delete entry;
1948 }
1949 }
1950 }
1951
IsMovable() const1952 bool SvxConfigEntry::IsMovable() const
1953 {
1954 return !IsPopup() || IsMain();
1955 }
1956
IsDeletable() const1957 bool SvxConfigEntry::IsDeletable() const
1958 {
1959 return !IsMain() || IsUserDefined();
1960 }
1961
IsRenamable() const1962 bool SvxConfigEntry::IsRenamable() const
1963 {
1964 return !IsMain() || IsUserDefined();
1965 }
1966
ToolbarSaveInData(const uno::Reference<css::ui::XUIConfigurationManager> & xCfgMgr,const uno::Reference<css::ui::XUIConfigurationManager> & xParentCfgMgr,const OUString & aModuleId,bool docConfig)1967 ToolbarSaveInData::ToolbarSaveInData(
1968 const uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr,
1969 const uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr,
1970 const OUString& aModuleId,
1971 bool docConfig ) :
1972
1973 SaveInData ( xCfgMgr, xParentCfgMgr, aModuleId, docConfig ),
1974 m_aDescriptorContainer ( ITEM_DESCRIPTOR_CONTAINER )
1975
1976 {
1977 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
1978 // Initialize the m_xPersistentWindowState variable which is used
1979 // to get the default properties of system toolbars such as name
1980 uno::Reference< container::XNameAccess > xPWSS = css::ui::theWindowStateConfiguration::get( xContext );
1981
1982 xPWSS->getByName( aModuleId ) >>= m_xPersistentWindowState;
1983 }
1984
~ToolbarSaveInData()1985 ToolbarSaveInData::~ToolbarSaveInData()
1986 {
1987 }
1988
GetSystemStyle(const OUString & rResourceURL)1989 sal_Int32 ToolbarSaveInData::GetSystemStyle( const OUString& rResourceURL )
1990 {
1991 sal_Int32 result = 0;
1992
1993 if ( rResourceURL.startsWith( "private" ) &&
1994 m_xPersistentWindowState.is() &&
1995 m_xPersistentWindowState->hasByName( rResourceURL ) )
1996 {
1997 try
1998 {
1999 uno::Sequence< beans::PropertyValue > aProps;
2000 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
2001
2002 if ( a >>= aProps )
2003 {
2004 for (beans::PropertyValue const& prop : aProps)
2005 {
2006 if ( prop.Name == ITEM_DESCRIPTOR_STYLE )
2007 {
2008 prop.Value >>= result;
2009 break;
2010 }
2011 }
2012 }
2013 }
2014 catch ( uno::Exception& )
2015 {
2016 // do nothing, a default value is returned
2017 }
2018 }
2019
2020 return result;
2021 }
2022
SetSystemStyle(const uno::Reference<frame::XFrame> & xFrame,const OUString & rResourceURL,sal_Int32 nStyle)2023 void ToolbarSaveInData::SetSystemStyle(
2024 const uno::Reference< frame::XFrame >& xFrame,
2025 const OUString& rResourceURL,
2026 sal_Int32 nStyle )
2027 {
2028 // change the style using the API
2029 SetSystemStyle( rResourceURL, nStyle );
2030
2031 // this code is a temporary hack as the UI is not updating after
2032 // changing the toolbar style via the API
2033 uno::Reference< css::frame::XLayoutManager > xLayoutManager;
2034 vcl::Window *window = nullptr;
2035
2036 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
2037 if ( xPropSet.is() )
2038 {
2039 uno::Any a = xPropSet->getPropertyValue( u"LayoutManager"_ustr );
2040 a >>= xLayoutManager;
2041 }
2042
2043 if ( xLayoutManager.is() )
2044 {
2045 uno::Reference< css::ui::XUIElement > xUIElement =
2046 xLayoutManager->getElement( rResourceURL );
2047
2048 // check reference before we call getRealInterface. The layout manager
2049 // can only provide references for elements that have been created
2050 // before. It's possible that the current element is not available.
2051 uno::Reference< css::awt::XWindow > xWindow;
2052 if ( xUIElement.is() )
2053 xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
2054
2055 window = VCLUnoHelper::GetWindow( xWindow );
2056 }
2057
2058 if ( window == nullptr || window->GetType() != WindowType::TOOLBOX )
2059 return;
2060
2061 ToolBox* toolbox = static_cast<ToolBox*>(window);
2062
2063 if ( nStyle == 0 )
2064 {
2065 toolbox->SetButtonType( ButtonType::SYMBOLONLY );
2066 }
2067 else if ( nStyle == 1 )
2068 {
2069 toolbox->SetButtonType( ButtonType::TEXT );
2070 }
2071 if ( nStyle == 2 )
2072 {
2073 toolbox->SetButtonType( ButtonType::SYMBOLTEXT );
2074 }
2075 }
2076
SetSystemStyle(const OUString & rResourceURL,sal_Int32 nStyle)2077 void ToolbarSaveInData::SetSystemStyle(
2078 const OUString& rResourceURL,
2079 sal_Int32 nStyle )
2080 {
2081 if ( !(rResourceURL.startsWith( "private" ) &&
2082 m_xPersistentWindowState.is() &&
2083 m_xPersistentWindowState->hasByName( rResourceURL )) )
2084 return;
2085
2086 try
2087 {
2088 uno::Sequence< beans::PropertyValue > aProps;
2089
2090 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
2091
2092 if ( a >>= aProps )
2093 {
2094 for ( beans::PropertyValue& prop : asNonConstRange(aProps) )
2095 {
2096 if ( prop.Name == ITEM_DESCRIPTOR_STYLE )
2097 {
2098 prop.Value <<= nStyle;
2099 break;
2100 }
2101 }
2102 }
2103
2104 uno::Reference< container::XNameReplace >
2105 xNameReplace( m_xPersistentWindowState, uno::UNO_QUERY );
2106
2107 xNameReplace->replaceByName( rResourceURL, uno::Any( aProps ) );
2108 }
2109 catch ( uno::Exception& )
2110 {
2111 // do nothing, a default value is returned
2112 TOOLS_WARN_EXCEPTION("cui.customize", "Exception setting toolbar style");
2113 }
2114 }
2115
GetSystemUIName(const OUString & rResourceURL)2116 OUString ToolbarSaveInData::GetSystemUIName( const OUString& rResourceURL )
2117 {
2118 OUString result;
2119
2120 if ( rResourceURL.startsWith( "private" ) &&
2121 m_xPersistentWindowState.is() &&
2122 m_xPersistentWindowState->hasByName( rResourceURL ) )
2123 {
2124 try
2125 {
2126 uno::Sequence< beans::PropertyValue > aProps;
2127 uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) );
2128
2129 if ( a >>= aProps )
2130 {
2131 for (beans::PropertyValue const& prop : aProps)
2132 {
2133 if ( prop.Name == ITEM_DESCRIPTOR_UINAME )
2134 {
2135 prop.Value >>= result;
2136 }
2137 }
2138 }
2139 }
2140 catch ( uno::Exception& )
2141 {
2142 // do nothing, an empty UIName will be returned
2143 }
2144 }
2145
2146 if ( rResourceURL.startsWith( ".uno" ) &&
2147 m_xCommandToLabelMap.is() &&
2148 m_xCommandToLabelMap->hasByName( rResourceURL ) )
2149 {
2150 uno::Any a;
2151 try
2152 {
2153 a = m_xCommandToLabelMap->getByName( rResourceURL );
2154
2155 uno::Sequence< beans::PropertyValue > aPropSeq;
2156 if ( a >>= aPropSeq )
2157 {
2158 for (beans::PropertyValue const& prop : aPropSeq)
2159 {
2160 if ( prop.Name == ITEM_DESCRIPTOR_LABEL )
2161 {
2162 prop.Value >>= result;
2163 }
2164 }
2165 }
2166 }
2167 catch ( uno::Exception& )
2168 {
2169 // not a system command name
2170 }
2171 }
2172
2173 return result;
2174 }
2175
GetEntries()2176 SvxEntries* ToolbarSaveInData::GetEntries()
2177 {
2178 typedef std::unordered_map<OUString, bool > ToolbarInfo;
2179
2180 ToolbarInfo aToolbarInfo;
2181
2182 if ( pRootEntry == nullptr )
2183 {
2184
2185 pRootEntry.reset( new SvxConfigEntry( u"MainToolbars"_ustr, OUString(), true, /*bParentData*/false) );
2186
2187 const uno::Sequence< uno::Sequence < beans::PropertyValue > > info =
2188 GetConfigManager()->getUIElementsInfo(
2189 css::ui::UIElementType::TOOLBAR );
2190
2191 for ( uno::Sequence<beans::PropertyValue> const & props : info )
2192 {
2193 OUString url;
2194 OUString systemname;
2195 OUString uiname;
2196
2197 for ( const beans::PropertyValue& prop : props )
2198 {
2199 if ( prop.Name == ITEM_DESCRIPTOR_RESOURCEURL )
2200 {
2201 prop.Value >>= url;
2202 systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
2203 }
2204 else if ( prop.Name == ITEM_DESCRIPTOR_UINAME )
2205 {
2206 prop.Value >>= uiname;
2207 }
2208 }
2209
2210 try
2211 {
2212 uno::Reference< container::XIndexAccess > xToolbarSettings =
2213 GetConfigManager()->getSettings( url, false );
2214
2215 if ( uiname.isEmpty() )
2216 {
2217 // try to get the name from m_xPersistentWindowState
2218 uiname = GetSystemUIName( url );
2219
2220 if ( uiname.isEmpty() )
2221 {
2222 uiname = systemname;
2223 }
2224 }
2225
2226 SvxConfigEntry* pEntry = new SvxConfigEntry(
2227 uiname, url, true, /*bParentData*/false );
2228
2229 pEntry->SetMain();
2230 pEntry->SetStyle( GetSystemStyle( url ) );
2231
2232
2233 // insert into std::unordered_map to filter duplicates from the parent
2234 aToolbarInfo.emplace( systemname, true );
2235
2236 if ( systemname.startsWith( CUSTOM_TOOLBAR_STR ) )
2237 {
2238 pEntry->SetUserDefined();
2239 }
2240 else
2241 {
2242 pEntry->SetUserDefined( false );
2243 }
2244
2245 pRootEntry->GetEntries()->push_back( pEntry );
2246
2247 LoadToolbar( xToolbarSettings, pEntry );
2248 }
2249 catch ( container::NoSuchElementException& )
2250 {
2251 // TODO, handle resourceURL with no settings
2252 }
2253 }
2254
2255 uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager();
2256 if ( xParentCfgMgr.is() )
2257 {
2258 // Retrieve also the parent toolbars to make it possible
2259 // to configure module toolbars and save them into the document
2260 // config manager.
2261 const uno::Sequence< uno::Sequence < beans::PropertyValue > > info_ =
2262 xParentCfgMgr->getUIElementsInfo(
2263 css::ui::UIElementType::TOOLBAR );
2264
2265 for ( uno::Sequence<beans::PropertyValue> const & props : info_ )
2266 {
2267 OUString url;
2268 OUString systemname;
2269 OUString uiname;
2270
2271 for ( const beans::PropertyValue& prop : props )
2272 {
2273 if ( prop.Name == ITEM_DESCRIPTOR_RESOURCEURL )
2274 {
2275 prop.Value >>= url;
2276 systemname = url.copy( url.lastIndexOf( '/' ) + 1 );
2277 }
2278 else if ( prop.Name == ITEM_DESCRIPTOR_UINAME )
2279 {
2280 prop.Value >>= uiname;
2281 }
2282 }
2283
2284 // custom toolbars of the parent are not visible in the document layer
2285 OUString custom(CUSTOM_TOOLBAR_STR);
2286 if ( systemname.startsWith( custom ) )
2287 continue;
2288
2289 // check if toolbar is already in the document layer
2290 ToolbarInfo::const_iterator pIter = aToolbarInfo.find( systemname );
2291 if ( pIter == aToolbarInfo.end() )
2292 {
2293 aToolbarInfo.emplace( systemname, true );
2294
2295 try
2296 {
2297 uno::Reference< container::XIndexAccess > xToolbarSettings =
2298 xParentCfgMgr->getSettings( url, false );
2299
2300 if ( uiname.isEmpty() )
2301 {
2302 // try to get the name from m_xPersistentWindowState
2303 uiname = GetSystemUIName( url );
2304
2305 if ( uiname.isEmpty() )
2306 {
2307 uiname = systemname;
2308 }
2309 }
2310
2311 SvxConfigEntry* pEntry = new SvxConfigEntry(
2312 uiname, url, true, true );
2313
2314 pEntry->SetMain();
2315 pEntry->SetStyle( GetSystemStyle( url ) );
2316
2317 if ( systemname.startsWith( custom ) )
2318 {
2319 pEntry->SetUserDefined();
2320 }
2321 else
2322 {
2323 pEntry->SetUserDefined( false );
2324 }
2325
2326 pRootEntry->GetEntries()->push_back( pEntry );
2327
2328 LoadToolbar( xToolbarSettings, pEntry );
2329 }
2330 catch ( container::NoSuchElementException& )
2331 {
2332 // TODO, handle resourceURL with no settings
2333 }
2334 }
2335 }
2336 }
2337
2338 std::sort( GetEntries()->begin(), GetEntries()->end(), SvxConfigPageHelper::EntrySort );
2339 }
2340
2341 return pRootEntry->GetEntries();
2342 }
2343
2344 void
SetEntries(std::unique_ptr<SvxEntries> pNewEntries)2345 ToolbarSaveInData::SetEntries( std::unique_ptr<SvxEntries> pNewEntries )
2346 {
2347 pRootEntry->SetEntries( std::move(pNewEntries) );
2348 }
2349
2350 bool
HasURL(const OUString & rURL)2351 ToolbarSaveInData::HasURL( const OUString& rURL )
2352 {
2353 for (auto const& entry : *GetEntries())
2354 {
2355 if (entry->GetCommand() == rURL)
2356 {
2357 return !entry->IsParentData();
2358 }
2359 }
2360 return false;
2361 }
2362
HasSettings()2363 bool ToolbarSaveInData::HasSettings()
2364 {
2365 // return true if there is at least one toolbar entry
2366 return !GetEntries()->empty();
2367 }
2368
Reset()2369 void ToolbarSaveInData::Reset()
2370 {
2371 // reset each toolbar by calling removeSettings for its toolbar URL
2372 for (auto const& entry : *GetEntries())
2373 {
2374 try
2375 {
2376 const OUString& url = entry->GetCommand();
2377 GetConfigManager()->removeSettings( url );
2378 }
2379 catch ( uno::Exception& )
2380 {
2381 // error occurred removing the settings
2382 // TODO - add error dialog in future?
2383 }
2384 }
2385
2386 // persist changes to toolbar storage
2387 PersistChanges( GetConfigManager() );
2388
2389 // now delete the root SvxConfigEntry the next call to GetEntries()
2390 // causes it to be reinitialised
2391 pRootEntry.reset();
2392
2393 // reset all icons to default
2394 try
2395 {
2396 GetImageManager()->reset();
2397 PersistChanges( GetImageManager() );
2398 }
2399 catch ( uno::Exception& )
2400 {
2401 SAL_WARN("cui.customize", "Error resetting all icons when resetting toolbars");
2402 }
2403 }
2404
Apply()2405 bool ToolbarSaveInData::Apply()
2406 {
2407 // toolbar changes are instantly applied
2408 return false;
2409 }
2410
ApplyToolbar(uno::Reference<container::XIndexContainer> const & rToolbarBar,uno::Reference<lang::XSingleComponentFactory> & rFactory,SvxConfigEntry const * pToolbarData)2411 void ToolbarSaveInData::ApplyToolbar(
2412 uno::Reference< container::XIndexContainer > const & rToolbarBar,
2413 uno::Reference< lang::XSingleComponentFactory >& rFactory,
2414 SvxConfigEntry const * pToolbarData )
2415 {
2416 uno::Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2417
2418 for (auto const& entry : *pToolbarData->GetEntries())
2419 {
2420 if (entry->IsPopup())
2421 {
2422 uno::Sequence< beans::PropertyValue > aPropValueSeq =
2423 SvxConfigPageHelper::ConvertToolbarEntry(entry);
2424
2425 uno::Reference< container::XIndexContainer > xSubMenuBar(
2426 rFactory->createInstanceWithContext( xContext ),
2427 uno::UNO_QUERY );
2428
2429 sal_Int32 nIndex = aPropValueSeq.getLength();
2430 aPropValueSeq.realloc( nIndex + 1 );
2431 auto pPropValueSeq = aPropValueSeq.getArray();
2432 pPropValueSeq[nIndex].Name = m_aDescriptorContainer;
2433 pPropValueSeq[nIndex].Value <<= xSubMenuBar;
2434 rToolbarBar->insertByIndex(
2435 rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
2436
2437 ApplyToolbar(xSubMenuBar, rFactory, entry);
2438 }
2439 else if (entry->IsSeparator())
2440 {
2441 rToolbarBar->insertByIndex(
2442 rToolbarBar->getCount(), uno::Any( m_aSeparatorSeq ));
2443 }
2444 else
2445 {
2446 uno::Sequence< beans::PropertyValue > aPropValueSeq =
2447 SvxConfigPageHelper::ConvertToolbarEntry(entry);
2448
2449 rToolbarBar->insertByIndex(
2450 rToolbarBar->getCount(), uno::Any( aPropValueSeq ));
2451 }
2452 }
2453 }
2454
ApplyToolbar(SvxConfigEntry * pToolbar)2455 void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry* pToolbar )
2456 {
2457 // Apply new toolbar structure to our settings container
2458 uno::Reference< container::XIndexAccess > xSettings =
2459 GetConfigManager()->createSettings();
2460
2461 uno::Reference< container::XIndexContainer > xIndexContainer (
2462 xSettings, uno::UNO_QUERY );
2463
2464 uno::Reference< lang::XSingleComponentFactory > xFactory (
2465 xSettings, uno::UNO_QUERY );
2466
2467 ApplyToolbar( xIndexContainer, xFactory, pToolbar );
2468
2469 uno::Reference< beans::XPropertySet > xProps(
2470 xSettings, uno::UNO_QUERY );
2471
2472 if ( pToolbar->IsUserDefined() )
2473 {
2474 xProps->setPropertyValue(
2475 ITEM_DESCRIPTOR_UINAME,
2476 uno::Any( pToolbar->GetName() ) );
2477 }
2478
2479 try
2480 {
2481 if ( GetConfigManager()->hasSettings( pToolbar->GetCommand() ) )
2482 {
2483 GetConfigManager()->replaceSettings(
2484 pToolbar->GetCommand(), xSettings );
2485 }
2486 else
2487 {
2488 GetConfigManager()->insertSettings(
2489 pToolbar->GetCommand(), xSettings );
2490 if ( pToolbar->IsParentData() )
2491 pToolbar->SetParentData( false );
2492 }
2493 }
2494 catch ( css::uno::Exception const & )
2495 {
2496 TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings");
2497 }
2498
2499 PersistChanges( GetConfigManager() );
2500 }
2501
CreateToolbar(SvxConfigEntry * pToolbar)2502 void ToolbarSaveInData::CreateToolbar( SvxConfigEntry* pToolbar )
2503 {
2504 // show the new toolbar in the UI also
2505 uno::Reference< container::XIndexAccess >
2506 xSettings = GetConfigManager()->createSettings();
2507
2508 uno::Reference< beans::XPropertySet >
2509 xPropertySet( xSettings, uno::UNO_QUERY );
2510
2511 xPropertySet->setPropertyValue(
2512 ITEM_DESCRIPTOR_UINAME,
2513 uno::Any( pToolbar->GetName() ) );
2514
2515 try
2516 {
2517 GetConfigManager()->insertSettings( pToolbar->GetCommand(), xSettings );
2518 }
2519 catch ( css::uno::Exception const & )
2520 {
2521 TOOLS_WARN_EXCEPTION("cui.customize", "caught exception saving settings");
2522 }
2523
2524 GetEntries()->push_back( pToolbar );
2525
2526 PersistChanges( GetConfigManager() );
2527 }
2528
RemoveToolbar(SvxConfigEntry * pToolbar)2529 void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry* pToolbar )
2530 {
2531 try
2532 {
2533 OUString url = pToolbar->GetCommand();
2534 GetConfigManager()->removeSettings( url );
2535 SvxConfigPageHelper::RemoveEntry( GetEntries(), pToolbar );
2536 delete pToolbar;
2537
2538 PersistChanges( GetConfigManager() );
2539
2540 // remove the persistent window state data
2541 css::uno::Reference< css::container::XNameContainer > xNameContainer(
2542 m_xPersistentWindowState, css::uno::UNO_QUERY_THROW );
2543
2544 xNameContainer->removeByName( url );
2545 }
2546 catch ( uno::Exception& )
2547 {
2548 // error occurred removing the settings
2549 }
2550 }
2551
RestoreToolbar(SvxConfigEntry * pToolbar)2552 void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry* pToolbar )
2553 {
2554 OUString url = pToolbar->GetCommand();
2555
2556 // Restore of toolbar is done by removing it from
2557 // its configuration manager and then getting it again
2558 bool bParentToolbar = pToolbar->IsParentData();
2559
2560 // Cannot restore parent toolbar
2561 if ( bParentToolbar )
2562 return;
2563
2564 try
2565 {
2566 GetConfigManager()->removeSettings( url );
2567 pToolbar->GetEntries()->clear();
2568 PersistChanges( GetConfigManager() );
2569 }
2570 catch ( uno::Exception& )
2571 {
2572 // if an error occurs removing the settings then just return
2573 return;
2574 }
2575
2576 // Now reload the toolbar settings
2577 try
2578 {
2579 uno::Reference< container::XIndexAccess > xToolbarSettings;
2580 if ( IsDocConfig() )
2581 {
2582 xToolbarSettings = GetParentConfigManager()->getSettings( url, false );
2583 pToolbar->SetParentData();
2584 }
2585 else
2586 xToolbarSettings = GetConfigManager()->getSettings( url, false );
2587
2588 LoadToolbar( xToolbarSettings, pToolbar );
2589
2590 // After reloading, ensure that the icon is reset of each entry
2591 // in the toolbar
2592 uno::Sequence< OUString > aURLSeq( 1 );
2593 auto pURLSeq = aURLSeq.getArray();
2594 for (auto const& entry : *pToolbar->GetEntries())
2595 {
2596 pURLSeq[ 0 ] = entry->GetCommand();
2597
2598 try
2599 {
2600 GetImageManager()->removeImages( SvxConfigPageHelper::GetImageType(), aURLSeq );
2601 }
2602 catch ( uno::Exception& )
2603 {
2604 SAL_WARN("cui.customize", "Error restoring icon when resetting toolbar");
2605 }
2606 }
2607 PersistChanges( GetImageManager() );
2608 }
2609 catch ( container::NoSuchElementException& )
2610 {
2611 // cannot find the resource URL after removing it
2612 // so no entry will appear in the toolbar list
2613 }
2614 }
2615
LoadToolbar(const uno::Reference<container::XIndexAccess> & xToolbarSettings,SvxConfigEntry const * pParentData)2616 void ToolbarSaveInData::LoadToolbar(
2617 const uno::Reference< container::XIndexAccess >& xToolbarSettings,
2618 SvxConfigEntry const * pParentData )
2619 {
2620 SvxEntries* pEntries = pParentData->GetEntries();
2621
2622 for ( sal_Int32 nIndex = 0; nIndex < xToolbarSettings->getCount(); ++nIndex )
2623 {
2624 OUString aCommandURL;
2625 OUString aLabel;
2626 bool bIsVisible;
2627 sal_Int32 nStyle;
2628
2629 sal_uInt16 nType( css::ui::ItemType::DEFAULT );
2630
2631 bool bItem = SvxConfigPageHelper::GetToolbarItemData( xToolbarSettings, nIndex, aCommandURL,
2632 aLabel, nType, bIsVisible, nStyle );
2633
2634 if ( bItem )
2635 {
2636 bool bIsUserDefined = true;
2637
2638 if ( nType == css::ui::ItemType::DEFAULT )
2639 {
2640 uno::Any a;
2641 try
2642 {
2643 a = m_xCommandToLabelMap->getByName( aCommandURL );
2644 bIsUserDefined = false;
2645 }
2646 catch ( container::NoSuchElementException& )
2647 {
2648 bIsUserDefined = true;
2649 }
2650
2651 bool bUseDefaultLabel = false;
2652 // If custom label not set retrieve it from the command
2653 // to info service
2654 if ( aLabel.isEmpty() )
2655 {
2656 bUseDefaultLabel = true;
2657 uno::Sequence< beans::PropertyValue > aPropSeq;
2658 if ( a >>= aPropSeq )
2659 {
2660 for (beans::PropertyValue const& prop : aPropSeq)
2661 {
2662 if ( prop.Name == "Name" )
2663 {
2664 prop.Value >>= aLabel;
2665 break;
2666 }
2667 }
2668 }
2669 }
2670
2671 SvxConfigEntry* pEntry = new SvxConfigEntry(
2672 aLabel, aCommandURL, false, /*bParentData*/false );
2673
2674 pEntry->SetUserDefined( bIsUserDefined );
2675 pEntry->SetVisible( bIsVisible );
2676 pEntry->SetStyle( nStyle );
2677
2678 if ( !bUseDefaultLabel )
2679 pEntry->SetName( aLabel );
2680
2681 pEntries->push_back( pEntry );
2682 }
2683 else
2684 {
2685 SvxConfigEntry* pEntry = new SvxConfigEntry;
2686 pEntry->SetUserDefined( bIsUserDefined );
2687 pEntries->push_back( pEntry );
2688 }
2689 }
2690 }
2691 }
2692
SvxNewToolbarDialog(weld::Window * pWindow,const OUString & rName)2693 SvxNewToolbarDialog::SvxNewToolbarDialog(weld::Window* pWindow, const OUString& rName)
2694 : GenericDialogController(pWindow, u"cui/ui/newtoolbardialog.ui"_ustr, u"NewToolbarDialog"_ustr)
2695 , m_xEdtName(m_xBuilder->weld_entry(u"edit"_ustr))
2696 , m_xSaveInListBox(m_xBuilder->weld_combo_box(u"savein"_ustr))
2697 {
2698 m_xEdtName->set_text(rName);
2699 m_xEdtName->select_region(0, -1);
2700 }
2701
~SvxNewToolbarDialog()2702 SvxNewToolbarDialog::~SvxNewToolbarDialog()
2703 {
2704 }
2705
2706 /*******************************************************************************
2707 *
2708 * The SvxIconSelectorDialog class
2709 *
2710 *******************************************************************************/
SvxIconSelectorDialog(weld::Window * pWindow,uno::Reference<css::ui::XImageManager> xImageManager,uno::Reference<css::ui::XImageManager> xParentImageManager)2711 SvxIconSelectorDialog::SvxIconSelectorDialog(weld::Window *pWindow,
2712 uno::Reference< css::ui::XImageManager > xImageManager,
2713 uno::Reference< css::ui::XImageManager > xParentImageManager)
2714 : GenericDialogController(pWindow, u"cui/ui/iconselectordialog.ui"_ustr, u"IconSelector"_ustr)
2715 , m_xImageManager(std::move(xImageManager))
2716 , m_xParentImageManager(std::move(xParentImageManager))
2717 , m_xTbSymbol(new ValueSet(m_xBuilder->weld_scrolled_window(u"symbolswin"_ustr, true)))
2718 , m_xTbSymbolWin(new weld::CustomWeld(*m_xBuilder, u"symbolsToolbar"_ustr, *m_xTbSymbol))
2719 , m_xFtNote(m_xBuilder->weld_label(u"noteLabel"_ustr))
2720 , m_xBtnImport(m_xBuilder->weld_button(u"importButton"_ustr))
2721 , m_xBtnDelete(m_xBuilder->weld_button(u"deleteButton"_ustr))
2722 {
2723 typedef std::unordered_map< OUString, bool > ImageInfo;
2724
2725 m_nExpectedSize = 16;
2726 if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_LARGE)
2727 m_nExpectedSize = 24;
2728 else if (SvxConfigPageHelper::GetImageType() & css::ui::ImageType::SIZE_32)
2729 m_nExpectedSize = 32;
2730
2731 if ( m_nExpectedSize != 16 )
2732 {
2733 m_xFtNote->set_label(SvxConfigPageHelper::replaceSixteen(m_xFtNote->get_label(), m_nExpectedSize));
2734 }
2735
2736 m_xTbSymbol->SetStyle(m_xTbSymbol->GetStyle() | WB_ITEMBORDER | WB_VSCROLL);
2737 m_xTbSymbol->SetColCount(11);
2738 m_xTbSymbol->SetLineCount(5);
2739 m_xTbSymbol->SetItemWidth(m_nExpectedSize);
2740 m_xTbSymbol->SetItemHeight(m_nExpectedSize);
2741 m_xTbSymbol->SetExtraSpacing(6);
2742 Size aSize(m_xTbSymbol->CalcWindowSizePixel(Size(m_nExpectedSize, m_nExpectedSize), 11, 5));
2743 m_xTbSymbol->set_size_request(aSize.Width(), aSize.Height());
2744
2745 uno::Reference< uno::XComponentContext > xComponentContext =
2746 ::comphelper::getProcessComponentContext();
2747
2748 m_xGraphProvider.set( graphic::GraphicProvider::create( xComponentContext ) );
2749
2750 uno::Reference< css::util::XPathSettings > xPathSettings =
2751 css::util::thePathSettings::get( xComponentContext );
2752
2753
2754 OUString aDirectory = xPathSettings->getUserConfig();
2755
2756 sal_Int32 aCount = aDirectory.getLength();
2757
2758 if ( aCount > 0 )
2759 {
2760 sal_Unicode aChar = aDirectory[ aCount-1 ];
2761 if ( aChar != '/')
2762 {
2763 aDirectory += "/";
2764 }
2765 }
2766 else
2767 {
2768 m_xBtnImport->set_sensitive(false);
2769 }
2770
2771 aDirectory += "soffice.cfg/import";
2772
2773 uno::Reference< lang::XSingleServiceFactory > xStorageFactory(
2774 css::embed::FileSystemStorageFactory::create( xComponentContext ) );
2775
2776 uno::Sequence< uno::Any > aArgs{ uno::Any(aDirectory),
2777 uno::Any(css::embed::ElementModes::READWRITE) };
2778
2779 uno::Reference< css::embed::XStorage > xStorage(
2780 xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY );
2781
2782 uno::Sequence<uno::Any> aProp(comphelper::InitAnyPropertySequence(
2783 {
2784 {"UserConfigStorage", uno::Any(xStorage)},
2785 {"OpenMode", uno::Any(css::embed::ElementModes::READWRITE)}
2786 }));
2787 m_xImportedImageManager = css::ui::ImageManager::create( xComponentContext );
2788 m_xImportedImageManager->initialize(aProp);
2789
2790 ImageInfo aImageInfo1;
2791 if ( m_xImportedImageManager.is() )
2792 {
2793 const uno::Sequence< OUString > names = m_xImportedImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2794 for (auto const & name : names )
2795 aImageInfo1.emplace( name, false );
2796 }
2797
2798 uno::Sequence< OUString > name( 1 );
2799 auto pname = name.getArray();
2800 for (auto const& elem : aImageInfo1)
2801 {
2802 pname[ 0 ] = elem.first;
2803 uno::Sequence< uno::Reference< graphic::XGraphic> > graphics = m_xImportedImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2804 if ( graphics.hasElements() )
2805 {
2806 m_aGraphics.push_back(graphics[0]);
2807 Image img(graphics[0]);
2808 m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first);
2809 }
2810 }
2811
2812 ImageInfo aImageInfo;
2813
2814 if ( m_xParentImageManager.is() )
2815 {
2816 const uno::Sequence< OUString > names = m_xParentImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2817 for ( auto const & i : names )
2818 aImageInfo.emplace( i, false );
2819 }
2820
2821 const uno::Sequence< OUString > names = m_xImageManager->getAllImageNames( SvxConfigPageHelper::GetImageType() );
2822 for ( auto const & i : names )
2823 {
2824 ImageInfo::iterator pIter = aImageInfo.find( i );
2825 if ( pIter != aImageInfo.end() )
2826 pIter->second = true;
2827 else
2828 aImageInfo.emplace( i, true );
2829 }
2830
2831 // large growth factor, expecting many entries
2832 for (auto const& elem : aImageInfo)
2833 {
2834 pname[ 0 ] = elem.first;
2835
2836 uno::Sequence< uno::Reference< graphic::XGraphic> > graphics;
2837 try
2838 {
2839 if (elem.second)
2840 graphics = m_xImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2841 else
2842 graphics = m_xParentImageManager->getImages( SvxConfigPageHelper::GetImageType(), name );
2843 }
2844 catch ( uno::Exception& )
2845 {
2846 // can't get sequence for this name so it will not be
2847 // added to the list
2848 }
2849
2850 if ( graphics.hasElements() )
2851 {
2852 Image img(graphics[0]);
2853 if (!img.GetBitmapEx().IsEmpty())
2854 {
2855 m_aGraphics.push_back(graphics[0]);
2856 m_xTbSymbol->InsertItem(m_aGraphics.size(), img, elem.first);
2857 }
2858 }
2859 }
2860
2861 m_xBtnDelete->set_sensitive( false );
2862 m_xTbSymbol->SetSelectHdl( LINK(this, SvxIconSelectorDialog, SelectHdl) );
2863 m_xBtnImport->connect_clicked( LINK(this, SvxIconSelectorDialog, ImportHdl) );
2864 m_xBtnDelete->connect_clicked( LINK(this, SvxIconSelectorDialog, DeleteHdl) );
2865 }
2866
~SvxIconSelectorDialog()2867 SvxIconSelectorDialog::~SvxIconSelectorDialog()
2868 {
2869 }
2870
GetSelectedIcon()2871 uno::Reference< graphic::XGraphic> SvxIconSelectorDialog::GetSelectedIcon()
2872 {
2873 uno::Reference<graphic::XGraphic> result;
2874
2875 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2876
2877 if (nId)
2878 {
2879 result = m_aGraphics[nId - 1];
2880 }
2881
2882 return result;
2883 }
2884
IMPL_LINK_NOARG(SvxIconSelectorDialog,SelectHdl,ValueSet *,void)2885 IMPL_LINK_NOARG(SvxIconSelectorDialog, SelectHdl, ValueSet*, void)
2886 {
2887 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2888
2889 if (!nId)
2890 {
2891 m_xBtnDelete->set_sensitive(false);
2892 return;
2893 }
2894
2895 OUString aSelImageText = m_xTbSymbol->GetItemText(nId);
2896 if (m_xImportedImageManager->hasImage(SvxConfigPageHelper::GetImageType(), aSelImageText))
2897 {
2898 m_xBtnDelete->set_sensitive(true);
2899 }
2900 else
2901 {
2902 m_xBtnDelete->set_sensitive(false);
2903 }
2904 }
2905
IMPL_LINK_NOARG(SvxIconSelectorDialog,ImportHdl,weld::Button &,void)2906 IMPL_LINK_NOARG(SvxIconSelectorDialog, ImportHdl, weld::Button&, void)
2907 {
2908 sfx2::FileDialogHelper aImportDialog(
2909 css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
2910 FileDialogFlags::Graphic | FileDialogFlags::MultiSelection, m_xDialog.get());
2911 aImportDialog.SetContext(sfx2::FileDialogHelper::IconImport);
2912
2913 // disable the link checkbox in the dialog
2914 uno::Reference< css::ui::dialogs::XFilePickerControlAccess >
2915 xController( aImportDialog.GetFilePicker(), uno::UNO_QUERY);
2916 if ( xController.is() )
2917 {
2918 xController->enableControl(
2919 css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK,
2920 false);
2921 }
2922
2923 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
2924 sal_uInt16 nFilter = rFilter.GetImportFormatNumberForShortName(u"png");
2925 aImportDialog.SetCurrentFilter(rFilter.GetImportFormatName(nFilter));
2926
2927 if ( ERRCODE_NONE == aImportDialog.Execute() )
2928 {
2929 uno::Sequence< OUString > paths = aImportDialog.GetMPath();
2930 ImportGraphics ( paths );
2931 }
2932 }
2933
IMPL_LINK_NOARG(SvxIconSelectorDialog,DeleteHdl,weld::Button &,void)2934 IMPL_LINK_NOARG(SvxIconSelectorDialog, DeleteHdl, weld::Button&, void)
2935 {
2936 OUString message = CuiResId( RID_CUISTR_DELETE_ICON_CONFIRM );
2937
2938 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xDialog.get(),
2939 VclMessageType::Warning, VclButtonsType::OkCancel,
2940 message));
2941 if (xWarn->run() != RET_OK)
2942 return;
2943
2944 sal_uInt16 nId = m_xTbSymbol->GetSelectedItemId();
2945
2946 uno::Sequence<OUString> URLs { m_xTbSymbol->GetItemText(nId) };
2947 m_xTbSymbol->RemoveItem(nId);
2948 m_xImportedImageManager->removeImages( SvxConfigPageHelper::GetImageType(), URLs );
2949 if ( m_xImportedImageManager->isModified() )
2950 {
2951 m_xImportedImageManager->store();
2952 }
2953 }
2954
ReplaceGraphicItem(const OUString & aURL)2955 bool SvxIconSelectorDialog::ReplaceGraphicItem(
2956 const OUString& aURL )
2957 {
2958 uno::Reference< graphic::XGraphic > xGraphic;
2959 uno::Sequence< beans::PropertyValue > aMediaProps{ comphelper::makePropertyValue(u"URL"_ustr, aURL) };
2960
2961 css::awt::Size aSize;
2962 bool bOK = false;
2963 try
2964 {
2965 xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
2966
2967 uno::Reference< beans::XPropertySet > props =
2968 m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
2969 uno::Any a = props->getPropertyValue( u"SizePixel"_ustr );
2970 a >>= aSize;
2971 if (0 == aSize.Width || 0 == aSize.Height)
2972 return false;
2973 else
2974 bOK = true;
2975 }
2976 catch ( uno::Exception& )
2977 {
2978 return false;
2979 }
2980
2981 bool bResult( false );
2982 size_t nCount = m_xTbSymbol->GetItemCount();
2983 for (size_t n = 0; n < nCount; ++n)
2984 {
2985 sal_uInt16 nId = m_xTbSymbol->GetItemId( n );
2986
2987 if ( m_xTbSymbol->GetItemText( nId ) == aURL )
2988 {
2989 try
2990 {
2991 // replace/insert image with provided URL
2992 size_t nPos = nId - 1;
2993 assert(nPos == m_xTbSymbol->GetItemPos(nId));
2994 m_xTbSymbol->RemoveItem(nId);
2995
2996 Image aImage( xGraphic );
2997 if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
2998 {
2999 BitmapEx aBitmap = aImage.GetBitmapEx();
3000 BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
3001 aImage = Image( aBitmapex);
3002 }
3003 m_xTbSymbol->InsertItem(nId, aImage, aURL, nPos); //modify
3004
3005 m_aGraphics[nPos] = Graphic(aImage.GetBitmapEx()).GetXGraphic();
3006
3007 m_xImportedImageManager->replaceImages( SvxConfigPageHelper::GetImageType(), { aURL }, { xGraphic } );
3008 m_xImportedImageManager->store();
3009
3010 bResult = true;
3011 break;
3012 }
3013 catch ( css::uno::Exception& )
3014 {
3015 break;
3016 }
3017 }
3018 }
3019
3020 return bResult;
3021 }
3022
3023 namespace
3024 {
ReplaceIconName(std::u16string_view rMessage)3025 OUString ReplaceIconName(std::u16string_view rMessage)
3026 {
3027 OUString name;
3028 OUString message = CuiResId( RID_CUISTR_REPLACE_ICON_WARNING );
3029 OUString placeholder(u"%ICONNAME"_ustr );
3030 sal_Int32 pos = message.indexOf( placeholder );
3031 if ( pos != -1 )
3032 {
3033 name = message.replaceAt(
3034 pos, placeholder.getLength(), rMessage );
3035 }
3036 return name;
3037 }
3038
3039 class SvxIconReplacementDialog
3040 {
3041 private:
3042 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
3043 public:
SvxIconReplacementDialog(weld::Window * pParent,std::u16string_view rMessage,bool bYestoAll)3044 SvxIconReplacementDialog(weld::Window *pParent, std::u16string_view rMessage, bool bYestoAll)
3045 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Warning, VclButtonsType::NONE, ReplaceIconName(rMessage)))
3046 {
3047 m_xQueryBox->set_title(CuiResId(RID_CUISTR_REPLACE_ICON_CONFIRM));
3048 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Yes), 2);
3049 if (bYestoAll)
3050 m_xQueryBox->add_button(CuiResId(RID_CUISTR_YESTOALL), 5);
3051 m_xQueryBox->add_button(GetStandardText(StandardButtonType::No), 4);
3052 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), 6);
3053 m_xQueryBox->set_default_response(2);
3054 }
run()3055 short run() { return m_xQueryBox->run(); }
3056 };
3057 }
3058
ImportGraphics(const uno::Sequence<OUString> & rPaths)3059 void SvxIconSelectorDialog::ImportGraphics(
3060 const uno::Sequence< OUString >& rPaths )
3061 {
3062 std::vector< OUString > rejected( rPaths.getLength() );
3063 sal_Int32 rejectedCount = 0;
3064
3065 sal_uInt16 ret = 0;
3066 sal_Int32 aIndex;
3067 OUString aIconName;
3068
3069 if ( rPaths.getLength() == 1 )
3070 {
3071 if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), rPaths[0] ) )
3072 {
3073 aIndex = rPaths[0].lastIndexOf( '/' );
3074 aIconName = rPaths[0].copy( aIndex+1 );
3075 SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, false);
3076 ret = aDlg.run();
3077 if ( ret == 2 )
3078 {
3079 ReplaceGraphicItem( rPaths[0] );
3080 }
3081 }
3082 else
3083 {
3084 if ( !ImportGraphic( rPaths[0] ) )
3085 {
3086 rejected[0] = rPaths[0];
3087 rejectedCount = 1;
3088 }
3089 }
3090 }
3091 else
3092 {
3093 OUString aSourcePath( rPaths[0] );
3094 if ( rPaths[0].lastIndexOf( '/' ) != rPaths[0].getLength() -1 )
3095 aSourcePath = rPaths[0] + "/";
3096
3097 for ( sal_Int32 i = 1; i < rPaths.getLength(); ++i )
3098 {
3099 OUString aPath = aSourcePath + rPaths[i];
3100 if ( m_xImportedImageManager->hasImage( SvxConfigPageHelper::GetImageType(), aPath ) )
3101 {
3102 aIndex = rPaths[i].lastIndexOf( '/' );
3103 aIconName = rPaths[i].copy( aIndex+1 );
3104 SvxIconReplacementDialog aDlg(m_xDialog.get(), aIconName, true);
3105 ret = aDlg.run();
3106 if ( ret == 2 )
3107 {
3108 ReplaceGraphicItem( aPath );
3109 }
3110 else if ( ret == 5 )
3111 {
3112 for ( sal_Int32 k = i; k < rPaths.getLength(); ++k )
3113 {
3114 aPath = aSourcePath + rPaths[k];
3115 bool bHasReplaced = ReplaceGraphicItem( aPath );
3116
3117 if ( !bHasReplaced )
3118 {
3119 bool result = ImportGraphic( aPath );
3120 if ( !result )
3121 {
3122 rejected[ rejectedCount ] = rPaths[i];
3123 ++rejectedCount;
3124 }
3125 }
3126 }
3127 break;
3128 }
3129 }
3130 else
3131 {
3132 bool result = ImportGraphic( aSourcePath + rPaths[i] );
3133 if ( !result )
3134 {
3135 rejected[ rejectedCount ] = rPaths[i];
3136 ++rejectedCount;
3137 }
3138 }
3139 }
3140 }
3141
3142 if ( rejectedCount == 0 )
3143 return;
3144
3145 OUStringBuffer message;
3146 OUString fPath;
3147 if (rejectedCount > 1)
3148 fPath = OUString::Concat(rPaths[0].subView(8)) + "/";
3149 for ( sal_Int32 i = 0; i < rejectedCount; ++i )
3150 {
3151 message.append(fPath + rejected[i] + "\n");
3152 }
3153
3154 SvxIconChangeDialog aDialog(m_xDialog.get(), message.makeStringAndClear());
3155 aDialog.run();
3156 }
3157
ImportGraphic(const OUString & aURL)3158 bool SvxIconSelectorDialog::ImportGraphic( const OUString& aURL )
3159 {
3160 bool result = false;
3161
3162 uno::Sequence< beans::PropertyValue > aMediaProps{ comphelper::makePropertyValue(u"URL"_ustr, aURL) };
3163
3164 try
3165 {
3166 uno::Reference< beans::XPropertySet > props =
3167 m_xGraphProvider->queryGraphicDescriptor( aMediaProps );
3168
3169 uno::Any a = props->getPropertyValue(u"SizePixel"_ustr);
3170
3171 uno::Reference< graphic::XGraphic > xGraphic = m_xGraphProvider->queryGraphic( aMediaProps );
3172 if ( xGraphic.is() )
3173 {
3174 bool bOK = true;
3175 css::awt::Size aSize;
3176
3177 a >>= aSize;
3178 if ( 0 == aSize.Width || 0 == aSize.Height )
3179 bOK = false;
3180
3181 Image aImage( xGraphic );
3182
3183 if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) )
3184 {
3185 BitmapEx aBitmap = aImage.GetBitmapEx();
3186 BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, m_nExpectedSize);
3187 aImage = Image( aBitmapex);
3188 }
3189 if ( bOK && !!aImage )
3190 {
3191 m_aGraphics.push_back(Graphic(aImage.GetBitmapEx()).GetXGraphic());
3192 m_xTbSymbol->InsertItem(m_aGraphics.size(), aImage, aURL);
3193
3194 uno::Sequence<OUString> aImportURL { aURL };
3195 uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph{ xGraphic };
3196 m_xImportedImageManager->insertImages( SvxConfigPageHelper::GetImageType(), aImportURL, aImportGraph );
3197 if ( m_xImportedImageManager->isModified() )
3198 {
3199 m_xImportedImageManager->store();
3200 }
3201
3202 result = true;
3203 }
3204 else
3205 {
3206 SAL_WARN("cui.customize", "could not create Image from XGraphic");
3207 }
3208 }
3209 else
3210 {
3211 SAL_WARN("cui.customize", "could not get query XGraphic");
3212 }
3213 }
3214 catch( uno::Exception const & )
3215 {
3216 TOOLS_WARN_EXCEPTION("cui.customize", "Caught exception importing XGraphic");
3217 }
3218 return result;
3219 }
3220
3221 /*******************************************************************************
3222 *
3223 * The SvxIconChangeDialog class added for issue83555
3224 *
3225 *******************************************************************************/
SvxIconChangeDialog(weld::Window * pWindow,const OUString & rMessage)3226 SvxIconChangeDialog::SvxIconChangeDialog(weld::Window *pWindow, const OUString& rMessage)
3227 : MessageDialogController(pWindow, u"cui/ui/iconchangedialog.ui"_ustr, u"IconChange"_ustr, u"grid"_ustr)
3228 , m_xLineEditDescription(m_xBuilder->weld_text_view(u"addrTextview"_ustr))
3229 {
3230 m_xLineEditDescription->set_size_request(m_xLineEditDescription->get_approximate_digit_width() * 48,
3231 m_xLineEditDescription->get_text_height() * 8);
3232 m_xLineEditDescription->set_text(rMessage);
3233 }
3234
SvxConfigPageFunctionDropTarget(SvxConfigPage & rPage,weld::TreeView & rTreeView)3235 SvxConfigPageFunctionDropTarget::SvxConfigPageFunctionDropTarget(SvxConfigPage&rPage, weld::TreeView& rTreeView)
3236 : weld::ReorderingDropTarget(rTreeView)
3237 , m_rPage(rPage)
3238 {
3239 }
3240
ExecuteDrop(const ExecuteDropEvent & rEvt)3241 sal_Int8 SvxConfigPageFunctionDropTarget::ExecuteDrop(const ExecuteDropEvent& rEvt)
3242 {
3243 sal_Int8 nRet = weld::ReorderingDropTarget::ExecuteDrop(rEvt);
3244 m_rPage.ListModified();
3245 return nRet;;
3246 }
3247
3248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3249