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