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 <config_features.h>
21 #include <com/sun/star/drawing/ModuleDispatcher.hpp>
22 #include <com/sun/star/frame/Desktop.hpp>
23 #include <com/sun/star/frame/DispatchResultEvent.hpp>
24 #include <com/sun/star/frame/DispatchResultState.hpp>
25 #include <com/sun/star/frame/DispatchHelper.hpp>
26 #include <com/sun/star/frame/UnknownModuleException.hpp>
27 #include <com/sun/star/frame/XLayoutManager.hpp>
28 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
29 #include <com/sun/star/sdbc/DriverManager.hpp>
30 #include <com/sun/star/text/ModuleDispatcher.hpp>
31 #include <com/sun/star/task/OfficeRestartManager.hpp>
32 #include <com/sun/star/task/XInteractionHandler.hpp>
33 #include <com/sun/star/ui/dialogs/AddressBookSourcePilot.hpp>
34 #include <com/sun/star/ui/UIElementType.hpp>
35 #include <com/sun/star/ui/XUIElement.hpp>
36 #include <com/sun/star/uno/Reference.hxx>
37 #include <com/sun/star/util/XCloseable.hpp>
38 #include <com/sun/star/util/CloseVetoException.hpp>
39 #include <org/freedesktop/PackageKit/SyncDbusSessionHelper.hpp>
40 
41 #include <comphelper/dispatchcommand.hxx>
42 #include <comphelper/lok.hxx>
43 #include <comphelper/namedvaluecollection.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <comphelper/propertysequence.hxx>
46 #include <comphelper/sequence.hxx>
47 
48 #include <svtools/addresstemplate.hxx>
49 #include <svtools/miscopt.hxx>
50 #include <svtools/restartdialog.hxx>
51 #include <svl/visitem.hxx>
52 
53 #include <unotools/configmgr.hxx>
54 #include <tools/diagnose_ex.h>
55 #include <vcl/weld.hxx>
56 #include <svl/intitem.hxx>
57 #include <svl/eitem.hxx>
58 #include <svl/stritem.hxx>
59 #include <basic/sbstar.hxx>
60 #include <basic/basrdll.hxx>
61 #include <basic/sberrors.hxx>
62 #include <vcl/help.hxx>
63 #include <rtl/ustrbuf.hxx>
64 #include <sal/log.hxx>
65 #include <osl/file.hxx>
66 #include <vcl/EnumContext.hxx>
67 #include <vcl/toolbox.hxx>
68 
69 #include <unotools/moduleoptions.hxx>
70 #include <svtools/helpopt.hxx>
71 #include <rtl/bootstrap.hxx>
72 
73 #include <com/sun/star/frame/ModuleManager.hpp>
74 #include <com/sun/star/beans/XPropertySet.hpp>
75 
76 #include <sfx2/app.hxx>
77 #include <sfx2/request.hxx>
78 #include <sfx2/dispatch.hxx>
79 #include <sfx2/bindings.hxx>
80 #include <sfx2/msg.hxx>
81 #include <sfx2/objface.hxx>
82 #include <sfx2/objsh.hxx>
83 #include <sfx2/viewsh.hxx>
84 #include <sfx2/docfac.hxx>
85 #include <sfx2/strings.hrc>
86 #include <sfx2/sfxresid.hxx>
87 #include <appdata.hxx>
88 #include <sfx2/viewfrm.hxx>
89 #include <sfx2/sfxdlg.hxx>
90 #include <sfx2/sfxsids.hrc>
91 #include <sorgitm.hxx>
92 #include <sfx2/sfxhelp.hxx>
93 #include <sfx2/zoomitem.hxx>
94 #include <sfx2/templatedlg.hxx>
95 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
96 #include <sfx2/sidebar/SidebarController.hxx>
97 #include <sfx2/safemode.hxx>
98 #include <sfx2/sfxuno.hxx>
99 #include <sfx2/devtools/DevelopmentToolDockingWindow.hxx>
100 
101 #include <comphelper/types.hxx>
102 #include <officecfg/Office/Common.hxx>
103 #include <unotools/confignode.hxx>
104 #include <memory>
105 
106 #include <openuriexternally.hxx>
107 
108 #include "getbasctlfunction.hxx"
109 
110 using namespace ::com::sun::star;
111 using namespace ::com::sun::star::beans;
112 using namespace ::com::sun::star::uno;
113 using namespace ::com::sun::star::frame;
114 using namespace ::com::sun::star::container;
115 using namespace ::com::sun::star::util;
116 using namespace ::com::sun::star::lang;
117 using namespace ::com::sun::star::ui;
118 
119 namespace
120 {
lcl_getAppName(vcl::EnumContext::Application eApp)121     OUString lcl_getAppName( vcl::EnumContext::Application eApp )
122     {
123         switch ( eApp )
124         {
125             case vcl::EnumContext::Application::Writer:
126                 return "Writer";
127             case vcl::EnumContext::Application::Calc:
128                 return "Calc";
129             case vcl::EnumContext::Application::Impress:
130                 return "Impress";
131             case vcl::EnumContext::Application::Draw:
132                 return "Draw";
133             case vcl::EnumContext::Application::Formula:
134                 return "Formula";
135             case vcl::EnumContext::Application::Base:
136                 return "Base";
137             default:
138                 return OUString();
139         }
140     }
141 
142     // lp#527938, debian#602953, fdo#33266, i#105408
lcl_isBaseAvailable()143     bool lcl_isBaseAvailable()
144     {
145         try
146         {
147             // if we get css::sdbc::DriverManager, libsdbc2 is there
148             // and the bibliography is assumed to work
149             return css::sdbc::DriverManager::create(comphelper::getProcessComponentContext()).is();
150         }
151         catch (const Exception &)
152         {
153             TOOLS_INFO_EXCEPTION("sfx.appl", "assuming Base to be missing");
154             return false;
155         }
156     }
lcl_tryLoadBibliography()157     void lcl_tryLoadBibliography()
158     {
159         // lp#527938, debian#602953, fdo#33266, i#105408
160         // make sure we actually can instantiate services from base first
161         if(!lcl_isBaseAvailable())
162         {
163             if (officecfg::Office::Common::PackageKit::EnableBaseInstallation::get())
164             {
165                 try
166                 {
167                     using namespace org::freedesktop::PackageKit;
168                     using namespace svtools;
169                     Reference< XSyncDbusSessionHelper > xSyncDbusSessionHelper(SyncDbusSessionHelper::create(comphelper::getProcessComponentContext()));
170                     Sequence< OUString > vPackages { "libreoffice-base" };
171                     xSyncDbusSessionHelper->InstallPackageNames(vPackages, OUString());
172                     // I'll be back (hopefully)!
173                     SolarMutexGuard aGuard;
174                     executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, RESTART_REASON_BIBLIOGRAPHY_INSTALL);
175                 }
176                 catch (const Exception &)
177                 {
178                     TOOLS_INFO_EXCEPTION("sfx.appl", "trying to install LibreOffice Base");
179                 }
180             }
181             return;
182         }
183 
184         try // fdo#48775
185         {
186             SfxStringItem aURL(SID_FILE_NAME, ".component:Bibliography/View1");
187             SfxStringItem aRef(SID_REFERER, "private:user");
188             SfxStringItem aTarget(SID_TARGETNAME, "_blank");
189             SfxViewFrame::Current()->GetDispatcher()->ExecuteList(SID_OPENDOC,
190                 SfxCallMode::ASYNCHRON, { &aURL, &aRef, &aTarget });
191         }
192         catch (const Exception &)
193         {
194             TOOLS_INFO_EXCEPTION( "sfx.appl", "trying to load bibliography database");
195         }
196     }
197 }
198 /// Find the correct location of the document (CREDITS.fodt, etc.), and return
199 /// it in rURL if found.
checkURL(const char * pName,const char * pExt,OUString & rURL)200 static bool checkURL( const char *pName, const char *pExt, OUString &rURL )
201 {
202     using namespace osl;
203     DirectoryItem aDirItem;
204 
205 #ifdef MACOSX
206     rURL = "$BRAND_BASE_DIR/Resources/" + OUString::createFromAscii( pName ) +
207            OUString::createFromAscii( pExt );
208 #else
209     rURL = "$BRAND_BASE_DIR/" + OUString::createFromAscii( pName ) +
210            OUString::createFromAscii( pExt );
211 #endif
212     rtl::Bootstrap::expandMacros( rURL );
213 
214     if (!rURL.isEmpty())
215         return DirectoryItem::get( rURL, aDirItem ) == DirectoryItem::E_None;
216     else
217         return false;
218 }
219 
220 /// Displays CREDITS or LICENSE in any of the available version
showDocument(const char * pBaseName)221 static void showDocument( const char* pBaseName )
222 {
223     try {
224         Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
225         auto args(::comphelper::InitPropertySequence({
226             {"ViewOnly",    makeAny(true)},
227             {"ReadOnly",    makeAny(true)}
228         }));
229 
230         OUString aURL;
231         if ( checkURL ( pBaseName, ".fodt", aURL ) ||
232              checkURL ( pBaseName, ".html", aURL ) ||
233              checkURL ( pBaseName, "", aURL ) ) {
234             xDesktop->loadComponentFromURL( aURL, "_blank", 0, args );
235         }
236     } catch (const css::uno::Exception &) {
237     }
238 }
239 
240 namespace
241 {
GetRequestFrame(const SfxRequest & rReq)242     Reference<XFrame> GetRequestFrame(const SfxRequest& rReq)
243     {
244         const SfxItemSet* pArgs = rReq.GetInternalArgs_Impl();
245         const SfxPoolItem* pItem = nullptr;
246         Reference <XFrame> xFrame;
247         if (pArgs && pArgs->GetItemState(SID_FILLFRAME, false, &pItem) == SfxItemState::SET)
248         {
249             OSL_ENSURE( dynamic_cast< const SfxUnoFrameItem *>( pItem ) !=  nullptr, "SfxApplication::OfaExec_Impl: XFrames are to be transported via SfxUnoFrameItem by now!" );
250             xFrame = static_cast< const SfxUnoFrameItem*>( pItem )->GetFrame();
251         }
252         return xFrame;
253     }
254 
255     class LicenseDialog : public weld::GenericDialogController
256     {
257     public:
LicenseDialog(weld::Window * pParent)258         LicenseDialog(weld::Window* pParent)
259             : GenericDialogController(pParent, "sfx/ui/licensedialog.ui",  "LicenseDialog")
260         {
261         }
262 
run()263         virtual short run() override
264         {
265             short nRet = GenericDialogController::run();
266             if (nRet == RET_OK)
267                 showDocument("LICENSE");
268             return nRet;
269         }
270     };
271 
272     class SafeModeQueryDialog : public weld::MessageDialogController
273     {
274     public:
SafeModeQueryDialog(weld::Window * pParent)275         SafeModeQueryDialog(weld::Window* pParent)
276             : MessageDialogController(pParent, "sfx/ui/safemodequerydialog.ui", "SafeModeQueryDialog")
277         {
278         }
279 
run()280         virtual short run() override
281         {
282             short nRet = MessageDialogController::run();
283             if (nRet == RET_OK)
284             {
285                 sfx2::SafeMode::putFlag();
286                 uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
287                 css::task::OfficeRestartManager::get(xContext)->requestRestart(
288                     css::uno::Reference< css::task::XInteractionHandler >());
289             }
290             return nRet;
291         }
292     };
293 }
294 
GetFrameWeld() const295 weld::Window* SfxRequest::GetFrameWeld() const
296 {
297     const SfxItemSet* pIntArgs = GetInternalArgs_Impl();
298     const SfxPoolItem* pItem = nullptr;
299     if (pIntArgs && pIntArgs->GetItemState(SID_DIALOG_PARENT, false, &pItem) == SfxItemState::SET)
300     {
301         assert(dynamic_cast<const SfxUnoAnyItem*>(pItem));
302         auto aAny = static_cast<const SfxUnoAnyItem*>(pItem)->GetValue();
303         Reference<awt::XWindow> xWindow;
304         aAny >>= xWindow;
305         return Application::GetFrameWeld(xWindow);
306     }
307 
308     Reference<XFrame> xFrame(GetRequestFrame(*this));
309     if (!xFrame)
310     {
311         SAL_WARN("sfx.appl", "no parent for dialogs");
312         return nullptr;
313     }
314     return Application::GetFrameWeld(xFrame->getContainerWindow());
315 }
316 
MiscExec_Impl(SfxRequest & rReq)317 void SfxApplication::MiscExec_Impl( SfxRequest& rReq )
318 {
319     bool bDone = false;
320     switch ( rReq.GetSlot() )
321     {
322         case SID_SETOPTIONS:
323         {
324             if( rReq.GetArgs() )
325                 SetOptions_Impl( *rReq.GetArgs() );
326             break;
327         }
328 
329         case SID_QUITAPP:
330         case SID_LOGOUT:
331         {
332             // protect against reentrant calls
333             if ( pImpl->bInQuit )
334                 return;
335 
336             if ( rReq.GetSlot() == SID_LOGOUT )
337             {
338                 for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
339                     pObjSh; pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
340                 {
341                     if ( !pObjSh->IsModified() )
342                         continue;
343 
344                     SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pObjSh );
345                     if ( !pFrame || !pFrame->GetWindow().IsReallyVisible() )
346                         continue;
347 
348                     if (pObjSh->PrepareClose())
349                         pObjSh->SetModified( false );
350                     else
351                         return;
352                 }
353 
354                 SfxStringItem aNameItem( SID_FILE_NAME, "vnd.sun.star.cmd:logout" );
355                 SfxStringItem aReferer( SID_REFERER, "private/user" );
356                 pImpl->pAppDispat->ExecuteList(SID_OPENDOC,
357                         SfxCallMode::SLOT, { &aNameItem, &aReferer });
358                 return;
359             }
360 
361             // try from nested requests again after 100ms
362             if( Application::GetDispatchLevel() > 1 )
363             {
364                 /* Don't save the request for closing the application and try it later
365                    again. This is an UI bound functionality ... and the user will  try it again
366                    if the dialog is closed. But we should not close the application automatically
367                    if this dialog is closed by the user ...
368                    So we ignore this request now and wait for a new user decision.
369                 */
370                 SAL_INFO("sfx.appl", "QueryExit => sal_False, DispatchLevel == " << Application::GetDispatchLevel() );
371                 return;
372             }
373 
374             // block reentrant calls
375             pImpl->bInQuit = true;
376             Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
377 
378             rReq.ForgetAllArgs();
379 
380             // if terminate() failed, pImpl->bInQuit will now be sal_False, allowing further calls of SID_QUITAPP
381             bool bTerminated = xDesktop->terminate();
382             if (!bTerminated)
383                 // if terminate() was successful, SfxApplication is now dead!
384                 pImpl->bInQuit = false;
385 
386             // Set return value, terminate if possible
387             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bTerminated ) );
388             return;
389         }
390 
391         case SID_CONFIG:
392         case SID_TOOLBOXOPTIONS:
393         case SID_CONFIGSTATUSBAR:
394         case SID_CONFIGMENU:
395         case SID_CONFIGACCEL:
396         case SID_CONFIGEVENT:
397         {
398             SfxAbstractDialogFactory* pFact =
399                 SfxAbstractDialogFactory::Create();
400 
401             const SfxStringItem* pStringItem = rReq.GetArg<SfxStringItem>(SID_CONFIG);
402 
403             SfxItemSet aSet(
404                 GetPool(), svl::Items<SID_CONFIG, SID_CONFIG>{} );
405 
406             if ( pStringItem )
407             {
408                 aSet.Put( SfxStringItem(
409                     SID_CONFIG, pStringItem->GetValue() ) );
410             }
411 
412             Reference <XFrame> xFrame(GetRequestFrame(rReq));
413             ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateCustomizeTabDialog(rReq.GetFrameWeld(),
414                 &aSet, xFrame ));
415 
416             const short nRet = pDlg->Execute();
417 
418             if ( nRet )
419                 bDone = true;
420             break;
421         }
422 
423         case SID_CLOSEDOCS:
424         {
425 
426             Reference < XDesktop2 > xDesktop  = Desktop::create( ::comphelper::getProcessComponentContext() );
427             Reference< XIndexAccess > xTasks = xDesktop->getFrames();
428             if ( !xTasks.is() )
429                 break;
430 
431             sal_Int32 n=0;
432             do
433             {
434                 if ( xTasks->getCount() <= n )
435                     break;
436 
437                 Any aAny = xTasks->getByIndex(n);
438                 Reference < XCloseable > xTask;
439                 aAny >>= xTask;
440                 try
441                 {
442                     xTask->close(true);
443                     n++;
444                 }
445                 catch( CloseVetoException& )
446                 {
447                 }
448             }
449             while( true );
450 
451             bool bOk = ( n == 0);
452             rReq.SetReturnValue( SfxBoolItem( 0, bOk ) );
453             bDone = true;
454             break;
455         }
456 
457         case SID_SAVEDOCS:
458         {
459             bool bOK = true;
460             for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
461                   pObjSh;
462                   pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
463             {
464                 SfxRequest aReq( SID_SAVEDOC, SfxCallMode::SLOT, pObjSh->GetPool() );
465                 if ( pObjSh->IsModified() )
466                 {
467                     pObjSh->ExecuteSlot( aReq );
468                     const SfxBoolItem *pItem = dynamic_cast<const SfxBoolItem*>( aReq.GetReturnValue()  );
469                     if ( !pItem || !pItem->GetValue() )
470                         bOK = false;
471                 }
472             }
473 
474             rReq.SetReturnValue( SfxBoolItem( 0, bOK ) );
475             rReq.Done();
476             break;
477         }
478 
479         case SID_SEND_FEEDBACK:
480         {
481             OUString module = SfxHelp::GetCurrentModuleIdentifier();
482             OUString sURL(officecfg::Office::Common::Menus::SendFeedbackURL::get() + //officecfg/registry/data/org/openoffice/Office/Common.xcu => https://hub.libreoffice.org/send-feedback/
483                 "?LOversion=" + utl::ConfigManager::getAboutBoxProductVersion() +
484                 "&LOlocale=" + utl::ConfigManager::getUILocale() +
485                 "&LOmodule=" + module.subView(module.lastIndexOf('.') + 1 )  );
486             sfx2::openUriExternally(sURL, false);
487             break;
488         }
489 
490         case SID_Q_AND_A:
491         {
492             // Askbot has URL's normalized to languages, not locales
493             // Get language from locale: ll or lll or ll-CC or lll-CC
494 
495             OUString sURL(officecfg::Office::Common::Menus::QA_URL::get() + //https://hub.libreoffice.org/forum/
496                 "?LOlocale=" + utl::ConfigManager::getUILocale());
497             sfx2::openUriExternally(sURL, false);
498             break;
499         }
500         case SID_DOCUMENTATION:
501         {
502             // Open documentation page based on locales
503             OUString sURL(officecfg::Office::Common::Menus::DocumentationURL::get() + //https://hub.libreoffice.org/documentation/
504                 "?LOlocale=" + utl::ConfigManager::getUILocale());
505             sfx2::openUriExternally(sURL, false);
506             break;
507         }
508         case SID_GETINVOLVED:
509         {
510             // Open get involved/join us page based on locales
511             OUString sURL(officecfg::Office::Common::Menus::GetInvolvedURL::get() + //https://hub.libreoffice.org/joinus/
512                 "?LOlocale=" + utl::ConfigManager::getUILocale());
513             sfx2::openUriExternally(sURL, false);
514             break;
515         }
516         case SID_DONATION:
517         {
518             // Open donation page based on language + script (BCP47) with language as fall back.
519             OUString aLang = LanguageTag(utl::ConfigManager::getUILocale()).getLanguage();
520             OUString aBcp47 = LanguageTag(utl::ConfigManager::getUILocale()).getBcp47();
521             OUString sURL(officecfg::Office::Common::Menus::DonationURL::get() + //https://hub.libreoffice.org/donation/
522                 "?BCP47=" + aBcp47 + "&LOlang=" + aLang );
523             sfx2::openUriExternally(sURL, false);
524             break;
525         }
526         case SID_WHATSNEW:
527         {
528             // Open release notes depending on version and locale
529             OUString sURL(officecfg::Office::Common::Menus::ReleaseNotesURL::get() + //https://hub.libreoffice.org/ReleaseNotes/
530                 "?LOvers=" + utl::ConfigManager::getProductVersion() +
531                 "&LOlocale=" + LanguageTag(utl::ConfigManager::getUILocale()).getBcp47() );
532             sfx2::openUriExternally(sURL, false);
533             break;
534         }
535         case SID_SHOW_LICENSE:
536         {
537             LicenseDialog aDialog(rReq.GetFrameWeld());
538             aDialog.run();
539             break;
540         }
541 
542         case SID_SHOW_CREDITS:
543         {
544             showDocument( "CREDITS" );
545             break;
546         }
547 
548         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
549         case SID_HELPINDEX:
550         {
551             Help* pHelp = Application::GetHelp();
552             if ( pHelp )
553             {
554                 pHelp->Start(".uno:HelpIndex", rReq.GetFrameWeld()); // show start page
555                 bDone = true;
556             }
557             break;
558         }
559 
560         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
561         case SID_HELPTIPS:
562         {
563             // Evaluate Parameter
564             const SfxBoolItem* pOnItem = rReq.GetArg<SfxBoolItem>(SID_HELPTIPS);
565             bool bOn = pOnItem
566                             ? pOnItem->GetValue()
567                             : !Help::IsQuickHelpEnabled();
568 
569             if ( bOn )
570                 Help::EnableQuickHelp();
571             else
572                 Help::DisableQuickHelp();
573             SvtHelpOptions().SetHelpTips( bOn );
574             Invalidate(SID_HELPTIPS);
575             bDone = true;
576 
577             // Record if possible
578             if ( !rReq.IsAPI() )
579                 rReq.AppendItem( SfxBoolItem( SID_HELPTIPS, bOn) );
580             break;
581         }
582         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
583         case SID_EXTENDEDHELP:
584         {
585             Help::StartExtHelp();
586             break;
587         }
588         case SID_HELPBALLOONS:
589         {
590             // Evaluate Parameter
591             const SfxBoolItem* pOnItem = rReq.GetArg<SfxBoolItem>(SID_HELPBALLOONS);
592             bool bOn = pOnItem
593                             ? pOnItem->GetValue()
594                             : !Help::IsBalloonHelpEnabled();
595 
596             if ( bOn )
597                 Help::EnableBalloonHelp();
598             else
599                 Help::DisableBalloonHelp();
600             SvtHelpOptions().SetExtendedHelp( bOn );
601             Invalidate(SID_HELPBALLOONS);
602             bDone = true;
603 
604             // Record if possible
605             if ( !rReq.IsAPI() )
606                 rReq.AppendItem( SfxBoolItem( SID_HELPBALLOONS, bOn) );
607             break;
608         }
609         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
610         case SID_TIPOFTHEDAY:
611         {
612             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
613             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateTipOfTheDayDialog(rReq.GetFrameWeld()));
614             pDlg->StartExecuteAsync(nullptr);
615             bDone = true;
616             break;
617         }
618 
619         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
620         case SID_ABOUT:
621         {
622             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
623             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateAboutDialog(rReq.GetFrameWeld()));
624             pDlg->Execute();
625             bDone = true;
626             break;
627         }
628 
629         case SID_TEMPLATE_MANAGER:
630         {
631             SfxTemplateManagerDlg aDialog(rReq.GetFrameWeld());
632             aDialog.run();
633             bDone = true;
634             break;
635         }
636 
637         case SID_TEMPLATE_ADDRESSBOOKSOURCE:
638         {
639             svt::AddressBookSourceDialog aDialog(rReq.GetFrameWeld(), ::comphelper::getProcessComponentContext());
640             aDialog.run();
641             bDone = true;
642             break;
643         }
644 
645 #if HAVE_FEATURE_SCRIPTING
646         case SID_BASICSTOP:
647             StarBASIC::Stop();
648             break;
649 
650         case SID_BASICBREAK :
651             BasicDLL::BasicBreak();
652             break;
653 #endif
654 
655         case SID_ZOOM_50_PERCENT:
656         case SID_ZOOM_75_PERCENT:
657         case SID_ZOOM_100_PERCENT:
658         case SID_ZOOM_150_PERCENT:
659         case SID_ZOOM_200_PERCENT:
660         case SID_ZOOM_OPTIMAL:
661         case SID_ZOOM_ENTIRE_PAGE:
662         case SID_ZOOM_PAGE_WIDTH:
663         {
664             SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
665             if (!pCurrentShell)
666                 return;
667 
668             // make sure aZoom is initialized with a proper value if SetType
669             // doesn't work
670             SvxZoomItem aZoom( SvxZoomType::PERCENT, 100 );
671 
672             switch (rReq.GetSlot())
673             {
674                 case SID_ZOOM_50_PERCENT:
675                     aZoom.SetValue(50);
676                     break;
677                 case SID_ZOOM_75_PERCENT:
678                     aZoom.SetValue(75);
679                     break;
680                 case SID_ZOOM_100_PERCENT:
681                     aZoom.SetValue(100);
682                     break;
683                 case SID_ZOOM_150_PERCENT:
684                     aZoom.SetValue(150);
685                     break;
686                 case SID_ZOOM_200_PERCENT:
687                     aZoom.SetValue(200);
688                     break;
689                 case SID_ZOOM_OPTIMAL:
690                     aZoom.SetType( SvxZoomType::OPTIMAL );
691                     break;
692                 case SID_ZOOM_ENTIRE_PAGE:
693                     aZoom.SetType( SvxZoomType::WHOLEPAGE );
694                     break;
695                 case SID_ZOOM_PAGE_WIDTH:
696                     aZoom.SetType( SvxZoomType::PAGEWIDTH );
697                     break;
698             }
699 
700             pCurrentShell->GetDispatcher()->ExecuteList(SID_ATTR_ZOOM, SfxCallMode::ASYNCHRON, { &aZoom });
701 
702             break;
703         }
704         case SID_TOOLBAR_MODE:
705         {
706             const SfxStringItem* pModeName = rReq.GetArg<SfxStringItem>( SID_TOOLBAR_MODE );
707 
708             if ( !pModeName )
709             {
710                 bDone = true;
711                 break;
712             }
713 
714             OUString aNewName(pModeName->GetValue());
715             uno::Reference< uno::XComponentContext > xContext =
716                     ::comphelper::getProcessComponentContext();
717 
718             // Get information about current frame and module
719             Reference<XFrame> xCurrentFrame;
720             vcl::EnumContext::Application eCurrentApp = vcl::EnumContext::Application::NONE;
721             OUString aCurrentMode;
722 
723             SfxViewFrame* pViewFrame = SfxViewFrame::Current();
724             if( pViewFrame )
725             {
726                 xCurrentFrame = pViewFrame->GetFrame().GetFrameInterface();
727 
728                 const Reference<frame::XModuleManager> xModuleManager  = frame::ModuleManager::create( xContext );
729                 eCurrentApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xCurrentFrame ) );
730 
731                 OUString aPath = "org.openoffice.Office.UI.ToolbarMode/Applications/" +
732                     lcl_getAppName( eCurrentApp );
733 
734                 const utl::OConfigurationTreeRoot aAppNode(
735                                                     xContext,
736                                                     aPath,
737                                                     true);
738                 if ( !aAppNode.isValid() )
739                 {
740                     bDone = true;
741                     break;
742                 }
743 
744                 aCurrentMode = comphelper::getString( aAppNode.getNodeValue( "Active" ) );
745 
746                 if ( aCurrentMode == aNewName )
747                 {
748                     bDone = true;
749                     break;
750                 }
751 
752                 // Save new toolbar mode for a current module
753                 aAppNode.setNodeValue( "Active", makeAny( aNewName ) );
754                 aAppNode.commit();
755             }
756 
757             // Apply settings for all frames
758             pViewFrame = SfxViewFrame::GetFirst();
759             while( pViewFrame )
760             {
761                 Reference<XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
762 
763                 // We want to change mode only for a current app module, ignore other apps
764                 const Reference<frame::XModuleManager> xModuleManager  = frame::ModuleManager::create( xContext );
765                 vcl::EnumContext::Application eApp = vcl::EnumContext::GetApplicationEnum( xModuleManager->identify( xFrame ) );
766                 if ( eApp != eCurrentApp )
767                 {
768                     pViewFrame = SfxViewFrame::GetNext( *pViewFrame );
769                     continue;
770                 }
771 
772                 Reference<css::beans::XPropertySet> xPropSet( xFrame, UNO_QUERY );
773                 Reference<css::frame::XLayoutManager> xLayoutManager;
774                 if ( xPropSet.is() )
775                 {
776                     try
777                     {
778                         Any aValue = xPropSet->getPropertyValue( "LayoutManager" );
779                         aValue >>= xLayoutManager;
780                     }
781                     catch ( const css::uno::RuntimeException& )
782                     {
783                         throw;
784                     }
785                     catch ( css::uno::Exception& )
786                     {
787                     }
788                 }
789 
790                 if ( xLayoutManager.is() )
791                 {
792                     css::uno::Sequence<OUString> aMandatoryToolbars;
793                     css::uno::Sequence<OUString> aUserToolbars;
794                     std::vector<OUString> aBackupList;
795                     OUString aSidebarMode;
796 
797                     OUString aPath = "org.openoffice.Office.UI.ToolbarMode/Applications/" +
798                         lcl_getAppName( eApp ) +
799                         "/Modes";
800 
801                     // Read mode settings
802                     const utl::OConfigurationTreeRoot aModesNode(
803                                             xContext,
804                                             aPath,
805                                             true);
806                     if ( !aModesNode.isValid() )
807                     {
808                         bDone = true;
809                         break;
810                     }
811 
812                     const Sequence<OUString> aModeNodeNames( aModesNode.getNodeNames() );
813 
814                     for ( const auto& rModeNodeName : aModeNodeNames )
815                     {
816                         const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
817                         if ( !aModeNode.isValid() )
818                             continue;
819 
820                         OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
821 
822                         if ( aCommandArg == aNewName )
823                         {
824                             aMandatoryToolbars = aModeNode.getNodeValue( "Toolbars" ).get< uno::Sequence<OUString> >();
825                             aUserToolbars = aModeNode.getNodeValue( "UserToolbars" ).get< uno::Sequence<OUString> >();
826                             aSidebarMode = comphelper::getString( aModeNode.getNodeValue( "Sidebar" ) );
827                             break;
828                         }
829                     }
830 
831                     // Backup visible toolbar list and hide all toolbars
832                     const Sequence<Reference<XUIElement>> aUIElements = xLayoutManager->getElements();
833                     for ( const Reference< XUIElement >& xUIElement : aUIElements )
834                     {
835                         Reference< XPropertySet > xPropertySet( xUIElement, UNO_QUERY );
836                         if ( xPropertySet.is() && xUIElement.is() )
837                         {
838                             try
839                             {
840                                 OUString aResName;
841                                 sal_Int16 nType( -1 );
842                                 xPropertySet->getPropertyValue( "Type" ) >>= nType;
843                                 xPropertySet->getPropertyValue( "ResourceURL" ) >>= aResName;
844 
845                                 if (( nType == css::ui::UIElementType::TOOLBAR ) &&
846                                     !aResName.isEmpty() )
847                                 {
848                                     if ( xLayoutManager->isElementVisible( aResName ) )
849                                     {
850                                         aBackupList.push_back( aResName );
851                                     }
852                                     xLayoutManager->hideElement( aResName );
853                                 }
854                             }
855                             catch ( const Exception& )
856                             {
857                             }
858                         }
859                     }
860 
861                     // Show/Hide the Notebookbar
862                     const SfxStringItem pItem(SID_NOTEBOOKBAR, aNewName);
863                     pViewFrame->GetDispatcher()->ExecuteList(SID_NOTEBOOKBAR, SfxCallMode::SYNCHRON, {&pItem});
864 
865                     // Show toolbars
866                     for ( const OUString& rName : std::as_const(aMandatoryToolbars) )
867                     {
868                         xLayoutManager->createElement( rName );
869                         xLayoutManager->showElement( rName );
870                     }
871 
872                     for ( const OUString& rName : std::as_const(aUserToolbars) )
873                     {
874                         xLayoutManager->createElement( rName );
875                         xLayoutManager->showElement( rName );
876                     }
877 
878                     // Sidebar
879                     pViewFrame->ShowChildWindow( SID_SIDEBAR );
880 
881                     sfx2::sidebar::SidebarController* pSidebar =
882                             sfx2::sidebar::SidebarController::GetSidebarControllerForFrame( xFrame );
883                     if ( pSidebar )
884                     {
885                         if ( aSidebarMode == "Arrow" )
886                         {
887                             pSidebar->FadeOut();
888                         }
889                         else if ( aSidebarMode == "Tabs" )
890                         {
891                             pSidebar->FadeIn();
892                             pSidebar->RequestOpenDeck();
893                             pSidebar->RequestCloseDeck();
894                         }
895                         else if ( aSidebarMode == "Opened" )
896                         {
897                             pSidebar->FadeIn();
898                             pSidebar->RequestOpenDeck();
899                         }
900                     }
901 
902                     // Save settings
903                     if ( pViewFrame == SfxViewFrame::Current() )
904                     {
905                         css::uno::Sequence<OUString> aBackup( comphelper::containerToSequence(aBackupList) );
906 
907                         for ( const auto& rModeNodeName : aModeNodeNames )
908                         {
909                             const utl::OConfigurationNode aModeNode( aModesNode.openNode( rModeNodeName ) );
910                             if ( !aModeNode.isValid() )
911                                 continue;
912 
913                             OUString aCommandArg = comphelper::getString( aModeNode.getNodeValue( "CommandArg" ) );
914 
915                             if ( aCommandArg == aCurrentMode )
916                             {
917                                 aModeNode.setNodeValue( "UserToolbars", makeAny( aBackup ) );
918                                 break;
919                             }
920                         }
921                         aModesNode.commit();
922                     }
923                 }
924 
925                 pViewFrame = SfxViewFrame::GetNext(*pViewFrame);
926             }
927 
928             bDone = true;
929             break;
930         }
931         case SID_TOOLBAR_MODE_UI:
932         {
933             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
934             ScopedVclPtr<VclAbstractDialog> pDlg(
935                 pFact->CreateToolbarmodeDialog(rReq.GetFrameWeld()));
936             pDlg->Execute();
937             bDone = true;
938             break;
939         }
940         case SID_AVAILABLE_TOOLBARS:
941         {
942             const SfxStringItem* pToolbarName = rReq.GetArg<SfxStringItem>(SID_AVAILABLE_TOOLBARS);
943 
944             if ( pToolbarName )
945             {
946                 Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
947                 Reference< XFrame > xFrame = xDesktop->getActiveFrame();
948 
949                 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
950                 Reference< css::frame::XLayoutManager > xLayoutManager;
951                 if ( xPropSet.is() )
952                 {
953                     try
954                     {
955                         Any aValue = xPropSet->getPropertyValue("LayoutManager");
956                         aValue >>= xLayoutManager;
957                     }
958                     catch ( const css::uno::RuntimeException& )
959                     {
960                         throw;
961                     }
962                     catch ( css::uno::Exception& )
963                     {
964                     }
965                 }
966 
967                 if ( xLayoutManager.is() )
968                 {
969                     OUString aToolbarName = "private:resource/toolbar/" +
970                         pToolbarName->GetValue();
971 
972                     // Evaluate Parameter
973                     bool bShow( !xLayoutManager->isElementVisible( aToolbarName ));
974 
975                     if ( bShow )
976                     {
977                         xLayoutManager->createElement( aToolbarName );
978                         xLayoutManager->showElement( aToolbarName );
979                     }
980                     else
981                         xLayoutManager->hideElement( aToolbarName );
982                 }
983             }
984 
985             bDone = true;
986             break;
987         }
988         case SID_MENUBAR:
989         {
990             sfx2::SfxNotebookBar::ToggleMenubar();
991             bDone = true;
992             break;
993         }
994         case SID_DEVELOPMENT_TOOLS_DOCKING_WINDOW:
995         {
996             SfxViewShell* pViewShell = SfxViewShell::Current();
997             SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
998             auto nID = rReq.GetSlot();
999             pViewFrame->ToggleChildWindow(nID);
1000 
1001             bDone = true;
1002             break;
1003         }
1004         case SID_INSPECT_SELECTED_OBJECT:
1005         {
1006             SfxViewShell* pViewShell = SfxViewShell::Current();
1007             SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
1008 
1009             pViewFrame->ShowChildWindow(SID_DEVELOPMENT_TOOLS_DOCKING_WINDOW, true);
1010 
1011             SfxChildWindow* pChild = pViewFrame->GetChildWindow(SID_DEVELOPMENT_TOOLS_DOCKING_WINDOW);
1012             if (!pChild)
1013                 return;
1014 
1015             auto pDockingWin = dynamic_cast<DevelopmentToolDockingWindow*>(pChild->GetWindow());
1016             if (pDockingWin)
1017             {
1018                 pDockingWin->changeToCurrentSelection();
1019             }
1020 
1021             bDone = true;
1022             break;
1023         }
1024         case SID_SAFE_MODE:
1025         {
1026             SafeModeQueryDialog aDialog(rReq.GetFrameWeld());
1027             aDialog.run();
1028             break;
1029         }
1030         case SID_TOOLBAR_LOCK:
1031         {
1032             SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1033             if (pViewFrame)
1034             {
1035                 Reference<XFrame> xCurrentFrame;
1036                 uno::Reference<uno::XComponentContext> xContext
1037                     = ::comphelper::getProcessComponentContext();
1038                 xCurrentFrame = pViewFrame->GetFrame().GetFrameInterface();
1039                 const Reference<frame::XModuleManager> xModuleManager
1040                     = frame::ModuleManager::create(xContext);
1041                 const utl::OConfigurationTreeRoot aAppNode(
1042                     xContext, "org.openoffice.Office.UI.GlobalSettings/Toolbars/States", true);
1043                 if (aAppNode.isValid())
1044                 {
1045                     bool isLocked = comphelper::getBOOL(aAppNode.getNodeValue("Locked"));
1046                     aAppNode.setNodeValue("Locked", makeAny(!isLocked));
1047                     aAppNode.commit();
1048                     //TODO: apply immediately w/o restart needed
1049                     SolarMutexGuard aGuard;
1050                     svtools::executeRestartDialog(comphelper::getProcessComponentContext(), nullptr,
1051                                                   svtools::RESTART_REASON_UI_CHANGE);
1052                 }
1053             }
1054             break;
1055         }
1056         default:
1057             break;
1058     }
1059 
1060     if ( bDone )
1061         rReq.Done();
1062 }
1063 
MiscState_Impl(SfxItemSet & rSet)1064 void SfxApplication::MiscState_Impl(SfxItemSet &rSet)
1065 {
1066     const sal_uInt16 *pRanges = rSet.GetRanges();
1067     DBG_ASSERT(pRanges && *pRanges, "Set without range");
1068     while ( *pRanges )
1069     {
1070         for(sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich)
1071         {
1072             switch(nWhich)
1073             {
1074                 case SID_TEMPLATE_ADDRESSBOOKSOURCE:
1075                     if ( !SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::DATABASE) )
1076                         rSet.Put(SfxVisibilityItem(nWhich, false));
1077                     break;
1078                 case SID_QUITAPP:
1079                 {
1080                     if ( pImpl->nDocModalMode )
1081                         rSet.DisableItem(nWhich);
1082                     else
1083                         rSet.Put(SfxStringItem(nWhich, SfxResId(STR_QUITAPP)));
1084                     break;
1085                 }
1086 
1087                 case SID_CONFIG:
1088                 case SID_TOOLBOXOPTIONS:
1089                 case SID_CONFIGSTATUSBAR:
1090                 case SID_CONFIGMENU:
1091                 case SID_CONFIGACCEL:
1092                 case SID_CONFIGEVENT:
1093                 {
1094                     if( SvtMiscOptions().DisableUICustomization() )
1095                         rSet.DisableItem(nWhich);
1096                     break;
1097                 }
1098 
1099 #if HAVE_FEATURE_SCRIPTING
1100                 case SID_BASICSTOP:
1101                     if ( !StarBASIC::IsRunning() )
1102                         rSet.DisableItem(nWhich);
1103                     break;
1104 #endif
1105 
1106                 case SID_HELPTIPS:
1107                 {
1108                     rSet.Put( SfxBoolItem( SID_HELPTIPS, Help::IsQuickHelpEnabled() ) );
1109                 }
1110                 break;
1111                 case SID_HELPBALLOONS:
1112                 {
1113                     rSet.Put( SfxBoolItem( SID_HELPBALLOONS, Help::IsBalloonHelpEnabled() ) );
1114                 }
1115                 break;
1116 
1117                 case SID_EXTENDEDHELP:
1118                 {
1119                 }
1120                 break;
1121 
1122                 case SID_CLOSEDOCS:
1123                 {
1124                     Reference < XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1125                     Reference< XIndexAccess > xTasks = xDesktop->getFrames();
1126                     if ( !xTasks.is() || !xTasks->getCount() )
1127                         rSet.DisableItem(nWhich);
1128                     break;
1129                 }
1130 
1131                 case SID_SAVEDOCS:
1132                 {
1133                     bool bModified = false;
1134                     for ( SfxObjectShell *pObjSh = SfxObjectShell::GetFirst();
1135                           pObjSh;
1136                           pObjSh = SfxObjectShell::GetNext( *pObjSh ) )
1137                     {
1138                         if ( pObjSh->IsModified() )
1139                         {
1140                             bModified = true;
1141                             break;
1142                         }
1143                     }
1144 
1145                     if ( !bModified )
1146                         rSet.DisableItem( nWhich );
1147                     break;
1148                 }
1149 
1150                 case SID_TEMPLATE_MANAGER:
1151                     {
1152                         if ( !officecfg::Office::Common::Misc::ExperimentalMode::get() )
1153                         {
1154                            rSet.DisableItem( nWhich );
1155                            rSet.Put( SfxVisibilityItem( nWhich, false ) );
1156                         }
1157                     }
1158                     break;
1159 
1160                 case SID_ZOOM_50_PERCENT:
1161                 case SID_ZOOM_75_PERCENT:
1162                 case SID_ZOOM_100_PERCENT:
1163                 case SID_ZOOM_150_PERCENT:
1164                 case SID_ZOOM_200_PERCENT:
1165                 case SID_ZOOM_OPTIMAL:
1166                 case SID_ZOOM_ENTIRE_PAGE:
1167                 case SID_ZOOM_PAGE_WIDTH:
1168                     {
1169                         SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
1170 
1171                         const SfxPoolItem *pItem;
1172                         SfxItemState aState = pCurrentShell ?
1173                             pCurrentShell->GetDispatcher()->QueryState(SID_ATTR_ZOOM, pItem) : SfxItemState::DISABLED;
1174                         if ( aState == SfxItemState::DISABLED )
1175                             rSet.DisableItem( nWhich );
1176                     }
1177                     break;
1178 
1179                 case SID_MENUBAR:
1180                 {
1181                     Reference < XDesktop2 > xDesktop = Desktop::create ( ::comphelper::getProcessComponentContext() );
1182                     Reference< XFrame > xFrame = xDesktop->getActiveFrame();
1183 
1184                     Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
1185                     Reference< css::frame::XLayoutManager > xLayoutManager;
1186                     if ( xPropSet.is() )
1187                     {
1188                         try
1189                         {
1190                             Any aValue = xPropSet->getPropertyValue("LayoutManager");
1191                             aValue >>= xLayoutManager;
1192                         }
1193                         catch ( const css::uno::RuntimeException& )
1194                         {
1195                             throw;
1196                         }
1197                         catch ( css::uno::Exception& )
1198                         {
1199                         }
1200                     }
1201 
1202                     if ( xLayoutManager.is() )
1203                     {
1204                         const bool bState
1205                             = xLayoutManager->getElement("private:resource/menubar/menubar").is()
1206                               && xLayoutManager->isElementVisible(
1207                                      "private:resource/menubar/menubar");
1208 
1209                         SfxBoolItem aItem( SID_MENUBAR, bState );
1210                         rSet.Put( aItem );
1211                     }
1212                     break;
1213                 }
1214                 case SID_SAFE_MODE:
1215                 {
1216                     // no restart in safe mode when already in safe mode
1217                     if ( Application::IsSafeModeEnabled() )
1218                        rSet.DisableItem( SID_SAFE_MODE );
1219                     break;
1220                 }
1221                 case SID_DEVELOPMENT_TOOLS_DOCKING_WINDOW:
1222                 {
1223                     bool bSuccess = false;
1224                     auto* pViewShell = SfxViewShell::Current();
1225                     if (pViewShell)
1226                     {
1227                         auto* pViewFrame = pViewShell->GetViewFrame();
1228                         if (pViewFrame && pViewFrame->KnowsChildWindow(nWhich))
1229                         {
1230                             rSet.Put(SfxBoolItem(nWhich, pViewFrame->HasChildWindow(nWhich)));
1231                             bSuccess = true;
1232                         }
1233                     }
1234 
1235                     if (!bSuccess)
1236                         rSet.DisableItem(nWhich);
1237                 }
1238                 break;
1239                 case SID_INSPECT_SELECTED_OBJECT:
1240                 {
1241                     bool bSuccess = false;
1242                     auto* pViewShell = SfxViewShell::Current();
1243                     if (pViewShell)
1244                     {
1245                         auto* pViewFrame = pViewShell->GetViewFrame();
1246                         if (pViewFrame && pViewFrame->KnowsChildWindow(SID_DEVELOPMENT_TOOLS_DOCKING_WINDOW))
1247                         {
1248                             bSuccess = true;
1249                         }
1250                     }
1251                     if (!bSuccess)
1252                         rSet.DisableItem(nWhich);
1253                 }
1254                 break;
1255                 case SID_TOOLBAR_LOCK:
1256                 {
1257                     rSet.Put( SfxBoolItem( SID_TOOLBAR_LOCK, ToolBox::AlwaysLocked() ));
1258                 }
1259                 break;
1260                 default:
1261                     break;
1262             }
1263         }
1264 
1265         ++pRanges;
1266     }
1267 }
1268 
1269 #if HAVE_FEATURE_SCRIPTING
1270 
1271 #ifndef DISABLE_DYNLOADING
1272 
1273 typedef rtl_uString* (*basicide_choose_macro)(void*, void*, void*, sal_Bool);
1274 
1275 #else
1276 
1277 extern "C" rtl_uString* basicide_choose_macro(void*, void*, void*, sal_Bool);
1278 
1279 #endif
1280 
ChooseMacro(weld::Window * pParent,const Reference<XModel> & rxLimitToDocument,const Reference<XFrame> & xDocFrame,bool bChooseOnly)1281 static OUString ChooseMacro(weld::Window* pParent, const Reference<XModel>& rxLimitToDocument, const Reference<XFrame>& xDocFrame, bool bChooseOnly)
1282 {
1283 #ifndef DISABLE_DYNLOADING
1284     basicide_choose_macro pSymbol = reinterpret_cast<basicide_choose_macro>(sfx2::getBasctlFunction("basicide_choose_macro"));
1285 #else
1286 #define pSymbol basicide_choose_macro
1287 #endif
1288 
1289     // call basicide_choose_macro in basctl
1290     rtl_uString* pScriptURL = pSymbol(pParent, rxLimitToDocument.get(), xDocFrame.get(), bChooseOnly);
1291     OUString aScriptURL( pScriptURL );
1292     rtl_uString_release( pScriptURL );
1293     return aScriptURL;
1294 
1295 #ifdef DISABLE_DYNLOADING
1296 #undef pSymbol
1297 #endif
1298 }
1299 
1300 #endif
1301 
1302 namespace
1303 {
1304 #if HAVE_FEATURE_SCRIPTING
lcl_getDialogParent(const Reference<XFrame> & rxFrame)1305     weld::Window* lcl_getDialogParent(const Reference<XFrame>& rxFrame)
1306     {
1307         Reference<awt::XWindow> xContainerWindow;
1308         if (rxFrame.is())
1309             xContainerWindow = rxFrame->getContainerWindow();
1310         return Application::GetFrameWeld(xContainerWindow);
1311     }
1312 
lcl_getBasicIDEViewFrame(SfxObjectShell const * i_pBasicIDE)1313     SfxViewFrame* lcl_getBasicIDEViewFrame( SfxObjectShell const * i_pBasicIDE )
1314     {
1315         SfxViewFrame* pView = SfxViewFrame::GetFirst( i_pBasicIDE );
1316         while ( pView )
1317         {
1318             if ( pView->GetObjectShell()->GetFactory().GetDocumentServiceName() == "com.sun.star.script.BasicIDE" )
1319                 break;
1320             pView = SfxViewFrame::GetNext( *pView, i_pBasicIDE );
1321         }
1322         return pView;
1323     }
lcl_findStartModuleFrame(const Reference<XComponentContext> & rxContext)1324     Reference< XFrame > lcl_findStartModuleFrame( const Reference<XComponentContext> & rxContext )
1325     {
1326         try
1327         {
1328             Reference < XDesktop2 > xDesktop = Desktop::create( rxContext );
1329             Reference < XIndexAccess > xContainer( xDesktop->getFrames(), UNO_QUERY_THROW );
1330 
1331             Reference< XModuleManager2 > xCheck = ModuleManager::create(rxContext);
1332 
1333             sal_Int32 nCount = xContainer->getCount();
1334             for ( sal_Int32 i=0; i<nCount; ++i )
1335             {
1336                 try
1337                 {
1338                     Reference < XFrame > xFrame( xContainer->getByIndex(i), UNO_QUERY_THROW );
1339                     OUString sModule = xCheck->identify( xFrame );
1340                     if ( sModule == "com.sun.star.frame.StartModule" )
1341                         return xFrame;
1342                 }
1343                 catch( const UnknownModuleException& )
1344                 {
1345                     // silence
1346                 }
1347                 catch(const Exception&)
1348                 {
1349                     // re-throw, caught below
1350                     throw;
1351                 }
1352             }
1353         }
1354         catch( const Exception& )
1355         {
1356                DBG_UNHANDLED_EXCEPTION("sfx.appl");
1357         }
1358         return nullptr;
1359     }
1360 #endif // HAVE_FEATURE_SCRIPTING
1361 }
1362 
OfaExec_Impl(SfxRequest & rReq)1363 void SfxApplication::OfaExec_Impl( SfxRequest& rReq )
1364 {
1365     switch ( rReq.GetSlot() )
1366     {
1367         case SID_OPTIONS_TREEDIALOG:
1368         {
1369             OUString sPageURL;
1370             const SfxStringItem* pURLItem = rReq.GetArg<SfxStringItem>(SID_OPTIONS_PAGEURL);
1371             if ( pURLItem )
1372                 sPageURL = pURLItem->GetValue();
1373             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1374             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1375             VclPtr<VclAbstractDialog> pDlg =
1376                 pFact->CreateFrameDialog(rReq.GetFrameWeld(), xFrame, rReq.GetSlot(), sPageURL );
1377             short nRet = pDlg->Execute();
1378             pDlg.disposeAndClear();
1379             SfxViewFrame* pView = SfxViewFrame::GetFirst();
1380             while ( pView )
1381             {
1382                 if (nRet == RET_OK)
1383                 {
1384                     SfxObjectShell* pObjSh = pView->GetObjectShell();
1385                     if (pObjSh)
1386                         pObjSh->SetConfigOptionsChecked(false);
1387                 }
1388                 pView->GetBindings().InvalidateAll(false);
1389                 pView = SfxViewFrame::GetNext( *pView );
1390             }
1391             break;
1392         }
1393 
1394         case SID_MORE_DICTIONARIES:
1395         {
1396             uno::Sequence<beans::PropertyValue> aArgs(1);
1397             aArgs[0].Name = "AdditionsTag";
1398             aArgs[0].Value <<= OUString("Dictionary");
1399             comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs);
1400             break;
1401         }
1402 #if HAVE_FEATURE_SCRIPTING
1403         case SID_BASICIDE_APPEAR:
1404         {
1405             SfxViewFrame* pView = lcl_getBasicIDEViewFrame( nullptr );
1406             if ( !pView )
1407             {
1408                 SfxObjectShell* pBasicIDE = SfxObjectShell::CreateObject( "com.sun.star.script.BasicIDE" );
1409                 pBasicIDE->DoInitNew();
1410                 pBasicIDE->SetModified( false );
1411                 try
1412                 {
1413                     // load the Basic IDE via direct access to the SFX frame loader. A generic loadComponentFromURL
1414                     // (which could be done via SfxViewFrame::LoadDocumentIntoFrame) is not feasible here, since the Basic IDE
1415                     // does not really play nice with the framework's concept. For instance, it is a "singleton document",
1416                     // which conflicts, at the latest, with the framework's concept of loading into _blank frames.
1417                     // So, since we know that our frame loader can handle it, we skip the generic framework loader
1418                     // mechanism, and the type detection (which doesn't know about the Basic IDE).
1419                     Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1420                     Reference< XSynchronousFrameLoader > xLoader(
1421                         xContext->getServiceManager()->createInstanceWithContext("com.sun.star.comp.office.FrameLoader", xContext),
1422                         UNO_QUERY_THROW );
1423                     ::comphelper::NamedValueCollection aLoadArgs;
1424                     aLoadArgs.put( "Model", pBasicIDE->GetModel() );
1425                     aLoadArgs.put( "URL", OUString( "private:factory/sbasic"  ) );
1426 
1427                     Reference< XFrame > xTargetFrame( lcl_findStartModuleFrame( xContext ) );
1428                     if ( !xTargetFrame.is() )
1429                         xTargetFrame = SfxFrame::CreateBlankFrame();
1430                     ENSURE_OR_THROW( xTargetFrame.is(), "could not obtain a frameto load the Basic IDE into!" );
1431 
1432                     xLoader->load( aLoadArgs.getPropertyValues(), xTargetFrame );
1433                 }
1434                 catch( const Exception& )
1435                 {
1436                     DBG_UNHANDLED_EXCEPTION("sfx.appl");
1437                 }
1438 
1439                 pView = lcl_getBasicIDEViewFrame( pBasicIDE );
1440                 if ( pView )
1441                     pView->SetName( "BASIC:1" );
1442             }
1443 
1444             if ( pView )
1445                 pView->GetFrame().Appear();
1446 
1447             const SfxItemSet* pArgs = rReq.GetArgs();
1448             if ( pArgs && pView )
1449             {
1450                 SfxViewShell* pViewShell = pView->GetViewShell();
1451                 SfxObjectShell* pObjShell = pView->GetObjectShell();
1452                 if ( pViewShell && pObjShell )
1453                 {
1454                     SfxRequest aReq( SID_BASICIDE_SHOWWINDOW, SfxCallMode::SYNCHRON, pObjShell->GetPool() );
1455                     aReq.SetArgs( *pArgs );
1456                     pViewShell->ExecuteSlot( aReq );
1457                 }
1458             }
1459 
1460             rReq.Done();
1461         }
1462         break;
1463 
1464         case SID_BASICCHOOSER:
1465         {
1466             const SfxItemSet* pArgs = rReq.GetArgs();
1467             const SfxPoolItem* pItem;
1468             bool bChooseOnly = false;
1469             Reference< XModel > xLimitToModel;
1470             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_RECORDMACRO, false, &pItem) )
1471             {
1472                 bool bRecord = static_cast<const SfxBoolItem*>(pItem)->GetValue();
1473                 if ( bRecord )
1474                 {
1475                     // !Hack
1476                     bChooseOnly = false;
1477                     SfxObjectShell* pCurrentShell = SfxObjectShell::Current();
1478                     OSL_ENSURE( pCurrentShell, "macro recording outside an SFX document?" );
1479                     if ( pCurrentShell )
1480                         xLimitToModel = pCurrentShell->GetModel();
1481                 }
1482             }
1483 
1484             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1485             rReq.SetReturnValue(SfxStringItem(rReq.GetSlot(), ChooseMacro(rReq.GetFrameWeld(), xLimitToModel, xFrame, bChooseOnly)));
1486             rReq.Done();
1487         }
1488         break;
1489 
1490         case SID_MACROORGANIZER:
1491         {
1492             SAL_INFO("sfx.appl", "handling SID_MACROORGANIZER");
1493             const SfxItemSet* pArgs = rReq.GetArgs();
1494             const SfxPoolItem* pItem;
1495             sal_Int16 nTabId = 0;
1496             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_MACROORGANIZER, false, &pItem) )
1497             {
1498                 nTabId = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
1499             }
1500 
1501             SfxApplication::MacroOrganizer(rReq.GetFrameWeld(), nTabId);
1502             rReq.Done();
1503         }
1504         break;
1505 
1506         case SID_RUNMACRO:
1507         {
1508             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1509             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: case ScriptOrg");
1510 
1511             Reference <XFrame> xFrame(GetRequestFrame(rReq));
1512             if ( !xFrame.is() )
1513             {
1514                 const SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1515                 if ( pViewFrame )
1516                     xFrame = pViewFrame->GetFrame().GetFrameInterface();
1517             }
1518 
1519             do  // artificial loop for flow control
1520             {
1521                 VclPtr<AbstractScriptSelectorDialog> pDlg(pFact->CreateScriptSelectorDialog(lcl_getDialogParent(xFrame), xFrame));
1522                 OSL_ENSURE( pDlg, "SfxApplication::OfaExec_Impl( SID_RUNMACRO ): no dialog!" );
1523                 if ( !pDlg )
1524                     break;
1525                 pDlg->SetRunLabel();
1526 
1527                 pDlg->StartExecuteAsync([pDlg, xFrame](sal_Int32 nDialogResult) {
1528                     if ( !nDialogResult )
1529                     {
1530                         pDlg->disposeOnce();
1531                         return;
1532                     }
1533 
1534                     Sequence< Any > args;
1535                     Sequence< sal_Int16 > outIndex;
1536                     Sequence< Any > outArgs;
1537                     Any ret;
1538 
1539                     Reference< XInterface > xScriptContext;
1540 
1541                     Reference< XController > xController;
1542                     if ( xFrame.is() )
1543                         xController = xFrame->getController();
1544                     if ( xController.is() )
1545                         xScriptContext = xController->getModel();
1546                     if ( !xScriptContext.is() )
1547                         xScriptContext = xController;
1548 
1549                     SfxObjectShell::CallXScript( xScriptContext, pDlg->GetScriptURL(), args, ret, outIndex, outArgs );
1550                     pDlg->disposeOnce();
1551                 });
1552             }
1553             while ( false );
1554             rReq.Done();
1555         }
1556         break;
1557 
1558         case SID_SCRIPTORGANIZER:
1559         {
1560             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1561             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: case ScriptOrg");
1562             const SfxItemSet* pArgs = rReq.GetArgs();
1563             const SfxPoolItem* pItem;
1564             OUString aLanguage;
1565             if(pArgs && SfxItemState::SET == pArgs->GetItemState(SID_SCRIPTORGANIZER, false, &pItem) )
1566             {
1567                 aLanguage = static_cast<const SfxScriptOrganizerItem*>(pItem)->getLanguage();
1568             }
1569 
1570             OUString aLang( aLanguage );
1571             SAL_INFO("sfx.appl", "SfxApplication::OfaExec_Impl: about to create dialog for: " << aLang);
1572             ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateSvxScriptOrgDialog(rReq.GetFrameWeld(), aLanguage));
1573             if( pDlg )
1574             {
1575                 pDlg->Execute();
1576             }
1577             else
1578             {
1579                 SAL_WARN("sfx.appl", "no dialog!!!");
1580             }
1581             rReq.Done();
1582         }
1583         break;
1584 #endif // HAVE_FEATURE_SCRIPTING
1585 
1586         case SID_OFFICE_CHECK_PLZ:
1587         {
1588             bool bRet = false;
1589             const SfxStringItem* pStringItem = rReq.GetArg<SfxStringItem>(rReq.GetSlot());
1590 
1591             if ( pStringItem )
1592             {
1593                 bRet = true /*!!!SfxIniManager::CheckPLZ( aPLZ )*/;
1594             }
1595 #if HAVE_FEATURE_SCRIPTING
1596             else
1597                 SbxBase::SetError( ERRCODE_BASIC_WRONG_ARGS );
1598 #endif
1599             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bRet ) );
1600         }
1601         break;
1602 
1603         case SID_AUTO_CORRECT_DLG:
1604         {
1605             SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1606             SfxItemSet aSet(GetPool(), svl::Items<SID_AUTO_CORRECT_DLG, SID_AUTO_CORRECT_DLG>{});
1607             const SfxPoolItem* pItem=nullptr;
1608             const SfxItemSet* pSet = rReq.GetArgs();
1609             SfxItemPool* pSetPool = pSet ? pSet->GetPool() : nullptr;
1610             if ( pSet && pSet->GetItemState( pSetPool->GetWhich( SID_AUTO_CORRECT_DLG ), false, &pItem ) == SfxItemState::SET )
1611                 aSet.Put( *pItem );
1612 
1613             ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateAutoCorrTabDialog(rReq.GetFrameWeld(), &aSet));
1614             pDlg->Execute();
1615 
1616             break;
1617         }
1618 
1619         case SID_NEWSD :
1620         {
1621             SvtModuleOptions aModuleOpt;
1622             if ( !aModuleOpt.IsImpress() )
1623             {
1624                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(rReq.GetFrameWeld(),
1625                                                                          VclMessageType::Warning, VclButtonsType::Ok,
1626                                                                          SfxResId(STR_MODULENOTINSTALLED)));
1627                 xBox->run();
1628                 return;
1629             }
1630 
1631             Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1632             Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext );
1633 
1634             OUString aCmd = OUString::createFromAscii( GetInterface()->GetSlot( rReq.GetSlot() )->GetUnoName() );
1635             Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
1636             Sequence < beans::PropertyValue > aSeq;
1637             if ( rReq.GetArgs() )
1638                 TransformItems( rReq.GetSlot(), *rReq.GetArgs(), aSeq );
1639             Any aResult = xHelper->executeDispatch( xProv, aCmd, OUString(), 0, aSeq );
1640             frame::DispatchResultEvent aEvent;
1641             bool bSuccess = (aResult >>= aEvent) &&
1642                                 (aEvent.State == frame::DispatchResultState::SUCCESS);
1643             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bSuccess ) );
1644         }
1645         break;
1646 
1647         case FN_LABEL :
1648         case FN_BUSINESS_CARD :
1649         case FN_XFORMS_INIT :
1650         {
1651             Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1652             Reference< frame::XDispatchProvider > xProv = text::ModuleDispatcher::create( xContext );
1653 
1654             OUString aCmd = OUString::createFromAscii( GetInterface()->GetSlot( rReq.GetSlot() )->GetUnoName() );
1655             Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) );
1656             Sequence < beans::PropertyValue > aSeq;
1657             if ( rReq.GetArgs() )
1658                 TransformItems( rReq.GetSlot(), *rReq.GetArgs(), aSeq );
1659             Any aResult = xHelper->executeDispatch( xProv, aCmd, OUString(), 0, aSeq );
1660             frame::DispatchResultEvent aEvent;
1661             bool bSuccess = (aResult >>= aEvent) &&
1662                                 (aEvent.State == frame::DispatchResultState::SUCCESS);
1663             rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bSuccess ) );
1664         }
1665         break;
1666 
1667         case SID_ADDRESS_DATA_SOURCE:
1668         {
1669             try
1670             {
1671                 Reference< uno::XComponentContext > xORB = ::comphelper::getProcessComponentContext();
1672                 Reference< ui::dialogs::XExecutableDialog > xDialog = ui::dialogs::AddressBookSourcePilot::createWithParent(xORB, nullptr);
1673                 xDialog->execute();
1674             }
1675             catch(const css::uno::Exception&)
1676             {
1677                 DBG_UNHANDLED_EXCEPTION("sfx.appl");
1678             }
1679         }
1680         break;
1681 
1682         case SID_COMP_BIBLIOGRAPHY:
1683             lcl_tryLoadBibliography();
1684         break;
1685     }
1686 }
1687 
OfaState_Impl(SfxItemSet & rSet)1688 void SfxApplication::OfaState_Impl(SfxItemSet &rSet)
1689 {
1690     SvtModuleOptions aModuleOpt;
1691 
1692     if( !aModuleOpt.IsWriter())
1693     {
1694         rSet.DisableItem( FN_LABEL );
1695         rSet.DisableItem( FN_BUSINESS_CARD );
1696         rSet.DisableItem( FN_XFORMS_INIT );
1697     }
1698     if ( comphelper::LibreOfficeKit::isActive() )
1699         rSet.DisableItem( SID_AUTO_CORRECT_DLG );
1700 
1701     bool bMacrosDisabled
1702         = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
1703     if (bMacrosDisabled)
1704     {
1705         rSet.DisableItem(SID_RUNMACRO);
1706         rSet.DisableItem(SID_MACROORGANIZER);
1707         rSet.DisableItem(SID_SCRIPTORGANIZER);
1708         rSet.DisableItem(SID_BASICIDE_APPEAR);
1709     }
1710 }
1711 
1712 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1713