bump product version to 7.2.5.1
[LibreOffice.git] / sfx2 / source / notebookbar / SfxNotebookBar.cxx
blobfb90113f9f0515a3662b8fd425b4346107cf75ca
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/.
8 */
10 #include <sfx2/bindings.hxx>
11 #include <sfx2/viewsh.hxx>
12 #include <sfx2/dispatch.hxx>
13 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
14 #include <vcl/notebookbar/notebookbar.hxx>
15 #include <vcl/syswin.hxx>
16 #include <sfx2/viewfrm.hxx>
17 #include <sfx2/sfxsids.hrc>
18 #include <comphelper/processfactory.hxx>
19 #include <comphelper/lok.hxx>
20 #include <com/sun/star/frame/UnknownModuleException.hpp>
21 #include <com/sun/star/frame/XLayoutManager.hpp>
22 #include <officecfg/Office/UI/ToolbarMode.hxx>
23 #include <com/sun/star/frame/XModuleManager.hpp>
24 #include <com/sun/star/frame/ModuleManager.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <unotools/confignode.hxx>
27 #include <comphelper/types.hxx>
28 #include <framework/addonsoptions.hxx>
29 #include <vcl/notebookbar/NotebookBarAddonsMerger.hxx>
30 #include <vector>
31 #include <map>
32 #include <vcl/WeldedTabbedNotebookbar.hxx>
34 using namespace sfx2;
35 using namespace css::uno;
36 using namespace css::ui;
37 using namespace css;
39 #define MENUBAR_STR "private:resource/menubar/menubar"
41 const char MERGE_NOTEBOOKBAR_URL[] = "URL";
43 bool SfxNotebookBar::m_bLock = false;
44 bool SfxNotebookBar::m_bHide = false;
45 std::map<const SfxViewShell*, std::shared_ptr<WeldedTabbedNotebookbar>> SfxNotebookBar::m_pNotebookBarWeldedWrapper;
47 static void NotebookbarAddonValues(
48 std::vector<Image>& aImageValues,
49 std::vector<css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>>>&
50 aExtensionValues)
52 framework::AddonsOptions aAddonsItems;
54 for (int nIdx = 0; nIdx < aAddonsItems.GetAddonsNotebookBarCount(); nIdx++)
56 const css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> aExtension
57 = aAddonsItems.GetAddonsNotebookBarPart(nIdx);
58 for (const css::uno::Sequence<css::beans::PropertyValue>& rExtensionVal : aExtension)
60 Image aImage;
61 bool isBigImage = true;
62 for (const auto& rProp : rExtensionVal)
64 if (rProp.Name == MERGE_NOTEBOOKBAR_URL)
66 OUString sImage;
67 rProp.Value >>= sImage;
68 aImage = Image(framework::AddonsOptions().GetImageFromURL(sImage, isBigImage));
71 aImageValues.push_back(aImage);
73 aExtensionValues.push_back(aExtension);
77 static Reference<frame::XLayoutManager> lcl_getLayoutManager( const Reference<frame::XFrame>& xFrame )
79 css::uno::Reference<css::frame::XLayoutManager> xLayoutManager;
81 if (xFrame.is())
83 Reference<css::beans::XPropertySet> xPropSet(xFrame, UNO_QUERY);
85 if (xPropSet.is())
87 Any aValue = xPropSet->getPropertyValue("LayoutManager");
88 aValue >>= xLayoutManager;
92 return xLayoutManager;
95 static OUString lcl_getAppName( vcl::EnumContext::Application eApp )
97 switch ( eApp )
99 case vcl::EnumContext::Application::Writer:
100 return "Writer";
101 case vcl::EnumContext::Application::Calc:
102 return "Calc";
103 case vcl::EnumContext::Application::Impress:
104 return "Impress";
105 case vcl::EnumContext::Application::Draw:
106 return "Draw";
107 case vcl::EnumContext::Application::Formula:
108 return "Formula";
109 default:
110 return OUString();
114 static void lcl_setNotebookbarFileName( vcl::EnumContext::Application eApp, const OUString& sFileName )
116 std::shared_ptr<comphelper::ConfigurationChanges> aBatch(
117 comphelper::ConfigurationChanges::create( ::comphelper::getProcessComponentContext() ) );
118 switch ( eApp )
120 case vcl::EnumContext::Application::Writer:
121 officecfg::Office::UI::ToolbarMode::ActiveWriter::set( sFileName, aBatch );
122 break;
123 case vcl::EnumContext::Application::Calc:
124 officecfg::Office::UI::ToolbarMode::ActiveCalc::set( sFileName, aBatch );
125 break;
126 case vcl::EnumContext::Application::Impress:
127 officecfg::Office::UI::ToolbarMode::ActiveImpress::set( sFileName, aBatch );
128 break;
129 case vcl::EnumContext::Application::Draw:
130 officecfg::Office::UI::ToolbarMode::ActiveDraw::set( sFileName, aBatch );
131 break;
132 default:
133 break;
135 aBatch->commit();
138 static OUString lcl_getNotebookbarFileName( vcl::EnumContext::Application eApp )
140 switch ( eApp )
142 case vcl::EnumContext::Application::Writer:
143 return officecfg::Office::UI::ToolbarMode::ActiveWriter::get();
144 case vcl::EnumContext::Application::Calc:
145 return officecfg::Office::UI::ToolbarMode::ActiveCalc::get();
146 case vcl::EnumContext::Application::Impress:
147 return officecfg::Office::UI::ToolbarMode::ActiveImpress::get();
148 case vcl::EnumContext::Application::Draw:
149 return officecfg::Office::UI::ToolbarMode::ActiveDraw::get();
151 default:
152 break;
154 return OUString();
157 static utl::OConfigurationTreeRoot lcl_getCurrentImplConfigRoot()
159 return utl::OConfigurationTreeRoot(::comphelper::getProcessComponentContext(),
160 "org.openoffice.Office.UI.ToolbarMode/",
161 true);
164 static utl::OConfigurationNode lcl_getCurrentImplConfigNode(const Reference<css::frame::XFrame>& xFrame,
165 utl::OConfigurationTreeRoot const & rNotebookbarNode )
167 if (!rNotebookbarNode.isValid())
168 return utl::OConfigurationNode();
170 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
172 vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
173 OUString aActive = lcl_getNotebookbarFileName( eApp );
175 const utl::OConfigurationNode aImplsNode = rNotebookbarNode.openNode("Applications/" + lcl_getAppName( eApp) + "/Modes");
176 const Sequence<OUString> aModeNodeNames( aImplsNode.getNodeNames() );
178 for ( const auto& rModeNodeName : aModeNodeNames )
180 const utl::OConfigurationNode aImplNode( aImplsNode.openNode( rModeNodeName ) );
181 if ( !aImplNode.isValid() )
182 continue;
184 OUString aCommandArg = comphelper::getString( aImplNode.getNodeValue( "CommandArg" ) );
186 if ( aCommandArg == aActive )
188 return aImplNode;
192 return utl::OConfigurationNode();
195 void SfxNotebookBar::CloseMethod(SfxBindings& rBindings)
197 SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame();
198 CloseMethod(rFrame.GetSystemWindow());
201 void SfxNotebookBar::CloseMethod(SystemWindow* pSysWindow)
203 if (pSysWindow)
205 RemoveListeners(pSysWindow);
206 if(pSysWindow->GetNotebookBar())
207 pSysWindow->CloseNotebookBar();
208 if (SfxViewFrame::Current())
209 SfxNotebookBar::ShowMenubar(SfxViewFrame::Current(), true);
213 void SfxNotebookBar::LockNotebookBar()
215 m_bHide = true;
216 m_bLock = true;
219 void SfxNotebookBar::UnlockNotebookBar()
221 m_bHide = false;
222 m_bLock = false;
225 bool SfxNotebookBar::IsActive()
227 if (m_bHide)
228 return false;
230 vcl::EnumContext::Application eApp = vcl::EnumContext::Application::Any;
232 if (SfxViewFrame::Current())
234 const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
235 if (!xFrame.is())
236 return false;
238 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
241 eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
243 catch (css::frame::UnknownModuleException& e)
245 SAL_WARN("sfx.appl", "SfxNotebookBar::IsActive(): " + e.Message);
246 return false;
249 else
250 return false;
252 OUString appName(lcl_getAppName( eApp ));
254 if (appName.isEmpty())
255 return false;
258 OUString aPath = "org.openoffice.Office.UI.ToolbarMode/Applications/" + appName;
260 const utl::OConfigurationTreeRoot aAppNode(
261 ::comphelper::getProcessComponentContext(),
262 aPath,
263 false);
264 if ( !aAppNode.isValid() )
265 return false;
267 OUString aActive = comphelper::getString( aAppNode.getNodeValue( "Active" ) );
269 if (comphelper::LibreOfficeKit::isActive() && aActive == "notebookbar_online.ui")
270 return true;
272 const utl::OConfigurationNode aModesNode = aAppNode.openNode("Modes");
273 const Sequence<OUString> aModeNodeNames( aModesNode.getNodeNames() );
275 for ( const auto& rModeNodeName : aModeNodeNames )
277 const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
278 if ( !aModeNode.isValid() )
279 continue;
281 OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
283 if ( aCommandArg == aActive )
285 return comphelper::getBOOL( aModeNode.getNodeValue( "HasNotebookbar" ) );
288 return false;
291 void SfxNotebookBar::ExecMethod(SfxBindings& rBindings, const OUString& rUIName)
293 // Save active UI file name
294 if ( !rUIName.isEmpty() && SfxViewFrame::Current() )
296 const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
297 if (xFrame.is())
299 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( ::comphelper::getProcessComponentContext() );
300 vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum(xModuleManager->identify(xFrame));
301 lcl_setNotebookbarFileName( eApp, rUIName );
305 // trigger the StateMethod
306 rBindings.Invalidate(SID_NOTEBOOKBAR);
307 rBindings.Update();
310 bool SfxNotebookBar::StateMethod(SfxBindings& rBindings, std::u16string_view rUIFile,
311 bool bReloadNotebookbar)
313 SfxFrame& rFrame = rBindings.GetDispatcher_Impl()->GetFrame()->GetFrame();
314 return StateMethod(rFrame.GetSystemWindow(), rFrame.GetFrameInterface(), rUIFile,
315 bReloadNotebookbar);
318 bool SfxNotebookBar::StateMethod(SystemWindow* pSysWindow,
319 const Reference<css::frame::XFrame>& xFrame,
320 std::u16string_view rUIFile, bool bReloadNotebookbar)
322 if (!pSysWindow)
324 if (SfxViewFrame::Current() && SfxViewFrame::Current()->GetWindow().GetSystemWindow())
325 pSysWindow = SfxViewFrame::Current()->GetWindow().GetSystemWindow();
326 else
327 return false;
330 if (IsActive())
332 css::uno::Reference<css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
333 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext );
334 OUString aModuleName = xModuleManager->identify( xFrame );
335 vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( aModuleName );
336 OUString sFile = lcl_getNotebookbarFileName( eApp );
337 if (comphelper::LibreOfficeKit::isActive())
338 sFile = "notebookbar_online.ui";
339 OUString sNewFile = rUIFile + sFile;
340 OUString sCurrentFile;
341 VclPtr<NotebookBar> pNotebookBar = pSysWindow->GetNotebookBar();
342 if ( pNotebookBar )
343 sCurrentFile = pNotebookBar->GetUIFilePath();
345 bool bChangedFile = sNewFile != sCurrentFile;
347 if ((!sFile.isEmpty() && bChangedFile) || !pNotebookBar || !pNotebookBar->IsVisible()
348 || bReloadNotebookbar || comphelper::LibreOfficeKit::isActive())
350 const SfxViewShell* pViewShell = SfxViewShell::Current();
352 // Notebookbar was loaded too early what caused:
353 // * in LOK: Paste Special feature was incorrectly initialized
354 // Skip first request so Notebookbar will be initialized after document was loaded
355 static std::map<const void*, bool> bSkippedFirstInit;
356 if (comphelper::LibreOfficeKit::isActive() && bSkippedFirstInit.find(pViewShell) == bSkippedFirstInit.end())
358 bSkippedFirstInit[pViewShell] = true;
359 return false;
362 RemoveListeners(pSysWindow);
364 OUString aBuf = rUIFile + sFile;
366 //Addons For Notebookbar
367 std::vector<Image> aImageValues;
368 std::vector<css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > > aExtensionValues;
369 NotebookBarAddonsItem aNotebookBarAddonsItem;
370 NotebookbarAddonValues(aImageValues , aExtensionValues);
371 aNotebookBarAddonsItem.aAddonValues = aExtensionValues;
372 aNotebookBarAddonsItem.aImageValues = aImageValues;
374 // setup if necessary
375 if (comphelper::LibreOfficeKit::isActive())
377 // update the current LOK language and locale for the dialog tunneling
378 comphelper::LibreOfficeKit::setLanguageTag(pViewShell->GetLOKLanguageTag());
379 comphelper::LibreOfficeKit::setLocale(pViewShell->GetLOKLocale());
382 pSysWindow->SetNotebookBar(aBuf, xFrame, aNotebookBarAddonsItem , bReloadNotebookbar);
383 pNotebookBar = pSysWindow->GetNotebookBar();
384 pNotebookBar->Show();
387 bool hasWeldedWrapper = m_pNotebookBarWeldedWrapper.find(pViewShell) != m_pNotebookBarWeldedWrapper.end();
388 if ((!hasWeldedWrapper || bReloadNotebookbar) && pNotebookBar->IsWelded())
390 sal_uInt64 nWindowId = reinterpret_cast<sal_uInt64>(pViewShell);
391 m_pNotebookBarWeldedWrapper.emplace(std::make_pair(pViewShell,
392 new WeldedTabbedNotebookbar(pNotebookBar->GetMainContainer(),
393 pNotebookBar->GetUIFilePath(),
394 xFrame,
395 nWindowId)));
396 pNotebookBar->SetDisposeCallback(LINK(nullptr, SfxNotebookBar, VclDisposeHdl), pViewShell);
399 pNotebookBar->GetParent()->Resize();
401 utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot());
402 const utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot));
403 SfxNotebookBar::ShowMenubar( comphelper::getBOOL( aModeNode.getNodeValue( "HasMenubar" ) ) );
405 SfxViewFrame* pView = SfxViewFrame::Current();
407 if(pView)
409 pNotebookBar->ControlListenerForCurrentController(true);
413 return true;
415 else if (auto pNotebookBar = pSysWindow->GetNotebookBar())
417 vcl::Window* pParent = pNotebookBar->GetParent();
418 RemoveListeners(pSysWindow);
419 pSysWindow->CloseNotebookBar();
420 pParent->Resize();
421 SfxNotebookBar::ShowMenubar(true);
424 return false;
427 void SfxNotebookBar::RemoveListeners(SystemWindow const * pSysWindow)
429 if (auto pNotebookBar = pSysWindow->GetNotebookBar())
431 pNotebookBar->StopListeningAllControllers();
435 void SfxNotebookBar::ShowMenubar(bool bShow)
437 if (m_bLock)
438 return;
440 m_bLock = true;
442 Reference<frame::XFrame> xFrame;
443 vcl::EnumContext::Application eCurrentApp = vcl::EnumContext::Application::NONE;
444 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
445 const Reference<frame::XModuleManager> xModuleManager = frame::ModuleManager::create( xContext );
447 if ( SfxViewFrame::Current() )
449 xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
450 eCurrentApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
453 SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
454 while( pViewFrame )
456 xFrame = pViewFrame->GetFrame().GetFrameInterface();
457 if ( xFrame.is() )
459 vcl::EnumContext::Application eApp =
460 vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
462 if ( eApp == eCurrentApp )
464 const Reference<frame::XLayoutManager>& xLayoutManager =
465 lcl_getLayoutManager( xFrame );
467 if (xLayoutManager.is())
469 xLayoutManager->lock();
471 if (xLayoutManager->getElement(MENUBAR_STR).is())
473 if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow)
474 xLayoutManager->hideElement(MENUBAR_STR);
475 else if(!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow)
476 xLayoutManager->showElement(MENUBAR_STR);
479 xLayoutManager->unlock();
484 pViewFrame = SfxViewFrame::GetNext( *pViewFrame );
486 m_bLock = false;
489 void SfxNotebookBar::ShowMenubar(SfxViewFrame const * pViewFrame, bool bShow)
491 if (m_bLock)
492 return;
494 m_bLock = true;
496 Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
497 if (xFrame.is())
499 const Reference<frame::XLayoutManager>& xLayoutManager = lcl_getLayoutManager(xFrame);
500 if (xLayoutManager.is())
502 xLayoutManager->lock();
504 if (xLayoutManager->getElement(MENUBAR_STR).is())
506 if (xLayoutManager->isElementVisible(MENUBAR_STR) && !bShow)
507 xLayoutManager->hideElement(MENUBAR_STR);
508 else if (!xLayoutManager->isElementVisible(MENUBAR_STR) && bShow)
509 xLayoutManager->showElement(MENUBAR_STR);
512 xLayoutManager->unlock();
515 m_bLock = false;
518 void SfxNotebookBar::ToggleMenubar()
520 if (!SfxViewFrame::Current())
521 return;
523 const Reference<frame::XFrame>& xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface();
524 if (!xFrame.is())
525 return;
527 const Reference<frame::XLayoutManager>& xLayoutManager =
528 lcl_getLayoutManager(xFrame);
530 bool bShow = true;
531 if (xLayoutManager.is() && xLayoutManager->getElement(MENUBAR_STR).is())
533 if (xLayoutManager->isElementVisible(MENUBAR_STR))
535 SfxNotebookBar::ShowMenubar(false);
536 bShow = false;
538 else
539 SfxNotebookBar::ShowMenubar(true);
542 // Save menubar settings
543 if (IsActive())
545 utl::OConfigurationTreeRoot aRoot(lcl_getCurrentImplConfigRoot());
546 utl::OConfigurationNode aModeNode(lcl_getCurrentImplConfigNode(xFrame, aRoot));
547 aModeNode.setNodeValue( "HasMenubar", toAny<bool>( bShow ) );
548 aRoot.commit();
552 void SfxNotebookBar::ReloadNotebookBar(std::u16string_view sUIPath)
554 if (SfxNotebookBar::IsActive())
556 SfxViewShell* pViewShell = SfxViewShell::Current();
557 sfx2::SfxNotebookBar::StateMethod(pViewShell->GetViewFrame()->GetBindings(), sUIPath, true);
561 IMPL_STATIC_LINK(SfxNotebookBar, VclDisposeHdl, const SfxViewShell*, pViewShell, void)
563 m_pNotebookBarWeldedWrapper.erase(pViewShell);
566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */