tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sfx2 / source / sidebar / ResourceManager.cxx
blobcf333c1b0a8f071a76f4d696cca16ececf192eac
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sidebar/DeckDescriptor.hxx>
21 #include <sidebar/PanelDescriptor.hxx>
22 #include <sfx2/sidebar/ResourceManager.hxx>
23 #include <sidebar/Tools.hxx>
25 #include <officecfg/Office/Common.hxx>
26 #include <officecfg/Office/UI/Sidebar.hxx>
27 #include <unotools/confignode.hxx>
28 #include <comphelper/lok.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/namedvaluecollection.hxx>
31 #include <comphelper/sequence.hxx>
32 #include <comphelper/types.hxx>
34 #include <comphelper/diagnose_ex.hxx>
35 #include <sal/log.hxx>
36 #include <vcl/EnumContext.hxx>
37 #include <o3tl/string_view.hxx>
39 #include <com/sun/star/frame/ModuleManager.hpp>
40 #include <com/sun/star/ui/XSidebarPanel.hpp>
41 #include <com/sun/star/ui/XUpdateModel.hpp>
43 #include <map>
45 using namespace css;
46 using namespace css::uno;
48 namespace sfx2::sidebar {
50 namespace
53 OUString getString(utl::OConfigurationNode const & aNode, const OUString& rNodeName)
55 return comphelper::getString(aNode.getNodeValue(rNodeName));
57 sal_Int32 getInt32(utl::OConfigurationNode const & aNode, const OUString& rNodeName)
59 return comphelper::getINT32(aNode.getNodeValue(rNodeName));
61 bool getBool(utl::OConfigurationNode const & aNode, const OUString& rNodeName)
63 return comphelper::getBOOL(aNode.getNodeValue(rNodeName));
66 css::uno::Sequence<OUString> BuildContextList (const ContextList& rContextList)
68 const ::std::vector<ContextList::Entry>& entries = rContextList.GetEntries();
70 css::uno::Sequence<OUString> result(entries.size());
71 auto resultRange = asNonConstRange(result);
72 tools::Long i = 0;
74 for (auto const& entry : entries)
76 OUString appName = entry.maContext.msApplication;
77 OUString contextName = entry.maContext.msContext;
78 OUString menuCommand = entry.msMenuCommand;
80 OUString visibility;
81 if (entry.mbIsInitiallyVisible)
82 visibility = "visible";
83 else
84 visibility = "hidden";
86 OUString element = appName + ", " + contextName +", " + visibility;
88 if (!menuCommand.isEmpty())
89 element += ", "+menuCommand;
91 resultRange[i] = element;
93 ++i;
96 return result;
100 } //end anonymous namespace
102 ResourceManager::ResourceManager()
104 ReadDeckList();
105 ReadPanelList();
106 ReadLastActive();
109 ResourceManager::~ResourceManager()
113 void ResourceManager::InitDeckContext(const Context& rContext)
115 for (auto const& deck : maDecks)
117 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
119 bool bIsEnabled;
120 if (pMatchingEntry)
121 bIsEnabled = pMatchingEntry->mbIsInitiallyVisible;
122 else
123 bIsEnabled = false;
125 deck->mbIsEnabled = bIsEnabled;
129 std::shared_ptr<DeckDescriptor> ResourceManager::ImplGetDeckDescriptor(std::u16string_view rsDeckId) const
131 for (auto const& deck : maDecks)
133 if (deck->mbHiddenInViewerMode && officecfg::Office::Common::Misc::ViewerAppMode::get())
134 continue;
135 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
136 continue;
137 if (deck->msId == rsDeckId)
138 return deck;
140 return nullptr;
143 std::shared_ptr<DeckDescriptor> ResourceManager::GetDeckDescriptor(std::u16string_view rsDeckId) const
145 return ImplGetDeckDescriptor( rsDeckId );
148 std::shared_ptr<PanelDescriptor> ResourceManager::ImplGetPanelDescriptor(std::u16string_view rsPanelId) const
150 for (auto const& panel : maPanels)
152 if (panel->msId == rsPanelId)
153 return panel;
155 return nullptr;
158 std::shared_ptr<PanelDescriptor> ResourceManager::GetPanelDescriptor(std::u16string_view rsPanelId) const
160 return ImplGetPanelDescriptor( rsPanelId );
163 const ResourceManager::DeckContextDescriptorContainer& ResourceManager::GetMatchingDecks (
164 DeckContextDescriptorContainer& rDecks,
165 const Context& rContext,
166 const bool bIsDocumentReadOnly,
167 const Reference<frame::XController>& rxController)
169 ReadLegacyAddons(rxController);
171 std::multimap<sal_Int32,DeckContextDescriptor> aOrderedIds;
172 for (auto const& deck : maDecks)
174 if (deck->mbHiddenInViewerMode && officecfg::Office::Common::Misc::ViewerAppMode::get())
175 continue;
176 if (deck->mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
177 continue;
179 const DeckDescriptor& rDeckDescriptor (*deck);
180 if (rDeckDescriptor.maContextList.GetMatch(rContext) == nullptr)
181 continue;
183 DeckContextDescriptor aDeckContextDescriptor;
184 aDeckContextDescriptor.msId = rDeckDescriptor.msId;
186 aDeckContextDescriptor.mbIsEnabled = (! bIsDocumentReadOnly || IsDeckEnabled(rDeckDescriptor.msId, rContext, rxController) )
187 && rDeckDescriptor.mbIsEnabled;
190 aOrderedIds.emplace(rDeckDescriptor.mnOrderIndex, aDeckContextDescriptor);
193 for (auto const& orderId : aOrderedIds)
195 rDecks.push_back(orderId.second);
198 return rDecks;
201 const ResourceManager::PanelContextDescriptorContainer& ResourceManager::GetMatchingPanels (
202 PanelContextDescriptorContainer& rPanelIds,
203 const Context& rContext,
204 std::u16string_view sDeckId,
205 const Reference<frame::XController>& rxController)
207 ReadLegacyAddons(rxController);
209 std::multimap<sal_Int32, PanelContextDescriptor> aOrderedIds;
210 for (auto const& panel : maPanels)
212 const PanelDescriptor& rPanelDescriptor (*panel);
213 if (rPanelDescriptor.mbExperimental && !officecfg::Office::Common::Misc::ExperimentalMode::get())
214 continue;
215 if ( rPanelDescriptor.msDeckId != sDeckId )
216 continue;
218 const ContextList::Entry* pEntry = rPanelDescriptor.maContextList.GetMatch(rContext);
219 if (pEntry == nullptr)
220 continue;
222 PanelContextDescriptor aPanelContextDescriptor;
223 aPanelContextDescriptor.msId = rPanelDescriptor.msId;
224 aPanelContextDescriptor.msMenuCommand = pEntry->msMenuCommand;
225 aPanelContextDescriptor.mbIsInitiallyVisible = pEntry->mbIsInitiallyVisible;
226 aPanelContextDescriptor.mbShowForReadOnlyDocuments = rPanelDescriptor.mbShowForReadOnlyDocuments;
227 aOrderedIds.emplace(rPanelDescriptor.mnOrderIndex, aPanelContextDescriptor);
230 for (auto const& orderId : aOrderedIds)
232 rPanelIds.push_back(orderId.second);
235 return rPanelIds;
238 const OUString& ResourceManager::GetLastActiveDeck( const Context& rContext )
240 if( maLastActiveDecks.find( rContext.msApplication ) == maLastActiveDecks.end())
241 return maLastActiveDecks[u"any"_ustr];
242 else
243 return maLastActiveDecks[rContext.msApplication];
246 void ResourceManager::SetLastActiveDeck( const Context& rContext, const OUString &rsDeckId )
248 maLastActiveDecks[rContext.msApplication] = rsDeckId;
251 void ResourceManager::ReadDeckList()
253 const utl::OConfigurationTreeRoot aDeckRootNode(
254 comphelper::getProcessComponentContext(),
255 u"org.openoffice.Office.UI.Sidebar/Content/DeckList"_ustr,
256 false);
257 if (!aDeckRootNode.isValid())
258 return;
260 const Sequence<OUString> aDeckNodeNames (aDeckRootNode.getNodeNames());
261 maDecks.clear();
262 for (const OUString& aDeckName : aDeckNodeNames)
264 if (comphelper::LibreOfficeKit::isActive())
266 // Hide these decks in LOK as they aren't fully functional.
267 if (aDeckName == "GalleryDeck" || aDeckName == "StyleListDeck")
268 continue;
271 const utl::OConfigurationNode aDeckNode(aDeckRootNode.openNode(aDeckName));
272 if (!aDeckNode.isValid())
273 continue;
275 maDecks.push_back(std::make_shared<DeckDescriptor>());
276 DeckDescriptor& rDeckDescriptor (*maDecks.back());
278 rDeckDescriptor.msTitle = getString(aDeckNode, u"Title"_ustr);
279 rDeckDescriptor.msId = getString(aDeckNode, u"Id"_ustr);
280 rDeckDescriptor.msIconURL = getString(aDeckNode, u"IconURL"_ustr);
281 rDeckDescriptor.msHighContrastIconURL = getString(aDeckNode, u"HighContrastIconURL"_ustr);
282 rDeckDescriptor.msTitleBarIconURL = getString(aDeckNode, u"TitleBarIconURL"_ustr);
283 rDeckDescriptor.msHighContrastTitleBarIconURL = getString(aDeckNode, u"HighContrastTitleBarIconURL"_ustr);
284 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
285 rDeckDescriptor.msHelpId = "SIDEBAR_" + rDeckDescriptor.msId.toAsciiUpperCase();
286 rDeckDescriptor.mnOrderIndex = getInt32(aDeckNode, u"OrderIndex"_ustr);
287 rDeckDescriptor.mbExperimental = getBool(aDeckNode, u"IsExperimental"_ustr);
288 rDeckDescriptor.mbHiddenInViewerMode = getBool(aDeckNode, u"HiddenInViewer"_ustr);
290 rDeckDescriptor.msNodeName = aDeckName;
292 ReadContextList(
293 aDeckNode,
294 rDeckDescriptor.maContextList,
295 OUString());
300 void ResourceManager::SaveDecksSettings(const Context& rContext)
302 for (auto const& deck : maDecks)
304 const ContextList::Entry* pMatchingEntry = deck->maContextList.GetMatch(rContext);
305 if (pMatchingEntry)
307 std::shared_ptr<DeckDescriptor> xDeckDesc = GetDeckDescriptor(deck->msId);
308 if (xDeckDesc)
309 SaveDeckSettings(xDeckDesc.get());
315 void ResourceManager::SaveDeckSettings(const DeckDescriptor* pDeckDesc)
317 const utl::OConfigurationTreeRoot aDeckRootNode(
318 comphelper::getProcessComponentContext(),
319 u"org.openoffice.Office.UI.Sidebar/Content/DeckList"_ustr,
320 true);
321 if (!aDeckRootNode.isValid())
322 return;
324 // save deck settings
326 ::uno::Sequence< OUString > sContextList = BuildContextList(pDeckDesc->maContextList);
328 utl::OConfigurationNode aDeckNode (aDeckRootNode.openNode(pDeckDesc->msNodeName));
330 css::uno::Any aTitle(Any(pDeckDesc->msTitle));
331 css::uno::Any aOrder(Any(pDeckDesc->mnOrderIndex));
332 css::uno::Any aContextList(sContextList);
334 bool bChanged = false;
335 if (aTitle != aDeckNode.getNodeValue(u"Title"_ustr))
337 aDeckNode.setNodeValue(u"Title"_ustr, aTitle);
338 bChanged = true;
340 if (aOrder != aDeckNode.getNodeValue(u"OrderIndex"_ustr))
342 aDeckNode.setNodeValue(u"OrderIndex"_ustr, aOrder);
343 bChanged = true;
345 if (aContextList != aDeckNode.getNodeValue(u"ContextList"_ustr))
347 aDeckNode.setNodeValue(u"ContextList"_ustr, aContextList);
348 bChanged = true;
351 if (bChanged)
352 aDeckRootNode.commit();
354 // save panel settings
356 const utl::OConfigurationTreeRoot aPanelRootNode(
357 comphelper::getProcessComponentContext(),
358 u"org.openoffice.Office.UI.Sidebar/Content/PanelList"_ustr,
359 true);
361 if (!aPanelRootNode.isValid())
362 return;
364 if (!pDeckDesc->mpDeck) // the deck has not been edited
365 return;
367 SharedPanelContainer rPanels = pDeckDesc->mpDeck->GetPanels();
369 bChanged = false;
370 for (auto const& panel : rPanels)
372 OUString panelId = panel->GetId();
373 std::shared_ptr<PanelDescriptor> xPanelDesc = GetPanelDescriptor(panelId);
375 ::uno::Sequence< OUString > sPanelContextList = BuildContextList(xPanelDesc->maContextList);
377 utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(xPanelDesc->msNodeName));
379 aTitle <<= xPanelDesc->msTitle;
380 aOrder <<= xPanelDesc->mnOrderIndex;
381 aContextList <<= sPanelContextList;
383 if (aTitle != aPanelNode.getNodeValue(u"Title"_ustr))
385 aPanelNode.setNodeValue(u"Title"_ustr, aTitle);
386 bChanged = true;
388 if (aOrder != aPanelNode.getNodeValue(u"OrderIndex"_ustr))
390 aPanelNode.setNodeValue(u"OrderIndex"_ustr, aOrder);
391 bChanged = true;
393 if (aContextList != aPanelNode.getNodeValue(u"ContextList"_ustr))
395 aPanelNode.setNodeValue(u"ContextList"_ustr, aContextList);
396 bChanged = true;
400 if (bChanged)
401 aPanelRootNode.commit();
404 void ResourceManager::SaveLastActiveDeck(const Context& rContext, const OUString& rActiveDeck)
406 maLastActiveDecks[rContext.msApplication] = rActiveDeck;
408 std::set<OUString> aLastActiveDecks;
409 for ( auto const & rEntry : maLastActiveDecks )
410 aLastActiveDecks.insert( rEntry.first + "," + rEntry.second);
412 std::shared_ptr<comphelper::ConfigurationChanges> cfgWriter( comphelper::ConfigurationChanges::create() );
414 officecfg::Office::UI::Sidebar::Content::LastActiveDeck::set(comphelper::containerToSequence(aLastActiveDecks), cfgWriter);
415 cfgWriter->commit();
419 void ResourceManager::ReadPanelList()
421 const utl::OConfigurationTreeRoot aPanelRootNode(
422 comphelper::getProcessComponentContext(),
423 u"org.openoffice.Office.UI.Sidebar/Content/PanelList"_ustr,
424 false);
425 if (!aPanelRootNode.isValid())
426 return;
428 const Sequence<OUString> aPanelNodeNames (aPanelRootNode.getNodeNames());
429 maPanels.clear();
430 for (const auto& rPanelNodeName : aPanelNodeNames)
432 const utl::OConfigurationNode aPanelNode (aPanelRootNode.openNode(rPanelNodeName));
433 if (!aPanelNode.isValid())
434 continue;
436 if (comphelper::LibreOfficeKit::isActive())
438 // Hide these panels in LOK as they aren't fully functional.
439 OUString aPanelId = getString(aPanelNode, u"Id"_ustr);
440 if (aPanelId == "PageStylesPanel" || aPanelId == "PageHeaderPanel"
441 || aPanelId == "PageFooterPanel")
442 continue;
445 maPanels.push_back(std::make_shared<PanelDescriptor>());
446 PanelDescriptor& rPanelDescriptor(*maPanels.back());
448 rPanelDescriptor.msTitle = getString(aPanelNode, u"Title"_ustr);
449 rPanelDescriptor.mbIsTitleBarOptional = getBool(aPanelNode, u"TitleBarIsOptional"_ustr);
450 rPanelDescriptor.msId = getString(aPanelNode, u"Id"_ustr);
451 rPanelDescriptor.msDeckId = getString(aPanelNode, u"DeckId"_ustr);
452 rPanelDescriptor.msTitleBarIconURL = getString(aPanelNode, u"TitleBarIconURL"_ustr);
453 rPanelDescriptor.msHighContrastTitleBarIconURL = getString(aPanelNode, u"HighContrastTitleBarIconURL"_ustr);
454 rPanelDescriptor.msImplementationURL = getString(aPanelNode, u"ImplementationURL"_ustr);
455 rPanelDescriptor.mnOrderIndex = getInt32(aPanelNode, u"OrderIndex"_ustr);
456 rPanelDescriptor.mbShowForReadOnlyDocuments = getBool(aPanelNode, u"ShowForReadOnlyDocument"_ustr);
457 rPanelDescriptor.mbWantsCanvas = getBool(aPanelNode, u"WantsCanvas"_ustr);
458 rPanelDescriptor.mbWantsAWT = getBool(aPanelNode, u"WantsAWT"_ustr);
459 rPanelDescriptor.mbExperimental = getBool(aPanelNode, u"IsExperimental"_ustr);
460 const OUString sDefaultMenuCommand(getString(aPanelNode, u"DefaultMenuCommand"_ustr));
462 rPanelDescriptor.msNodeName = rPanelNodeName;
464 ReadContextList(aPanelNode, rPanelDescriptor.maContextList, sDefaultMenuCommand);
468 void ResourceManager::ReadLastActive()
470 const Sequence <OUString> aLastActive (officecfg::Office::UI::Sidebar::Content::LastActiveDeck::get());
472 for (const auto& rDeckInfo : aLastActive)
474 sal_Int32 nCharIdx = rDeckInfo.lastIndexOf(',');
475 if ( nCharIdx <= 0 || (nCharIdx == rDeckInfo.getLength() - 1) )
477 SAL_WARN("sfx.sidebar", "Expecting 2 values separated by comma");
478 continue;
481 const OUString sApplicationName = rDeckInfo.copy( 0, nCharIdx );
482 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
483 const OUString sLastUsed = rDeckInfo.copy( nCharIdx + 1 );
485 // guard against garbage in place of application
486 if (eApplication != vcl::EnumContext::Application::NONE)
487 maLastActiveDecks.insert( std::make_pair(sApplicationName, sLastUsed ) );
490 // Set up a default for Math - will do nothing if already set
491 maLastActiveDecks.emplace(
492 vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::Formula),
493 "ElementsDeck");
496 void ResourceManager::ReadContextList (
497 const utl::OConfigurationNode& rParentNode,
498 ContextList& rContextList,
499 const OUString& rsDefaultMenuCommand)
501 const Any aValue = rParentNode.getNodeValue(u"ContextList"_ustr);
502 Sequence<OUString> aValues;
503 if (!(aValue >>= aValues))
504 return;
506 for (const OUString& sValue : aValues)
508 sal_Int32 nCharacterIndex (0);
509 const OUString sApplicationName (o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
510 if (nCharacterIndex < 0)
512 if (sApplicationName.getLength() == 0)
514 // This is a valid case: in the XML file the separator
515 // was used as terminator. Using it in the last line
516 // creates an additional but empty entry.
517 break;
519 else
521 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
522 continue;
526 const OUString sContextName(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
527 if (nCharacterIndex < 0)
529 OSL_FAIL("expecting three or four values per ContextList entry, separated by comma");
530 continue;
533 const std::u16string_view sInitialState(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex)));
535 // The fourth argument is optional.
536 const OUString sMenuCommandOverride(
537 nCharacterIndex < 0
538 ? OUString()
539 : OUString(o3tl::trim(o3tl::getToken(sValue, 0, ',', nCharacterIndex))));
541 const OUString sMenuCommand(
542 sMenuCommandOverride.getLength() > 0
543 ? (sMenuCommandOverride == "none"
544 ? OUString()
545 : sMenuCommandOverride)
546 : rsDefaultMenuCommand);
548 // Setup a list of application enums. Note that the
549 // application name may result in more than one value (eg
550 // DrawImpress will result in two enums, one for Draw and one
551 // for Impress).
552 std::vector<vcl::EnumContext::Application> aApplications;
553 vcl::EnumContext::Application eApplication (vcl::EnumContext::GetApplicationEnum(sApplicationName));
555 if (eApplication == vcl::EnumContext::Application::NONE
556 && sApplicationName != vcl::EnumContext::GetApplicationName(vcl::EnumContext::Application::NONE))
558 // Handle some special names: abbreviations that make
559 // context descriptions more readable.
560 if (sApplicationName == "Writer")
561 aApplications.push_back(vcl::EnumContext::Application::Writer);
562 else if (sApplicationName == "Calc")
563 aApplications.push_back(vcl::EnumContext::Application::Calc);
564 else if (sApplicationName == "Draw")
565 aApplications.push_back(vcl::EnumContext::Application::Draw);
566 else if (sApplicationName == "Impress")
567 aApplications.push_back(vcl::EnumContext::Application::Impress);
568 else if (sApplicationName == "Chart")
569 aApplications.push_back(vcl::EnumContext::Application::Chart);
570 else if (sApplicationName == "Math")
571 aApplications.push_back(vcl::EnumContext::Application::Formula);
572 else if (sApplicationName == "DrawImpress")
574 // A special case among the special names: it is
575 // common to use the same context descriptions for
576 // both Draw and Impress. This special case helps to
577 // avoid duplication in the .xcu file.
578 aApplications.push_back(vcl::EnumContext::Application::Draw);
579 aApplications.push_back(vcl::EnumContext::Application::Impress);
581 else if (sApplicationName == "WriterVariants")
583 // Another special case for all Writer variants.
584 aApplications.push_back(vcl::EnumContext::Application::Writer);
585 aApplications.push_back(vcl::EnumContext::Application::WriterGlobal);
586 aApplications.push_back(vcl::EnumContext::Application::WriterWeb);
587 aApplications.push_back(vcl::EnumContext::Application::WriterXML);
588 aApplications.push_back(vcl::EnumContext::Application::WriterForm);
589 aApplications.push_back(vcl::EnumContext::Application::WriterReport);
591 else
593 SAL_WARN("sfx.sidebar", "application name " << sApplicationName << " not recognized");
594 continue;
597 else
599 // No conversion of the application name necessary.
600 aApplications.push_back(eApplication);
603 // Setup the actual context enum.
604 const vcl::EnumContext::Context eContext (vcl::EnumContext::GetContextEnum(sContextName));
605 if (eContext == vcl::EnumContext::Context::Unknown)
607 SAL_WARN("sfx.sidebar", "context name " << sContextName << " not recognized");
608 continue;
611 // Setup the flag that controls whether a deck/pane is
612 // initially visible/expanded.
613 bool bIsInitiallyVisible;
614 if (sInitialState == u"visible")
615 bIsInitiallyVisible = true;
616 else if (sInitialState == u"hidden")
617 bIsInitiallyVisible = false;
618 else
620 OSL_FAIL("unrecognized state");
621 continue;
625 // Add context descriptors.
626 for (auto const& application : aApplications)
628 if (application != vcl::EnumContext::Application::NONE)
630 rContextList.AddContextDescription(
631 Context(
632 vcl::EnumContext::GetApplicationName(application),
633 vcl::EnumContext::GetContextName(eContext)),
634 bIsInitiallyVisible,
635 sMenuCommand);
641 void ResourceManager::ReadLegacyAddons (const Reference<frame::XController>& rxController)
643 // Get module name for given frame.
644 OUString sModuleName (Tools::GetModuleName(rxController));
645 if (sModuleName.getLength() == 0)
646 return;
647 if (maProcessedApplications.find(sModuleName) != maProcessedApplications.end())
649 // Addons for this application have already been read.
650 // There is nothing more to do.
651 return;
654 // Mark module as processed. Even when there is an error that
655 // prevents the configuration data from being read, this error
656 // will not be triggered a second time.
657 maProcessedApplications.insert(sModuleName);
659 // Get access to the configuration root node for the application.
660 utl::OConfigurationTreeRoot aLegacyRootNode (GetLegacyAddonRootNode(sModuleName));
661 if (!aLegacyRootNode.isValid())
662 return;
664 // Process child nodes.
665 std::vector<OUString> aMatchingNodeNames;
666 GetToolPanelNodeNames(aMatchingNodeNames, aLegacyRootNode);
667 const sal_Int32 nCount (aMatchingNodeNames.size());
668 for (sal_Int32 nReadIndex(0); nReadIndex<nCount; ++nReadIndex)
670 const OUString& rsNodeName (aMatchingNodeNames[nReadIndex]);
671 const utl::OConfigurationNode aChildNode (aLegacyRootNode.openNode(rsNodeName));
672 if (!aChildNode.isValid())
673 continue;
675 if ( rsNodeName == "private:resource/toolpanel/DrawingFramework/CustomAnimations" ||
676 rsNodeName == "private:resource/toolpanel/DrawingFramework/Layouts" ||
677 rsNodeName == "private:resource/toolpanel/DrawingFramework/MasterPages" ||
678 rsNodeName == "private:resource/toolpanel/DrawingFramework/SlideTransitions" ||
679 rsNodeName == "private:resource/toolpanel/DrawingFramework/TableDesign" )
680 continue;
682 maDecks.push_back(std::make_shared<DeckDescriptor>());
683 DeckDescriptor& rDeckDescriptor(*maDecks.back());
684 rDeckDescriptor.msTitle = getString(aChildNode, u"UIName"_ustr);
685 rDeckDescriptor.msId = rsNodeName;
686 rDeckDescriptor.msIconURL = getString(aChildNode, u"ImageURL"_ustr);
687 rDeckDescriptor.msHighContrastIconURL = rDeckDescriptor.msIconURL;
688 rDeckDescriptor.msTitleBarIconURL.clear();
689 rDeckDescriptor.msHighContrastTitleBarIconURL.clear();
690 rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
691 rDeckDescriptor.mbIsEnabled = true;
692 rDeckDescriptor.mnOrderIndex = 100000 + nReadIndex;
693 rDeckDescriptor.maContextList.AddContextDescription(Context(sModuleName, u"any"_ustr), true, OUString());
695 maPanels.push_back(std::make_shared<PanelDescriptor>());
696 PanelDescriptor& rPanelDescriptor(*maPanels.back());
697 rPanelDescriptor.msTitle = getString(aChildNode, u"UIName"_ustr);
698 rPanelDescriptor.mbIsTitleBarOptional = true;
699 rPanelDescriptor.msId = rsNodeName;
700 rPanelDescriptor.msDeckId = rsNodeName;
701 rPanelDescriptor.msTitleBarIconURL.clear();
702 rPanelDescriptor.msHighContrastTitleBarIconURL.clear();
703 rPanelDescriptor.msImplementationURL = rsNodeName;
704 rPanelDescriptor.mnOrderIndex = 100000 + nReadIndex;
705 rPanelDescriptor.mbShowForReadOnlyDocuments = false;
706 rPanelDescriptor.mbWantsCanvas = false;
707 rPanelDescriptor.mbWantsAWT = true;
708 rPanelDescriptor.maContextList.AddContextDescription(Context(sModuleName, u"any"_ustr), true, OUString());
712 void ResourceManager::StorePanelExpansionState (
713 std::u16string_view rsPanelId,
714 const bool bExpansionState,
715 const Context& rContext)
717 for (auto const& panel : maPanels)
719 if (panel->msId == rsPanelId)
721 ContextList::Entry* pEntry(panel->maContextList.GetMatch(rContext));
722 if (pEntry != nullptr)
723 pEntry->mbIsInitiallyVisible = bExpansionState;
728 utl::OConfigurationTreeRoot ResourceManager::GetLegacyAddonRootNode (const OUString& rsModuleName)
732 const Reference<XComponentContext>& xContext(comphelper::getProcessComponentContext());
733 const Reference<frame::XModuleManager2> xModuleAccess = frame::ModuleManager::create(xContext);
734 const comphelper::NamedValueCollection aModuleProperties(xModuleAccess->getByName(rsModuleName));
735 const OUString sWindowStateRef(aModuleProperties.getOrDefault(
736 u"ooSetupFactoryWindowStateConfigRef"_ustr,
737 OUString()));
739 OUString aPathComposer = "org.openoffice.Office.UI." + sWindowStateRef +
740 "/UIElements/States";
742 return utl::OConfigurationTreeRoot(xContext, aPathComposer, false);
744 catch (const Exception&)
746 DBG_UNHANDLED_EXCEPTION("sfx.sidebar");
749 return utl::OConfigurationTreeRoot();
752 void ResourceManager::GetToolPanelNodeNames (
753 std::vector<OUString>& rMatchingNames,
754 const utl::OConfigurationTreeRoot& aRoot)
756 const Sequence<OUString> aChildNodeNames (aRoot.getNodeNames());
757 std::copy_if(aChildNodeNames.begin(), aChildNodeNames.end(), std::back_inserter(rMatchingNames),
758 [](const OUString& rChildNodeName) { return rChildNodeName.startsWith( "private:resource/toolpanel/" ); });
761 bool ResourceManager::IsDeckEnabled (
762 std::u16string_view rsDeckId,
763 const Context& rContext,
764 const Reference<frame::XController>& rxController)
767 // Check if any panel that matches the current context can be
768 // displayed.
769 PanelContextDescriptorContainer aPanelContextDescriptors;
771 GetMatchingPanels(aPanelContextDescriptors, rContext, rsDeckId, rxController);
773 for (auto const& panelContextDescriptor : aPanelContextDescriptors)
775 if (panelContextDescriptor.mbShowForReadOnlyDocuments)
776 return true;
778 return false;
781 void ResourceManager::UpdateModel(const css::uno::Reference<css::frame::XModel>& xModel)
783 for (auto const& deck : maDecks)
785 if (!deck->mpDeck)
786 continue;
788 const SharedPanelContainer& rContainer = deck->mpDeck->GetPanels();
790 for (auto const& elem : rContainer)
792 css::uno::Reference<css::ui::XUpdateModel> xPanel(elem->GetPanelComponent(), css::uno::UNO_QUERY);
793 if (xPanel.is()) // tdf#108814 interface is optional
795 xPanel->updateModel(xModel);
801 void ResourceManager::disposeDecks()
803 for (auto const& deck : maDecks)
805 deck->mpDeck.disposeAndClear();
809 } // end of namespace sfx2::sidebar
811 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */