xref: /core/cui/source/options/treeopt.cxx (revision 116b9d6d)
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 <memory>
21 #include <string_view>
22 
23 #include <config_features.h>
24 #include <config_feature_opencl.h>
25 #include <config_feature_desktop.h>
26 #include <config_gpgme.h>
27 
28 #include <officecfg/Office/Common.hxx>
29 #include <officecfg/Office/Writer.hxx>
30 
31 #include <svx/dialogs.hrc>
32 #include <svx/svxids.hrc>
33 
34 #include <treeopt.hrc>
35 #include <helpids.h>
36 
37 #include "cfgchart.hxx"
38 #include "connpoolconfig.hxx"
39 #include "connpooloptions.hxx"
40 #include <cuioptgenrl.hxx>
41 #include <dbregister.hxx>
42 #include "dbregisterednamesconfig.hxx"
43 #include <dialmgr.hxx>
44 #include "fontsubs.hxx"
45 #include "optaccessibility.hxx"
46 #include <optasian.hxx>
47 #include "optchart.hxx"
48 #include "optcolor.hxx"
49 #include "optctl.hxx"
50 #include "optfltr.hxx"
51 #include "optgdlg.hxx"
52 #include "opthtml.hxx"
53 #include "optinet2.hxx"
54 #include "optjava.hxx"
55 #include "optjsearch.hxx"
56 #include <optlingu.hxx>
57 #if HAVE_FEATURE_OPENCL
58 #include "optopencl.hxx"
59 #endif
60 #include <optpath.hxx>
61 #include "optsave.hxx"
62 #include "optupdt.hxx"
63 #include "personalization.hxx"
64 #include <treeopt.hxx>
65 #include "optbasic.hxx"
66 #include "optlanguagetool.hxx"
67 #include "optdeepl.hxx"
68 
69 #include <com/sun/star/awt/XContainerWindowEventHandler.hpp>
70 #include <com/sun/star/awt/ContainerWindowProvider.hpp>
71 #include <com/sun/star/awt/XControl.hpp>
72 #include <com/sun/star/awt/PosSize.hpp>
73 #include <com/sun/star/frame/Desktop.hpp>
74 #include <com/sun/star/frame/ModuleManager.hpp>
75 #include <com/sun/star/frame/UnknownModuleException.hpp>
76 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
77 #include <com/sun/star/linguistic2/LinguProperties.hpp>
78 #include <com/sun/star/setup/UpdateCheck.hpp>
79 #include <comphelper/getexpandeduri.hxx>
80 #include <comphelper/processfactory.hxx>
81 #include <editeng/langitem.hxx>
82 #include <editeng/optitems.hxx>
83 #include <editeng/unolingu.hxx>
84 #include <linguistic/misc.hxx>
85 #include <officecfg/Office/OptionsDialog.hxx>
86 #include <sfx2/app.hxx>
87 #include <sfx2/dispatch.hxx>
88 #include <sfx2/module.hxx>
89 #include <sfx2/printopt.hxx>
90 #include <sfx2/shell.hxx>
91 #include <sfx2/viewsh.hxx>
92 #include <sfx2/viewfrm.hxx>
93 #include <svl/flagitem.hxx>
94 #include <svl/intitem.hxx>
95 #include <svl/cjkoptions.hxx>
96 #include <svl/ctloptions.hxx>
97 #include <svx/databaseregistrationui.hxx>
98 #include <toolkit/helper/vclunohelper.hxx>
99 #include <tools/urlobj.hxx>
100 #include <comphelper/diagnose_ex.hxx>
101 #include <unotools/configmgr.hxx>
102 #include <unotools/moduleoptions.hxx>
103 #include <unotools/optionsdlg.hxx>
104 #include <unotools/viewoptions.hxx>
105 #include <utility>
106 #include <vcl/help.hxx>
107 #include <vcl/svapp.hxx>
108 #include <vcl/weldutils.hxx>
109 #include <vcl/window.hxx>
110 #include <sal/log.hxx>
111 
112 using namespace ::com::sun::star;
113 using namespace ::com::sun::star::beans;
114 using namespace ::com::sun::star::container;
115 using namespace ::com::sun::star::frame;
116 using namespace ::com::sun::star::lang;
117 using namespace ::com::sun::star::linguistic2;
118 using namespace ::com::sun::star::uno;
119 using namespace ::com::sun::star::util;
120 
121 LastPageSaver* OfaTreeOptionsDialog::pLastPageSaver = nullptr;
122 
123 // some stuff for easier changes for SvtViewOptions
124 constexpr OUStringLiteral VIEWOPT_DATANAME = u"page data";
125 
126 static void SetViewOptUserItem( SvtViewOptions& rOpt, const OUString& rData )
127 {
128     rOpt.SetUserItem( VIEWOPT_DATANAME, Any( rData ) );
129 }
130 
131 static OUString GetViewOptUserItem( const SvtViewOptions& rOpt )
132 {
133     Any aAny( rOpt.GetUserItem( VIEWOPT_DATANAME ) );
134     OUString aUserData;
135     aAny >>= aUserData;
136 
137     return aUserData;
138 }
139 
140 namespace {
141 
142 struct ModuleToGroupNameMap_Impl
143 {
144     std::u16string_view m_pModule;
145     OUString    m_sGroupName;
146     sal_uInt16  m_nNodeId;
147 };
148 }
149 
150 static ModuleToGroupNameMap_Impl ModuleMap[] =
151 {
152     { u"ProductName", OUString(), SID_GENERAL_OPTIONS },
153     { u"LanguageSettings", OUString(), SID_LANGUAGE_OPTIONS },
154     { u"Internet", OUString(), SID_INET_DLG },
155     { u"LoadSave", OUString(), SID_FILTER_DLG },
156     { u"Writer", OUString(), SID_SW_EDITOPTIONS },
157     { u"WriterWeb", OUString(), SID_SW_ONLINEOPTIONS },
158     { u"Math", OUString(), SID_SM_EDITOPTIONS },
159     { u"Calc", OUString(), SID_SC_EDITOPTIONS },
160     { u"Impress", OUString(), SID_SD_EDITOPTIONS },
161     { u"Draw", OUString(), SID_SD_GRAPHIC_OPTIONS },
162     { u"Charts", OUString(), SID_SCH_EDITOPTIONS },
163     { u"Base", OUString(), SID_SB_STARBASEOPTIONS },
164 };
165 
166 static void setGroupName( std::u16string_view rModule, const OUString& rGroupName )
167 {
168     for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap)
169     {
170         if ( rEntry.m_pModule == rModule )
171         {
172             rEntry.m_sGroupName = rGroupName;
173             break;
174         }
175     }
176 }
177 
178 static OUString getGroupName( std::u16string_view rModule, bool bForced )
179 {
180     OUString sGroupName;
181     for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap)
182     {
183         if ( rEntry.m_pModule == rModule )
184         {
185             sGroupName = rEntry.m_sGroupName;
186             break;
187         }
188     }
189 
190     if ( sGroupName.isEmpty() && bForced )
191     {
192         if ( rModule == u"Writer" )
193             sGroupName = CuiResId(SID_SW_EDITOPTIONS_RES[0].first);
194         else if ( rModule == u"WriterWeb" )
195             sGroupName = CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first);
196         else if ( rModule == u"Calc" )
197             sGroupName = CuiResId(SID_SC_EDITOPTIONS_RES[0].first);
198         else if ( rModule == u"Impress" )
199             sGroupName = CuiResId(SID_SD_EDITOPTIONS_RES[0].first);
200         else if ( rModule == u"Draw" )
201             sGroupName = CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first);
202         else if ( rModule == u"Math" )
203             sGroupName = CuiResId(SID_SM_EDITOPTIONS_RES[0].first);
204         else if ( rModule == u"Base" )
205             sGroupName = CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first);
206     }
207     return sGroupName;
208 }
209 
210 static void deleteGroupNames()
211 {
212     for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap)
213         rEntry.m_sGroupName.clear();
214 }
215 
216 static sal_uInt16 getGroupNodeId( std::u16string_view rModule )
217 {
218     sal_uInt16 nNodeId = 0xFFFF;
219     for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap)
220     {
221         if ( rEntry.m_pModule == rModule )
222         {
223             nNodeId = rEntry.m_nNodeId;
224             break;
225         }
226     }
227 
228     return nNodeId;
229 }
230 
231 namespace {
232 
233 bool MailMergeCfgIsEmailSupported()
234 {
235     std::optional<bool> b = officecfg::Office::Writer::MailMergeWizard::EMailSupported::get();
236     return b && *b;
237 }
238 
239 }
240 
241 //typedef SfxTabPage* (*FNCreateTabPage)(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet);
242 static std::unique_ptr<SfxTabPage> CreateGeneralTabPage(sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
243 {
244     CreateTabPage fnCreate = nullptr;
245     switch(nId)
246     {
247         case RID_SFXPAGE_SAVE:                      fnCreate = &SvxSaveTabPage::Create; break;
248         case RID_SFXPAGE_PATH:                      fnCreate = &SvxPathTabPage::Create; break;
249         case RID_SFXPAGE_GENERAL:                   fnCreate = &SvxGeneralTabPage::Create; break;
250         case RID_SFXPAGE_PRINTOPTIONS:              fnCreate = &SfxCommonPrintOptionsTabPage::Create; break;
251         case OFA_TP_LANGUAGES:                      fnCreate = &OfaLanguagesTabPage::Create; break;
252         case RID_SFXPAGE_LINGU:                     fnCreate = &SvxLinguTabPage::Create; break;
253         case OFA_TP_VIEW:                           fnCreate = &OfaViewTabPage::Create; break;
254         case OFA_TP_MISC:                           fnCreate = &OfaMiscTabPage::Create; break;
255         case RID_SVXPAGE_ASIAN_LAYOUT:              fnCreate = &SvxAsianLayoutPage::Create; break;
256         case RID_SVX_FONT_SUBSTITUTION:             fnCreate = &SvxFontSubstTabPage::Create; break;
257         case RID_SVXPAGE_INET_PROXY:                fnCreate = &SvxProxyTabPage::Create; break;
258         case RID_SVXPAGE_INET_SECURITY:             fnCreate = &SvxSecurityTabPage::Create; break;
259         case RID_SVXPAGE_INET_MAIL:                 fnCreate = &SvxEMailTabPage::Create; break;
260 #if HAVE_FEATURE_DESKTOP
261         case RID_SVXPAGE_PERSONALIZATION:           fnCreate = &SvxPersonalizationTabPage::Create; break;
262 #endif
263         case RID_SVXPAGE_COLORCONFIG:               fnCreate = &SvxColorOptionsTabPage::Create; break;
264         case RID_OFAPAGE_HTMLOPT:                   fnCreate = &OfaHtmlTabPage::Create; break;
265         case SID_OPTFILTER_MSOFFICE:                fnCreate = &OfaMSFilterTabPage::Create; break;
266         case RID_OFAPAGE_MSFILTEROPT2:              fnCreate = &OfaMSFilterTabPage2::Create; break;
267         case RID_SVXPAGE_JSEARCH_OPTIONS:           fnCreate = &SvxJSearchOptionsPage::Create ; break;
268         case SID_SB_CONNECTIONPOOLING:              fnCreate = &::offapp::ConnectionPoolOptionsPage::Create; break;
269         case SID_SB_DBREGISTEROPTIONS:              fnCreate = &svx::DbRegistrationOptionsPage::Create; break;
270         case RID_SVXPAGE_ACCESSIBILITYCONFIG:       fnCreate = &SvxAccessibilityOptionsTabPage::Create; break;
271         case RID_SVXPAGE_OPTIONS_CTL:               fnCreate = &SvxCTLOptionsPage::Create ; break;
272         case RID_SVXPAGE_LANGTOOL_OPTIONS:          fnCreate = &OptLanguageToolTabPage::Create ; break;
273         case RID_SVXPAGE_DEEPL_OPTIONS:             fnCreate = &OptDeeplTabPage::Create ; break;
274         case RID_SVXPAGE_OPTIONS_JAVA:              fnCreate = &SvxJavaOptionsPage::Create ; break;
275 #if HAVE_FEATURE_OPENCL
276         case RID_SVXPAGE_OPENCL:                    fnCreate = &SvxOpenCLTabPage::Create ; break;
277 #endif
278         case RID_SVXPAGE_ONLINEUPDATE:              fnCreate = &SvxOnlineUpdateTabPage::Create; break;
279         case RID_OPTPAGE_CHART_DEFCOLORS:           fnCreate = &SvxDefaultColorOptPage::Create; break;
280 #if HAVE_FEATURE_SCRIPTING
281         case RID_SVXPAGE_BASICIDE_OPTIONS:          fnCreate = &SvxBasicIDEOptionsPage::Create; break;
282 #endif
283     }
284 
285     return fnCreate ? (*fnCreate)( pPage, pController, &rSet ) : nullptr;
286 }
287 
288 namespace {
289 
290 struct OptionsMapping_Impl
291 {
292     const char* m_pGroupName;
293     const char* m_pPageName;
294     sal_uInt16      m_nPageId;
295 };
296 
297 }
298 
299 OptionsMapping_Impl const OptionsMap_Impl[] =
300 {
301 //    GROUP                 PAGE                    PAGE-ID
302     { "ProductName",        nullptr,                SID_GENERAL_OPTIONS },
303     { "ProductName",        "UserData",             RID_SFXPAGE_GENERAL },
304     { "ProductName",        "General",              OFA_TP_MISC },
305     { "ProductName",        "View",                 OFA_TP_VIEW },
306     { "ProductName",        "Print",                RID_SFXPAGE_PRINTOPTIONS },
307     { "ProductName",        "Paths",                RID_SFXPAGE_PATH },
308     { "ProductName",        "Fonts",                RID_SVX_FONT_SUBSTITUTION },
309     { "ProductName",        "Security",             RID_SVXPAGE_INET_SECURITY },
310     { "ProductName",        "Personalization",      RID_SVXPAGE_PERSONALIZATION },
311     { "ProductName",        "Appearance",           RID_SVXPAGE_COLORCONFIG },
312     { "ProductName",        "Accessibility",        RID_SVXPAGE_ACCESSIBILITYCONFIG },
313     { "ProductName",        "Java",                 RID_SVXPAGE_OPTIONS_JAVA },
314     { "ProductName",        "BasicIDEOptions",      RID_SVXPAGE_BASICIDE_OPTIONS },
315     { "ProductName",        "OnlineUpdate",         RID_SVXPAGE_ONLINEUPDATE },
316     { "LanguageSettings",   nullptr,                SID_LANGUAGE_OPTIONS },
317     { "LanguageSettings",   "Languages",            OFA_TP_LANGUAGES  },
318     { "LanguageSettings",   "WritingAids",          RID_SFXPAGE_LINGU },
319     { "LanguageSettings",   "SearchingInJapanese",  RID_SVXPAGE_JSEARCH_OPTIONS },
320     { "LanguageSettings",   "AsianLayout",          RID_SVXPAGE_ASIAN_LAYOUT },
321     { "LanguageSettings",   "ComplexTextLayout",    RID_SVXPAGE_OPTIONS_CTL },
322     { "Internet",           nullptr,                SID_INET_DLG },
323     { "Internet",           "Proxy",                RID_SVXPAGE_INET_PROXY },
324     { "Internet",           "Email",                RID_SVXPAGE_INET_MAIL },
325     { "LoadSave",           nullptr,                SID_FILTER_DLG },
326     { "LoadSave",           "General",              RID_SFXPAGE_SAVE },
327     { "LoadSave",           "VBAProperties",        SID_OPTFILTER_MSOFFICE },
328     { "LoadSave",           "MicrosoftOffice",      RID_OFAPAGE_MSFILTEROPT2 },
329     { "LoadSave",           "HTMLCompatibility",    RID_OFAPAGE_HTMLOPT },
330     { "Writer",             nullptr,                SID_SW_EDITOPTIONS },
331     { "Writer",             "General",              RID_SW_TP_OPTLOAD_PAGE },
332     { "Writer",             "View",                 RID_SW_TP_CONTENT_OPT },
333     { "Writer",             "FormattingAids",       RID_SW_TP_OPTSHDWCRSR },
334     { "Writer",             "Grid",                 RID_SVXPAGE_GRID },
335     { "Writer",             "BasicFontsWestern",    RID_SW_TP_STD_FONT },
336     { "Writer",             "BasicFontsAsian",      RID_SW_TP_STD_FONT_CJK },
337     { "Writer",             "BasicFontsCTL",        RID_SW_TP_STD_FONT_CTL },
338     { "Writer",             "Print",                RID_SW_TP_OPTPRINT_PAGE },
339     { "Writer",             "Table",                RID_SW_TP_OPTTABLE_PAGE },
340     { "Writer",             "Changes",              RID_SW_TP_REDLINE_OPT },
341     { "Writer",             "Comparison",           RID_SW_TP_COMPARISON_OPT },
342     { "Writer",             "Compatibility",        RID_SW_TP_OPTCOMPATIBILITY_PAGE },
343     { "Writer",             "AutoCaption",          RID_SW_TP_OPTCAPTION_PAGE },
344     { "Writer",             "MailMerge",            RID_SW_TP_MAILCONFIG },
345     { "WriterWeb",          nullptr,                SID_SW_ONLINEOPTIONS },
346     { "WriterWeb",          "View",                 RID_SW_TP_HTML_CONTENT_OPT },
347     { "WriterWeb",          "FormattingAids",       RID_SW_TP_HTML_OPTSHDWCRSR },
348     { "WriterWeb",          "Grid",                 RID_SW_TP_HTML_OPTGRID_PAGE },
349     { "WriterWeb",          "Print",                RID_SW_TP_HTML_OPTPRINT_PAGE },
350     { "WriterWeb",          "Table",                RID_SW_TP_HTML_OPTTABLE_PAGE },
351     { "WriterWeb",          "Background",           RID_SW_TP_BACKGROUND },
352     { "Math",               nullptr,                SID_SM_EDITOPTIONS },
353     { "Math",               "Settings",             SID_SM_TP_PRINTOPTIONS },
354     { "Calc",               nullptr,                SID_SC_EDITOPTIONS },
355     { "Calc",               "General",              SID_SC_TP_LAYOUT },
356     { "Calc",               "View",                 SID_SC_TP_CONTENT },
357     { "Calc",               "Calculate",            SID_SC_TP_CALC },
358     { "Calc",               "Formula",              SID_SC_TP_FORMULA },
359     { "Calc",               "SortLists",            SID_SC_TP_USERLISTS },
360     { "Calc",               "Changes",              SID_SC_TP_CHANGES },
361     { "Calc",               "Compatibility",        SID_SC_TP_COMPATIBILITY },
362     { "Calc",               "Grid",                 SID_SC_TP_GRID },
363     { "Calc",               "Print",                RID_SC_TP_PRINT },
364     { "Impress",            nullptr,                SID_SD_EDITOPTIONS },
365     { "Impress",            "General",              SID_SI_TP_MISC },
366     { "Impress",            "View",                 SID_SI_TP_CONTENTS },
367     { "Impress",            "Grid",                 SID_SI_TP_SNAP },
368     { "Impress",            "Print",                SID_SI_TP_PRINT },
369     { "Draw",               nullptr,                SID_SD_GRAPHIC_OPTIONS },
370     { "Draw",               "General",              SID_SD_TP_MISC },
371     { "Draw",               "View",                 SID_SD_TP_CONTENTS },
372     { "Draw",               "Grid",                 SID_SD_TP_SNAP },
373     { "Draw",               "Print",                SID_SD_TP_PRINT },
374     { "Charts",             nullptr,                SID_SCH_EDITOPTIONS },
375     { "Charts",             "DefaultColors",        RID_OPTPAGE_CHART_DEFCOLORS },
376     { "Base",               nullptr,                SID_SB_STARBASEOPTIONS },
377     { "Base",               "Connections",          SID_SB_CONNECTIONPOOLING },
378     { "Base",               "Databases",            SID_SB_DBREGISTEROPTIONS },
379     { nullptr,                 nullptr,             0 }
380 };
381 
382 static bool lcl_getStringFromID( sal_uInt16 _nPageId, OUString& _rGroupName, OUString& _rPageName )
383 {
384     bool bRet = false;
385 
386     sal_uInt16 nIdx = 0;
387     while ( OptionsMap_Impl[nIdx].m_pGroupName != nullptr )
388     {
389         if ( _nPageId == OptionsMap_Impl[nIdx].m_nPageId )
390         {
391             bRet = true;
392             _rGroupName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pGroupName );
393             if ( OptionsMap_Impl[nIdx].m_pPageName != nullptr )
394                 _rPageName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pPageName );
395             break;
396         }
397         ++nIdx;
398     }
399 
400     return bRet;
401 }
402 
403 static bool lcl_isOptionHidden( sal_uInt16 _nPageId, const SvtOptionsDialogOptions& _rOptOptions )
404 {
405     bool bIsHidden = false;
406     OUString sGroupName, sPageName;
407     if ( lcl_getStringFromID( _nPageId, sGroupName, sPageName ) )
408     {
409         if ( sPageName.isEmpty() )
410             bIsHidden =  _rOptOptions.IsGroupHidden( sGroupName );
411         else
412             bIsHidden =  _rOptOptions.IsPageHidden( sPageName, sGroupName );
413     }
414     return bIsHidden;
415 }
416 
417 struct OptionsPageInfo
418 {
419     std::unique_ptr<SfxTabPage> m_xPage;
420     sal_uInt16          m_nPageId;
421     OUString       m_sPageURL;
422     OUString       m_sEventHdl;
423     std::unique_ptr<ExtensionsTabPage>  m_xExtPage;
424 
425     explicit OptionsPageInfo( sal_uInt16 nId ) : m_nPageId( nId ) {}
426 };
427 
428 struct OptionsGroupInfo
429 {
430     std::optional<SfxItemSet> m_pInItemSet;
431     std::unique_ptr<SfxItemSet> m_pOutItemSet;
432     SfxShell*           m_pShell;       // used to create the page
433     SfxModule*          m_pModule;      // used to create the ItemSet
434     sal_uInt16          m_nDialogId;    // Id of the former dialog
435 
436     OptionsGroupInfo( SfxShell* pSh, SfxModule* pMod, sal_uInt16 nId ) :
437         m_pShell( pSh ),
438         m_pModule( pMod ), m_nDialogId( nId ) {}
439 };
440 
441 // Basic ctor with common initialization
442 OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, bool fromExtensionManager)
443     : SfxOkDialogController(pParent, "cui/ui/optionsdialog.ui", "OptionsDialog")
444     , xOkPB(m_xBuilder->weld_button("ok"))
445     , xApplyPB(m_xBuilder->weld_button("apply"))
446     , xBackPB(m_xBuilder->weld_button("revert"))
447     , xTreeLB(m_xBuilder->weld_tree_view("pages"))
448     , xTabBox(m_xBuilder->weld_container("box"))
449     , m_pParent(pParent)
450     , sTitle(m_xDialog->get_title())
451     , bForgetSelection(false)
452     , bIsFromExtensionManager(fromExtensionManager)
453     , bIsForSetDocumentLanguage(false)
454     , bNeedsRestart(false)
455     , eRestartReason(svtools::RESTART_REASON_NONE)
456 {
457     Size aSize(xTreeLB->get_approximate_digit_width() * 82, xTreeLB->get_height_rows(30));
458 #if HAVE_FEATURE_GPGME
459     // tdf#115015: make enough space for crypto settings (approx. 14 text edits + padding)
460     aSize.setHeight((weld::GetMinimumEditHeight() + 6) * 14);
461 #endif
462     xTabBox->set_size_request(aSize.Width(), aSize.Height());
463     xTreeLB->set_size_request(xTreeLB->get_approximate_digit_width() * 35, aSize.Height());
464 
465     // Init tree and handler
466     xTreeLB->set_help_id(HID_OFADLG_TREELISTBOX);
467     xTreeLB->connect_changed(LINK(this, OfaTreeOptionsDialog, ShowPageHdl_Impl));
468     xBackPB->connect_clicked(LINK(this, OfaTreeOptionsDialog, BackHdl_Impl));
469     xApplyPB->connect_clicked(LINK(this, OfaTreeOptionsDialog, ApplyHdl_Impl));
470     xOkPB->connect_clicked(LINK(this, OfaTreeOptionsDialog, ApplyHdl_Impl));
471     m_xDialog->connect_help(LINK(this, OfaTreeOptionsDialog, HelpHdl_Impl));
472 
473     xTreeLB->set_accessible_name(sTitle);
474 }
475 
476 // Ctor() with Frame -----------------------------------------------------
477 OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, const Reference< XFrame >& _xFrame, bool bActivateLastSelection)
478     : OfaTreeOptionsDialog(pParent, false)
479 {
480     Initialize( _xFrame );
481     LoadExtensionOptions( u"" );
482     if (bActivateLastSelection)
483         ActivateLastSelection();
484 }
485 
486 // Ctor() with ExtensionId -----------------------------------------------
487 OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, std::u16string_view rExtensionId)
488     : OfaTreeOptionsDialog(pParent, !rExtensionId.empty())
489 {
490     LoadExtensionOptions( rExtensionId );
491     ActivateLastSelection();
492 }
493 
494 OfaTreeOptionsDialog::~OfaTreeOptionsDialog()
495 {
496     xCurrentPageEntry.reset();
497 
498     std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator();
499     bool bEntry = xTreeLB->get_iter_first(*xEntry);
500     // first children
501     while (bEntry)
502     {
503         // if Child (has parent), then OptionsPageInfo
504         if (xTreeLB->get_iter_depth(*xEntry))
505         {
506             OptionsPageInfo *pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry));
507             if(pPageInfo->m_xPage)
508             {
509                 pPageInfo->m_xPage->FillUserData();
510                 OUString aPageData(pPageInfo->m_xPage->GetUserData());
511                 if ( !aPageData.isEmpty() )
512                 {
513                     SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) );
514                     SetViewOptUserItem( aTabPageOpt, aPageData );
515                 }
516                 pPageInfo->m_xPage.reset();
517             }
518 
519             if (pPageInfo->m_nPageId == RID_SFXPAGE_LINGU)
520             {
521                 // write personal dictionaries
522                 Reference< XSearchableDictionaryList >  xDicList( LinguMgr::GetDictionaryList() );
523                 if (xDicList.is())
524                 {
525                     linguistic::SaveDictionaries( xDicList );
526                 }
527             }
528 
529             pPageInfo->m_xExtPage.reset();
530 
531             delete pPageInfo;
532         }
533         bEntry = xTreeLB->iter_next(*xEntry);
534     }
535 
536     // and parents
537     bEntry = xTreeLB->get_iter_first(*xEntry);
538     while (bEntry)
539     {
540         if (!xTreeLB->get_iter_depth(*xEntry))
541         {
542             OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xEntry));
543             delete pGroupInfo;
544         }
545         bEntry = xTreeLB->iter_next(*xEntry);
546     }
547     deleteGroupNames();
548 }
549 
550 OptionsPageInfo* OfaTreeOptionsDialog::AddTabPage(
551     sal_uInt16 nId, const OUString& rPageName, sal_uInt16 nGroup )
552 {
553     std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator();
554     if (!xTreeLB->get_iter_first(*xParent))
555         return nullptr;
556     xTreeLB->iter_nth_sibling(*xParent, nGroup);
557 
558     OptionsPageInfo* pPageInfo = new OptionsPageInfo( nId );
559     OUString sId(weld::toId(pPageInfo));
560     xTreeLB->insert(xParent.get(), -1, &rPageName, &sId, nullptr, nullptr, false, nullptr);
561     return pPageInfo;
562 }
563 
564 // the ItemSet* is passed on to the dialog's ownership
565 sal_uInt16  OfaTreeOptionsDialog::AddGroup(const OUString& rGroupName,
566                                         SfxShell* pCreateShell,
567                                         SfxModule* pCreateModule,
568                                         sal_uInt16 nDialogId )
569 {
570     OptionsGroupInfo* pInfo =
571         new OptionsGroupInfo( pCreateShell, pCreateModule, nDialogId );
572     OUString sId(weld::toId(pInfo));
573     xTreeLB->append(sId, rGroupName);
574 
575     sal_uInt16 nRet = 0;
576     std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator();
577     bool bEntry = xTreeLB->get_iter_first(*xEntry);
578     while (bEntry)
579     {
580         if (!xTreeLB->get_iter_depth(*xEntry))
581             nRet++;
582         bEntry = xTreeLB->iter_next(*xEntry);
583     }
584     return nRet - 1;
585 }
586 
587 IMPL_LINK_NOARG(OfaTreeOptionsDialog, ShowPageHdl_Impl, weld::TreeView&, void)
588 {
589     SelectHdl_Impl();
590 }
591 
592 void OfaTreeOptionsDialog::ResetCurrentPageFromConfig()
593 {
594     if (!(xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)))
595         return;
596 
597     OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry));
598     if (pPageInfo->m_xPage)
599     {
600         std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xCurrentPageEntry.get());
601         xTreeLB->iter_parent(*xParent);
602         OptionsGroupInfo* pGroupInfo =
603             weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent));
604         pPageInfo->m_xPage->Reset( &*pGroupInfo->m_pInItemSet );
605     }
606     else if ( pPageInfo->m_xExtPage )
607         pPageInfo->m_xExtPage->ResetPage();
608 }
609 
610 IMPL_LINK_NOARG(OfaTreeOptionsDialog, BackHdl_Impl, weld::Button&, void)
611 {
612     ResetCurrentPageFromConfig();
613 }
614 
615 void OfaTreeOptionsDialog::ApplyOptions()
616 {
617     std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator();
618     bool bEntry = xTreeLB->get_iter_first(*xEntry);
619     while (bEntry)
620     {
621         if (xTreeLB->get_iter_depth(*xEntry))
622         {
623             OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry));
624             if ( pPageInfo->m_xPage && !pPageInfo->m_xPage->HasExchangeSupport() )
625             {
626                 std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xEntry.get());
627                 xTreeLB->iter_parent(*xParent);
628                 OptionsGroupInfo* pGroupInfo =
629                     weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent));
630                 pPageInfo->m_xPage->FillItemSet(pGroupInfo->m_pOutItemSet.get());
631             }
632 
633             if ( pPageInfo->m_xExtPage )
634             {
635                 pPageInfo->m_xExtPage->DeactivatePage();
636                 pPageInfo->m_xExtPage->SavePage();
637             }
638             if ( pPageInfo->m_xPage && RID_OPTPAGE_CHART_DEFCOLORS == pPageInfo->m_nPageId )
639             {
640                 SvxDefaultColorOptPage* pPage = static_cast<SvxDefaultColorOptPage *>(pPageInfo->m_xPage.get());
641                 pPage->SaveChartOptions();
642             }
643         }
644         bEntry = xTreeLB->iter_next(*xEntry);
645     }
646 }
647 
648 IMPL_LINK_NOARG(OfaTreeOptionsDialog, HelpHdl_Impl, weld::Widget&, bool)
649 {
650     Help* pHelp = Application::GetHelp();
651     if (pHelp && xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry))
652     {
653         OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry));
654         if (pPageInfo->m_xPage)
655         {
656             OUString sHelpId(pPageInfo->m_xPage->GetHelpId());
657             pHelp->Start(sHelpId, m_xDialog.get());
658             return false;
659         }
660     }
661     return true;
662 }
663 
664 IMPL_LINK(OfaTreeOptionsDialog, ApplyHdl_Impl, weld::Button&, rButton, void)
665 {
666     bool bOkPressed = &rButton == xOkPB.get();
667 
668     OptionsGroupInfo* pGroupInfo = nullptr;
669 
670     if (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry))
671     {
672         OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry));
673         if ( pPageInfo->m_xPage )
674         {
675             std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xCurrentPageEntry.get());
676             xTreeLB->iter_parent(*xParent);
677 
678             pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent));
679             if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId
680                 && pPageInfo->m_xPage->HasExchangeSupport() )
681             {
682                 DeactivateRC nLeave = pPageInfo->m_xPage->DeactivatePage(pGroupInfo->m_pOutItemSet.get());
683                 if ( nLeave == DeactivateRC::KeepPage )
684                 {
685                     // the page mustn't be left, so return early
686                     assert(xTreeLB->is_selected(*xCurrentPageEntry)); // presumably this must be true here
687                     if (bOkPressed)
688                         return;
689                 }
690             }
691         }
692     }
693 
694     ApplyOptions();
695     ApplyItemSets();
696     utl::ConfigManager::storeConfigItems();
697 
698     if (bOkPressed)
699         m_xDialog->response(RET_OK);
700     else
701     {
702         // tdf#137930 rebuild the in and out itemsets to reflect the current
703         // post-apply state
704         if (pGroupInfo && pGroupInfo->m_pInItemSet)
705         {
706             // tdf#138596 seeing as the SfxTabPages keep pointers to the m_pInItemSet
707             // we update the contents of the existing SfxItemSets to match
708             // the current settings, rather than create new ones
709             auto xInItemSet = pGroupInfo->m_pShell
710                 ? pGroupInfo->m_pShell->CreateItemSet( pGroupInfo->m_nDialogId )
711                 : CreateItemSet( pGroupInfo->m_nDialogId );
712             pGroupInfo->m_pInItemSet->Set(*xInItemSet, false);
713             pGroupInfo->m_pOutItemSet->ClearItem();
714         }
715 
716         // for the Apply case, now that the settings are saved to config,
717         // reload the current page so it knows what the config now states
718         ResetCurrentPageFromConfig();
719         // reselect it to undo possible DeactivatePage above
720         xCurrentPageEntry.reset();
721         SelectHdl_Impl();
722     }
723 
724     if (!bNeedsRestart)
725         return;
726 
727     SolarMutexGuard aGuard;
728     weld::Window* pParent;
729     if (!bOkPressed)
730         pParent = m_xDialog.get();
731     else
732     {
733         m_xDialog->hide();
734         pParent = m_pParent;
735     }
736     bool bRestart = ::svtools::executeRestartDialog(comphelper::getProcessComponentContext(),
737                                                     pParent, eRestartReason);
738     if (bRestart && !bOkPressed)
739         m_xDialog->response(RET_OK);
740 }
741 
742 void OfaTreeOptionsDialog::ApplyItemSets()
743 {
744     std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator();
745     bool bEntry = xTreeLB->get_iter_first(*xEntry);
746     while (bEntry)
747     {
748         if (!xTreeLB->get_iter_depth(*xEntry))
749         {
750             OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xEntry));
751             if(pGroupInfo->m_pOutItemSet)
752             {
753                 if(pGroupInfo->m_pShell)
754                     pGroupInfo->m_pShell->ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet);
755                 else
756                     ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet);
757             }
758         }
759         bEntry = xTreeLB->iter_next(*xEntry);
760     }
761 }
762 
763 void OfaTreeOptionsDialog::ActivatePage( sal_uInt16 nResId )
764 {
765     bIsForSetDocumentLanguage = false;
766     if ( nResId == OFA_TP_LANGUAGES_FOR_SET_DOCUMENT_LANGUAGE )
767     {
768         bIsForSetDocumentLanguage = true;
769         nResId = OFA_TP_LANGUAGES;
770     }
771 
772     DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" );
773     if ( !pLastPageSaver )
774         pLastPageSaver = new LastPageSaver;
775     bForgetSelection = true;
776     sal_uInt16 nTemp = pLastPageSaver->m_nLastPageId;
777     pLastPageSaver->m_nLastPageId = nResId;
778     ActivateLastSelection();
779     pLastPageSaver->m_nLastPageId = nTemp;
780 }
781 
782 void OfaTreeOptionsDialog::ActivatePage( const OUString& rPageURL )
783 {
784     DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" );
785     if ( !pLastPageSaver )
786         pLastPageSaver = new LastPageSaver;
787     bForgetSelection = true;
788     pLastPageSaver->m_nLastPageId = 0;
789     pLastPageSaver->m_sLastPageURL_Tools = rPageURL;
790     ActivateLastSelection();
791 }
792 
793 void OfaTreeOptionsDialog::ActivateLastSelection()
794 {
795     std::unique_ptr<weld::TreeIter> xEntry;
796 
797     if (pLastPageSaver)
798     {
799         OUString sLastURL = bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr
800                                                   : pLastPageSaver->m_sLastPageURL_Tools;
801         if ( sLastURL.isEmpty() )
802         {
803             sLastURL = !bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr
804                                                 : pLastPageSaver->m_sLastPageURL_Tools;
805         }
806 
807         bool bMustExpand = ( INetURLObject( sLastURL ).GetProtocol() == INetProtocol::File );
808 
809         std::unique_ptr<weld::TreeIter> xTemp = xTreeLB->make_iterator();
810         bool bTemp = xTreeLB->get_iter_first(*xTemp);
811         while (bTemp)
812         {
813             // restore only selection of a leaf
814             if (xTreeLB->get_iter_depth(*xTemp) && xTreeLB->get_id(*xTemp).toInt64())
815             {
816                 OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xTemp));
817                 OUString sPageURL = pPageInfo->m_sPageURL;
818                 if ( bMustExpand )
819                 {
820                     sPageURL = comphelper::getExpandedUri(
821                         comphelper::getProcessComponentContext(), sPageURL);
822                 }
823 
824                 if ( ( !bIsFromExtensionManager
825                         && pPageInfo->m_nPageId && pPageInfo->m_nPageId == pLastPageSaver->m_nLastPageId )
826                             || ( !pPageInfo->m_nPageId && sLastURL == sPageURL ) )
827                 {
828                     xEntry = xTreeLB->make_iterator(xTemp.get());
829                     break;
830                 }
831             }
832             bTemp = xTreeLB->iter_next(*xTemp);
833         }
834     }
835 
836     if (!xEntry)
837     {
838         xEntry = xTreeLB->make_iterator();
839         if (!xTreeLB->get_iter_first(*xEntry) || !xTreeLB->iter_next(*xEntry))
840             xEntry.reset();
841     }
842 
843     if (!xEntry)
844         return;
845 
846     std::unique_ptr<weld::TreeIter> xParent(xTreeLB->make_iterator(xEntry.get()));
847     xTreeLB->iter_parent(*xParent);
848     xTreeLB->expand_row(*xParent);
849     xTreeLB->scroll_to_row(*xParent);
850     xTreeLB->scroll_to_row(*xEntry);
851     xTreeLB->set_cursor(*xEntry);
852     xTreeLB->select(*xEntry);
853     xTreeLB->grab_focus();
854     SelectHdl_Impl();
855 }
856 
857 void OfaTreeOptionsDialog::InitItemSets(OptionsGroupInfo& rGroupInfo)
858 {
859     if (!rGroupInfo.m_pInItemSet)
860         rGroupInfo.m_pInItemSet.emplace( rGroupInfo.m_pShell
861             ? *rGroupInfo.m_pShell->CreateItemSet( rGroupInfo.m_nDialogId )
862             : *CreateItemSet( rGroupInfo.m_nDialogId ) );
863     if (!rGroupInfo.m_pOutItemSet)
864         rGroupInfo.m_pOutItemSet = std::make_unique<SfxItemSet>(
865             *rGroupInfo.m_pInItemSet->GetPool(),
866             rGroupInfo.m_pInItemSet->GetRanges());
867 }
868 
869 void OfaTreeOptionsDialog::SelectHdl_Impl()
870 {
871     std::unique_ptr<weld::TreeIter> xEntry(xTreeLB->make_iterator());
872 
873     if (!xTreeLB->get_cursor(xEntry.get()))
874         return;
875 
876     if (xCurrentPageEntry && xCurrentPageEntry->equal(*xEntry))
877         return;
878 
879     std::unique_ptr<weld::TreeIter> xParent(xTreeLB->make_iterator(xEntry.get()));
880     bool bParent = xTreeLB->iter_parent(*xParent);
881 
882     // If the user has selected a category, automatically switch to a suitable
883     // default sub-page instead.
884     if (!bParent)
885         return;
886 
887     BuilderPage* pNewPage = nullptr;
888     OptionsPageInfo* pOptPageInfo = (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry))
889         ? weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry)) : nullptr;
890 
891     if (pOptPageInfo && pOptPageInfo->m_xPage && pOptPageInfo->m_xPage->IsVisible())
892     {
893         std::unique_ptr<weld::TreeIter> xCurParent(xTreeLB->make_iterator(xCurrentPageEntry.get()));
894         xTreeLB->iter_parent(*xCurParent);
895 
896         OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xCurParent));
897         DeactivateRC nLeave = DeactivateRC::LeavePage;
898         if ( RID_SVXPAGE_COLOR != pOptPageInfo->m_nPageId && pOptPageInfo->m_xPage->HasExchangeSupport() )
899            nLeave = pOptPageInfo->m_xPage->DeactivatePage( pGroupInfo->m_pOutItemSet.get() );
900 
901         if ( nLeave == DeactivateRC::KeepPage )
902         {
903             // we cannot leave this page, this is may be from a user clicking a different entry
904             // in the tree so reselect the current page
905             xTreeLB->select(*xCurrentPageEntry);
906             return;
907         }
908         else
909             pOptPageInfo->m_xPage->set_visible(false);
910     }
911     else if ( pOptPageInfo && pOptPageInfo->m_xExtPage )
912     {
913         pOptPageInfo->m_xExtPage->Hide();
914         pOptPageInfo->m_xExtPage->DeactivatePage();
915     }
916 
917     OptionsPageInfo *pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry));
918     OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent));
919     if(!pPageInfo->m_xPage && pPageInfo->m_nPageId > 0)
920     {
921         InitItemSets(*pGroupInfo);
922 
923         pPageInfo->m_xPage = ::CreateGeneralTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet);
924 
925         if(!pPageInfo->m_xPage && pGroupInfo->m_pModule)
926             pPageInfo->m_xPage = pGroupInfo->m_pModule->CreateTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet);
927 
928         DBG_ASSERT( pPageInfo->m_xPage, "tabpage could not created");
929         if ( pPageInfo->m_xPage )
930         {
931             SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) );
932             pPageInfo->m_xPage->SetUserData( GetViewOptUserItem( aTabPageOpt ) );
933             pPageInfo->m_xPage->Reset( &*pGroupInfo->m_pInItemSet );
934         }
935     }
936     else if ( 0 == pPageInfo->m_nPageId && !pPageInfo->m_xExtPage )
937     {
938         if ( !m_xContainerWinProvider.is() )
939         {
940             m_xContainerWinProvider = awt::ContainerWindowProvider::create( ::comphelper::getProcessComponentContext() );
941         }
942 
943         pPageInfo->m_xExtPage = std::make_unique<ExtensionsTabPage>(
944             xTabBox.get(), pPageInfo->m_sPageURL, pPageInfo->m_sEventHdl, m_xContainerWinProvider);
945     }
946 
947     if ( pPageInfo->m_xPage )
948     {
949         if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId &&
950              pPageInfo->m_xPage->HasExchangeSupport())
951         {
952             pPageInfo->m_xPage->ActivatePage(*pGroupInfo->m_pOutItemSet);
953         }
954         pPageInfo->m_xPage->set_visible(true);
955     }
956     else if ( pPageInfo->m_xExtPage )
957     {
958         pPageInfo->m_xExtPage->Show();
959         pPageInfo->m_xExtPage->ActivatePage();
960     }
961 
962     {
963         OUString sTitleText = sTitle
964                             + " - " + xTreeLB->get_text(*xParent)
965                             + " - " + xTreeLB->get_text(*xEntry);
966         m_xDialog->set_title(sTitleText);
967     }
968 
969     xCurrentPageEntry = std::move(xEntry);
970 
971     if ( !bForgetSelection )
972     {
973         if ( !pLastPageSaver )
974             pLastPageSaver = new LastPageSaver;
975         if ( !bIsFromExtensionManager )
976             pLastPageSaver->m_nLastPageId = pPageInfo->m_nPageId;
977         if ( pPageInfo->m_xExtPage )
978         {
979             if ( bIsFromExtensionManager )
980                 pLastPageSaver->m_sLastPageURL_ExtMgr = pPageInfo->m_sPageURL;
981             else
982                 pLastPageSaver->m_sLastPageURL_Tools = pPageInfo->m_sPageURL;
983         }
984     }
985     pNewPage = pPageInfo->m_xPage.get();
986 
987     // fdo#58170 use current page's layout child HelpId, unless there isn't a current page
988     OUString sHelpId(pNewPage ? pNewPage->GetHelpId() : OUString());
989     if (sHelpId.isEmpty())
990         sHelpId = HID_OFADLG_TREELISTBOX;
991     xTreeLB->set_help_id(sHelpId);
992 }
993 
994 std::optional<SfxItemSet> OfaTreeOptionsDialog::CreateItemSet( sal_uInt16 nId )
995 {
996     Reference< XLinguProperties >  xProp( LinguMgr::GetLinguPropertySet() );
997     std::optional<SfxItemSet> pRet;
998     switch(nId)
999     {
1000         case SID_GENERAL_OPTIONS:
1001         {
1002             pRet.emplace(
1003                 SfxGetpApp()->GetPool(),
1004                 svl::Items<
1005                     SID_HTML_MODE, SID_HTML_MODE,
1006                     SID_ATTR_METRIC, SID_ATTR_METRIC,
1007                     SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK,
1008                     SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER,
1009                     SID_ATTR_YEAR2000, SID_ATTR_YEAR2000> );
1010 
1011             SfxItemSetFixed<SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER> aOptSet( SfxGetpApp()->GetPool() );
1012             SfxApplication::GetOptions(aOptSet);
1013             pRet->Put(aOptSet);
1014 
1015             SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1016             if ( pViewFrame )
1017             {
1018                 const SfxUInt16Item* pItem = nullptr;
1019                 SfxDispatcher* pDispatch = pViewFrame->GetDispatcher();
1020 
1021                 // miscellaneous - Year2000
1022                 if( SfxItemState::DEFAULT <= pDispatch->QueryState( SID_ATTR_YEAR2000, pItem ) )
1023                     pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, pItem->GetValue() ) );
1024                 else
1025                     pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, officecfg::Office::Common::DateFormat::TwoDigitYear::get() ) );
1026             }
1027             else
1028                 pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, officecfg::Office::Common::DateFormat::TwoDigitYear::get() ) );
1029 
1030 
1031             // miscellaneous - Tabulator
1032             pRet->Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN, officecfg::Office::Common::Print::Warning::NotFound::get()));
1033 
1034             SfxPrinterChangeFlags nFlag = officecfg::Office::Common::Print::Warning::PaperSize::get() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE;
1035             nFlag  |= officecfg::Office::Common::Print::Warning::PaperOrientation::get() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE;
1036             pRet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlag) ));
1037 
1038         }
1039         break;
1040         case SID_LANGUAGE_OPTIONS :
1041         {
1042             pRet.emplace(
1043                 SfxGetpApp()->GetPool(),
1044                 svl::Items<
1045                     SID_ATTR_CHAR_CJK_LANGUAGE, SID_ATTR_CHAR_CJK_LANGUAGE,
1046                     SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_LANGUAGE,
1047                     SID_SET_DOCUMENT_LANGUAGE, SID_SET_DOCUMENT_LANGUAGE,
1048                     SID_ATTR_LANGUAGE, SID_ATTR_LANGUAGE,
1049                     SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK,
1050                     SID_OPT_LOCALE_CHANGED, SID_OPT_LOCALE_CHANGED>);
1051 
1052             // for linguistic
1053             SfxHyphenRegionItem aHyphen( SID_ATTR_HYPHENREGION );
1054 
1055             sal_Int16   nMinLead  = 2,
1056                         nMinTrail = 2;
1057             if (xProp.is())
1058             {
1059                 nMinLead = xProp->getHyphMinLeading();
1060                 nMinTrail = xProp->getHyphMinTrailing();
1061             }
1062             aHyphen.GetMinLead()  = static_cast<sal_uInt8>(nMinLead);
1063             aHyphen.GetMinTrail() = static_cast<sal_uInt8>(nMinTrail);
1064 
1065             SfxViewFrame* pViewFrame = SfxViewFrame::Current();
1066             if ( pViewFrame )
1067             {
1068                 const SvxLanguageItem* pLangItem = nullptr;
1069                 SfxDispatcher* pDispatch = pViewFrame->GetDispatcher();
1070                 if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_LANGUAGE, pLangItem))
1071                     pRet->Put(*pLangItem, SID_ATTR_LANGUAGE);
1072                 if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CJK_LANGUAGE, pLangItem))
1073                     pRet->Put(*pLangItem, SID_ATTR_CHAR_CJK_LANGUAGE);
1074                 if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CTL_LANGUAGE, pLangItem))
1075                     pRet->Put(*pLangItem, SID_ATTR_CHAR_CTL_LANGUAGE);
1076 
1077                 pRet->Put(aHyphen);
1078                 const SfxPoolItem* pItem = nullptr;
1079                 if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_AUTOSPELL_CHECK, pItem))
1080                 {
1081                     pRet->Put(std::unique_ptr<SfxPoolItem>(pItem->Clone()));
1082                 }
1083                 else
1084                 {
1085                         bool bVal = false;
1086                         if (xProp.is())
1087                         {
1088                             bVal = xProp->getIsSpellAuto();
1089                         }
1090 
1091                         pRet->Put(SfxBoolItem(SID_AUTOSPELL_CHECK, bVal));
1092                 }
1093             }
1094             pRet->Put( SfxBoolItem( SID_SET_DOCUMENT_LANGUAGE, bIsForSetDocumentLanguage ) );
1095         }
1096         break;
1097         case SID_INET_DLG :
1098                 pRet.emplace( SfxGetpApp()->GetPool(),
1099                                 svl::Items<
1100                 //SID_OPTIONS_START - ..END
1101                                 SID_SAVEREL_INET, SID_SAVEREL_FSYS,
1102                                 SID_INET_NOPROXY, SID_INET_FTP_PROXY_PORT,
1103                                 SID_SECURE_URL, SID_SECURE_URL> );
1104                 SfxApplication::GetOptions(*pRet);
1105         break;
1106         case SID_FILTER_DLG:
1107             pRet.emplace(
1108                 SfxGetpApp()->GetPool(),
1109                 svl::Items<
1110                     SID_ATTR_WARNALIENFORMAT, SID_ATTR_WARNALIENFORMAT,
1111                     SID_ATTR_DOCINFO, SID_ATTR_AUTOSAVEMINUTE,
1112                     SID_SAVEREL_INET, SID_SAVEREL_FSYS,
1113                     SID_ATTR_PRETTYPRINTING, SID_ATTR_PRETTYPRINTING> );
1114             SfxApplication::GetOptions(*pRet);
1115             break;
1116 
1117         case SID_SB_STARBASEOPTIONS:
1118             pRet.emplace( SfxGetpApp()->GetPool(),
1119                     svl::Items<SID_SB_POOLING_ENABLED, SID_SB_DB_REGISTER> );
1120             ::offapp::ConnectionPoolConfig::GetOptions(*pRet);
1121             svx::DbRegisteredNamesConfig::GetOptions(*pRet);
1122             break;
1123 
1124         case SID_SCH_EDITOPTIONS:
1125         {
1126             pRet.emplace( SfxGetpApp()->GetPool(), svl::Items<SID_SCH_EDITOPTIONS, SID_SCH_EDITOPTIONS> );
1127             pRet->Put( SvxChartColorTableItem( SID_SCH_EDITOPTIONS, SvxChartOptions::GetDefaultColors() ) );
1128             break;
1129         }
1130     }
1131     return pRet;
1132 }
1133 
1134 void OfaTreeOptionsDialog::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet )
1135 {
1136     switch(nId)
1137     {
1138         case SID_GENERAL_OPTIONS:
1139         {
1140             std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
1141 
1142             SfxItemSetFixed<SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER> aOptSet(SfxGetpApp()->GetPool());
1143             aOptSet.Put(rSet);
1144             if(aOptSet.Count())
1145                 SfxGetpApp()->SetOptions( aOptSet );
1146             // get dispatcher anew, because SetOptions() might have destroyed the dispatcher
1147             SfxViewFrame *pViewFrame = SfxViewFrame::Current();
1148 
1149 //          evaluate Year2000
1150             sal_uInt16 nY2K = USHRT_MAX;
1151             const SfxUInt16Item* pYearItem = rSet.GetItemIfSet( SID_ATTR_YEAR2000, false );
1152             if( pYearItem )
1153                 nY2K = pYearItem->GetValue();
1154             if( USHRT_MAX != nY2K )
1155             {
1156                 if ( pViewFrame )
1157                 {
1158                     SfxDispatcher* pDispatch = pViewFrame->GetDispatcher();
1159                     pDispatch->ExecuteList(SID_ATTR_YEAR2000,
1160                             SfxCallMode::ASYNCHRON, { pYearItem });
1161                 }
1162                 officecfg::Office::Common::DateFormat::TwoDigitYear::set(nY2K, batch);
1163             }
1164 
1165 //          evaluate print
1166             if(const SfxBoolItem* pWarnItem = rSet.GetItemIfSet(SID_PRINTER_NOTFOUND_WARN, false))
1167                 officecfg::Office::Common::Print::Warning::NotFound::set(pWarnItem->GetValue(), batch);
1168 
1169             if(const SfxFlagItem* pFlag = rSet.GetItemIfSet(SID_PRINTER_CHANGESTODOC, false))
1170             {
1171                 bool bPaperSizeWarning = bool(static_cast<SfxPrinterChangeFlags>(pFlag->GetValue()) &  SfxPrinterChangeFlags::CHG_SIZE);
1172                 officecfg::Office::Common::Print::Warning::PaperSize::set(bPaperSizeWarning, batch);
1173                 bool bPaperOrientationWarning = bool(static_cast<SfxPrinterChangeFlags>(pFlag->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION);
1174                 officecfg::Office::Common::Print::Warning::PaperOrientation::set(bPaperOrientationWarning, batch);
1175             }
1176 
1177 //          evaluate help options
1178             bool bHelpTips = officecfg::Office::Common::Help::Tip::get();
1179             if ( bHelpTips != Help::IsQuickHelpEnabled() )
1180                 bHelpTips ? Help::EnableQuickHelp() : Help::DisableQuickHelp();
1181             bool bExtendedHelp = officecfg::Office::Common::Help::ExtendedTip::get();
1182             if ( bExtendedHelp != Help::IsBalloonHelpEnabled() )
1183                 bExtendedHelp ? Help::EnableBalloonHelp() : Help::DisableBalloonHelp();
1184 
1185             batch->commit();
1186         }
1187         break;
1188         case SID_LANGUAGE_OPTIONS :
1189         {
1190             OfaTreeOptionsDialog::ApplyLanguageOptions(rSet);
1191         }
1192         break;
1193         case SID_INET_DLG :
1194         case SID_FILTER_DLG:
1195             SfxGetpApp()->SetOptions( rSet );
1196         break;
1197 
1198         case SID_SB_STARBASEOPTIONS:
1199             ::offapp::ConnectionPoolConfig::SetOptions( rSet );
1200             svx::DbRegisteredNamesConfig::SetOptions(rSet);
1201             break;
1202 
1203         case SID_SCH_EDITOPTIONS:
1204             // nothing to do. Chart options only apply to newly created charts
1205             break;
1206 
1207         default:
1208         {
1209             OSL_FAIL( "Unhandled option in ApplyItemSet" );
1210         }
1211         break;
1212     }
1213 
1214 }
1215 void OfaTreeOptionsDialog::ApplyLanguageOptions(const SfxItemSet& rSet)
1216 {
1217     bool bSaveSpellCheck = false;
1218     const SfxPoolItem* pItem = nullptr;
1219 
1220     Reference< XComponentContext >  xContext( ::comphelper::getProcessComponentContext() );
1221     Reference< XLinguProperties >  xProp = LinguProperties::create( xContext );
1222     if ( const SfxHyphenRegionItem* pHyphenItem = rSet.GetItemIfSet(SID_ATTR_HYPHENREGION, false ) )
1223     {
1224         xProp->setHyphMinLeading( static_cast<sal_Int16>(pHyphenItem->GetMinLead()) );
1225         xProp->setHyphMinTrailing( static_cast<sal_Int16>(pHyphenItem->GetMinTrail()) );
1226         bSaveSpellCheck = true;
1227     }
1228 
1229     SfxViewFrame *pViewFrame = SfxViewFrame::Current();
1230     if ( pViewFrame )
1231     {
1232         SfxDispatcher* pDispatch = pViewFrame->GetDispatcher();
1233         pItem = nullptr;
1234         if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_LANGUAGE, false, &pItem ))
1235         {
1236             pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem });
1237             bSaveSpellCheck = true;
1238         }
1239         if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE, false, &pItem ))
1240         {
1241             pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem });
1242             bSaveSpellCheck = true;
1243         }
1244         if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE, false, &pItem ))
1245         {
1246             pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem });
1247             bSaveSpellCheck = true;
1248         }
1249 
1250         if( SfxItemState::SET == rSet.GetItemState(SID_AUTOSPELL_CHECK, false, &pItem ))
1251         {
1252             bool bOnlineSpelling = static_cast<const SfxBoolItem*>(pItem)->GetValue();
1253             pDispatch->ExecuteList(SID_AUTOSPELL_CHECK,
1254                 SfxCallMode::ASYNCHRON|SfxCallMode::RECORD, { pItem });
1255 
1256             xProp->setIsSpellAuto( bOnlineSpelling );
1257         }
1258 
1259         if( bSaveSpellCheck )
1260         {
1261             //! the config item has changed since we modified the
1262             //! property set it uses
1263             pDispatch->Execute(SID_SPELLCHECKER_CHANGED, SfxCallMode::ASYNCHRON);
1264         }
1265     }
1266 
1267     if( SfxItemState::SET == rSet.GetItemState(SID_OPT_LOCALE_CHANGED, false, &pItem ))
1268     {
1269         SfxViewFrame* _pViewFrame = SfxViewFrame::GetFirst();
1270         while ( _pViewFrame )
1271         {
1272             _pViewFrame->GetDispatcher()->ExecuteList(pItem->Which(),
1273                     SfxCallMode::ASYNCHRON, { pItem });
1274             _pViewFrame = SfxViewFrame::GetNext( *_pViewFrame );
1275         }
1276     }
1277 }
1278 
1279 static OUString getCurrentFactory_Impl( const Reference< XFrame >& _xFrame )
1280 {
1281     OUString sIdentifier;
1282     Reference < XFrame > xCurrentFrame( _xFrame );
1283     Reference < XModuleManager2 > xModuleManager = ModuleManager::create(::comphelper::getProcessComponentContext());
1284     if ( !xCurrentFrame.is() )
1285     {
1286         Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1287         xCurrentFrame = xDesktop->getCurrentFrame();
1288     }
1289 
1290     if ( xCurrentFrame.is() )
1291     {
1292         try
1293         {
1294             sIdentifier = xModuleManager->identify( xCurrentFrame );
1295         }
1296         catch ( css::frame::UnknownModuleException& )
1297         {
1298             SAL_INFO( "cui.options", "unknown module" );
1299         }
1300         catch ( Exception const & )
1301         {
1302             TOOLS_WARN_EXCEPTION( "cui.options", "getActiveModule_Impl(): exception of XModuleManager::identify()" );
1303         }
1304     }
1305 
1306     return sIdentifier;
1307 }
1308 
1309 void OfaTreeOptionsDialog::Initialize( const Reference< XFrame >& _xFrame )
1310 {
1311     sal_uInt16 nGroup = 0;
1312 
1313     SvtOptionsDialogOptions aOptionsDlgOpt;
1314     sal_uInt16 nPageId;
1315 
1316     // %PRODUCTNAME options
1317     if ( !lcl_isOptionHidden( SID_GENERAL_OPTIONS, aOptionsDlgOpt ) )
1318     {
1319         setGroupName(u"ProductName", CuiResId(SID_GENERAL_OPTIONS_RES[0].first));
1320         nGroup = AddGroup(CuiResId(SID_GENERAL_OPTIONS_RES[0].first), nullptr, nullptr, SID_GENERAL_OPTIONS );
1321         const sal_uInt16 nEnd = static_cast<sal_uInt16>(std::size(SID_GENERAL_OPTIONS_RES));
1322 
1323         for (sal_uInt16 i = 1; i < nEnd; ++i)
1324         {
1325             OUString sNewTitle = CuiResId(SID_GENERAL_OPTIONS_RES[i].first);
1326             nPageId = SID_GENERAL_OPTIONS_RES[i].second;
1327             if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1328                 continue;
1329 
1330             // Disable Online Update page if service not installed
1331             if( RID_SVXPAGE_ONLINEUPDATE == nPageId )
1332             {
1333                 try
1334                 {
1335                     Reference < XInterface > xService( setup::UpdateCheck::create( ::comphelper::getProcessComponentContext() ) );
1336                     if( ! xService.is() )
1337                         continue;
1338                 }
1339                 catch ( css::uno::DeploymentException& )
1340                 {
1341                     continue;
1342                 }
1343             }
1344 
1345             // Disable Basic IDE options, if experimental features are not enabled
1346             if( RID_SVXPAGE_BASICIDE_OPTIONS == nPageId )
1347             {
1348                 if( ! officecfg::Office::Common::Misc::ExperimentalMode::get() )
1349                     continue;
1350             }
1351 
1352             AddTabPage( nPageId, sNewTitle, nGroup );
1353         }
1354     }
1355 
1356     // Load and Save options
1357     if ( !lcl_isOptionHidden( SID_FILTER_DLG, aOptionsDlgOpt ) )
1358     {
1359         setGroupName( u"LoadSave", CuiResId(SID_FILTER_DLG_RES[0].first) );
1360         nGroup = AddGroup( CuiResId(SID_FILTER_DLG_RES[0].first), nullptr, nullptr, SID_FILTER_DLG );
1361         for ( size_t i = 1; i < std::size(SID_FILTER_DLG_RES); ++i )
1362         {
1363             nPageId = static_cast<sal_uInt16>(SID_FILTER_DLG_RES[i].second);
1364             if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1365                 AddTabPage( nPageId, CuiResId(SID_FILTER_DLG_RES[i].first), nGroup );
1366         }
1367     }
1368 
1369     // Language options
1370     SvtCTLOptions aCTLLanguageOptions;
1371     if ( !lcl_isOptionHidden( SID_LANGUAGE_OPTIONS, aOptionsDlgOpt ) )
1372     {
1373         setGroupName(u"LanguageSettings", CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first));
1374         nGroup = AddGroup(CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first), nullptr, nullptr, SID_LANGUAGE_OPTIONS );
1375         for (size_t i = 1; i < std::size(SID_LANGUAGE_OPTIONS_RES); ++i)
1376         {
1377             nPageId = static_cast<sal_uInt16>(SID_LANGUAGE_OPTIONS_RES[i].second);
1378             if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1379                 continue;
1380 
1381             // Disable DeepL translation settings, if experimental mode is not enabled
1382             if( RID_SVXPAGE_DEEPL_OPTIONS == nPageId )
1383             {
1384                 if( ! officecfg::Office::Common::Misc::ExperimentalMode::get() )
1385                     continue;
1386             }
1387 
1388             if ( ( RID_SVXPAGE_JSEARCH_OPTIONS != nPageId || SvtCJKOptions::IsJapaneseFindEnabled() ) &&
1389                  ( RID_SVXPAGE_ASIAN_LAYOUT != nPageId    || SvtCJKOptions::IsAsianTypographyEnabled() ) &&
1390                  ( RID_SVXPAGE_OPTIONS_CTL != nPageId     || aCTLLanguageOptions.IsCTLFontEnabled() ) )
1391                 AddTabPage(nPageId, CuiResId(SID_LANGUAGE_OPTIONS_RES[i].first), nGroup);
1392         }
1393     }
1394 
1395     OUString aFactory = getCurrentFactory_Impl( _xFrame );
1396     DBG_ASSERT( GetModuleIdentifier( _xFrame ) == aFactory, "S H I T!!!" );
1397 
1398     // Writer and Writer/Web options
1399     SvtModuleOptions aModuleOpt;
1400     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
1401     {
1402         // text document
1403         if (   aFactory == "com.sun.star.text.TextDocument"
1404             || aFactory == "com.sun.star.text.WebDocument"
1405             || aFactory == "com.sun.star.text.GlobalDocument" )
1406         {
1407             SfxModule* pSwMod = SfxApplication::GetModule(SfxToolsModule::Writer);
1408             if ( !lcl_isOptionHidden( SID_SW_EDITOPTIONS, aOptionsDlgOpt ) )
1409             {
1410                 if ( aFactory == "com.sun.star.text.WebDocument" )
1411                     setGroupName( u"WriterWeb", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) );
1412                 else
1413                     setGroupName( u"Writer", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) );
1414                 nGroup = AddGroup(CuiResId(SID_SW_EDITOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_EDITOPTIONS );
1415                 for ( size_t i = 1; i < std::size(SID_SW_EDITOPTIONS_RES); ++i )
1416                 {
1417                     nPageId = static_cast<sal_uInt16>(SID_SW_EDITOPTIONS_RES[i].second);
1418                     if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1419                         continue;
1420                     if ( ( RID_SW_TP_STD_FONT_CJK != nPageId || SvtCJKOptions::IsCJKFontEnabled() ) &&
1421                          ( RID_SW_TP_STD_FONT_CTL != nPageId || aCTLLanguageOptions.IsCTLFontEnabled() ) &&
1422                          ( RID_SW_TP_MAILCONFIG != nPageId || MailMergeCfgIsEmailSupported() ) )
1423                         AddTabPage( nPageId, CuiResId(SID_SW_EDITOPTIONS_RES[i].first), nGroup );
1424                 }
1425 #ifdef DBG_UTIL
1426                 AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup );
1427 #endif
1428             }
1429 
1430             // HTML documents
1431             if ( !lcl_isOptionHidden( SID_SW_ONLINEOPTIONS, aOptionsDlgOpt ) )
1432             {
1433                 nGroup = AddGroup(CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_ONLINEOPTIONS );
1434                 for( size_t i = 1; i < std::size(SID_SW_ONLINEOPTIONS_RES); ++i )
1435                 {
1436                     nPageId = static_cast<sal_uInt16>(SID_SW_ONLINEOPTIONS_RES[i].second);
1437                     if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1438                         AddTabPage(nPageId, CuiResId(SID_SW_ONLINEOPTIONS_RES[i].first), nGroup);
1439                 }
1440 #ifdef DBG_UTIL
1441                 AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup );
1442 #endif
1443             }
1444         }
1445     }
1446 
1447     // Calc options
1448     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
1449     {
1450         if ( aFactory == "com.sun.star.sheet.SpreadsheetDocument" )
1451         {
1452             if ( !lcl_isOptionHidden( SID_SC_EDITOPTIONS, aOptionsDlgOpt ) )
1453             {
1454                 SfxModule* pScMod = SfxApplication::GetModule( SfxToolsModule::Calc );
1455                 setGroupName( u"Calc", CuiResId(SID_SC_EDITOPTIONS_RES[0].first) );
1456                 nGroup = AddGroup( CuiResId(SID_SC_EDITOPTIONS_RES[0].first), pScMod, pScMod, SID_SC_EDITOPTIONS );
1457                 const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SC_EDITOPTIONS_RES));
1458                 for ( sal_uInt16 i = 1; i < nCount; ++i )
1459                 {
1460                     nPageId = static_cast<sal_uInt16>(SID_SC_EDITOPTIONS_RES[i].second);
1461                     if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1462                         continue;
1463 
1464                     AddTabPage( nPageId, CuiResId(SID_SC_EDITOPTIONS_RES[i].first), nGroup );
1465                 }
1466             }
1467         }
1468     }
1469 
1470     // Impress options
1471     SfxModule* pSdMod = SfxApplication::GetModule( SfxToolsModule::Draw );
1472     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
1473     {
1474         if ( aFactory == "com.sun.star.presentation.PresentationDocument" )
1475         {
1476             if ( !lcl_isOptionHidden( SID_SD_EDITOPTIONS, aOptionsDlgOpt ) )
1477             {
1478                 setGroupName( u"Impress", CuiResId(SID_SD_EDITOPTIONS_RES[0].first) );
1479                 nGroup = AddGroup( CuiResId(SID_SD_EDITOPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_EDITOPTIONS );
1480                 const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SD_EDITOPTIONS_RES));
1481                 for ( sal_uInt16 i = 1; i < nCount; ++i )
1482                 {
1483                     nPageId = static_cast<sal_uInt16>(SID_SD_EDITOPTIONS_RES[i].second);
1484                     if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1485                         continue;
1486 
1487                     AddTabPage( nPageId, CuiResId(SID_SD_EDITOPTIONS_RES[i].first), nGroup );
1488                 }
1489             }
1490         }
1491     }
1492 
1493     // Draw options
1494     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
1495     {
1496         if ( aFactory == "com.sun.star.drawing.DrawingDocument" )
1497         {
1498             if ( !lcl_isOptionHidden( SID_SD_GRAPHIC_OPTIONS, aOptionsDlgOpt ) )
1499             {
1500                 setGroupName( u"Draw", CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first) );
1501                 nGroup = AddGroup( CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_GRAPHIC_OPTIONS );
1502                 const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SD_GRAPHIC_OPTIONS_RES));
1503                 for ( sal_uInt16 i = 1; i < nCount; ++i )
1504                 {
1505                     nPageId = static_cast<sal_uInt16>(SID_SD_GRAPHIC_OPTIONS_RES[i].second);
1506                     if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1507                         continue;
1508 
1509                     AddTabPage( nPageId, CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[i].first), nGroup );
1510                 }
1511             }
1512         }
1513     }
1514 
1515     // Math options
1516     if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) )
1517     {
1518         if ( aFactory == "com.sun.star.formula.FormulaProperties" )
1519         {
1520             if ( !lcl_isOptionHidden( SID_SM_EDITOPTIONS, aOptionsDlgOpt ) )
1521             {
1522                 SfxModule* pSmMod = SfxApplication::GetModule(SfxToolsModule::Math);
1523                 setGroupName( u"Math", CuiResId(SID_SM_EDITOPTIONS_RES[0].first) );
1524                 nGroup = AddGroup(CuiResId(SID_SM_EDITOPTIONS_RES[0].first), pSmMod, pSmMod, SID_SM_EDITOPTIONS );
1525                 for ( size_t i = 1; i < std::size(SID_SM_EDITOPTIONS_RES); ++i )
1526                 {
1527                     nPageId = static_cast<sal_uInt16>(SID_SM_EDITOPTIONS_RES[i].second);
1528                     if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1529                         AddTabPage( nPageId, CuiResId(SID_SM_EDITOPTIONS_RES[i].first), nGroup );
1530                 }
1531             }
1532         }
1533     }
1534 
1535     // Database - needed only if there is an application which integrates with databases
1536     if ( !lcl_isOptionHidden( SID_SB_STARBASEOPTIONS, aOptionsDlgOpt ) &&
1537         (   aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE )
1538         ||  aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER )
1539         ||  aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC )
1540         ) )
1541     {
1542         setGroupName( u"Base", CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first) );
1543         nGroup = AddGroup( CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first), nullptr, nullptr, SID_SB_STARBASEOPTIONS );
1544         for ( size_t i = 1; i < std::size(SID_SB_STARBASEOPTIONS_RES); ++i )
1545         {
1546             nPageId = static_cast<sal_uInt16>(SID_SB_STARBASEOPTIONS_RES[i].second);
1547             if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1548                 AddTabPage( nPageId, CuiResId(SID_SB_STARBASEOPTIONS_RES[i].first), nGroup );
1549         }
1550     }
1551 
1552     // Chart options (always installed and active)
1553     if ( !lcl_isOptionHidden( SID_SCH_EDITOPTIONS, aOptionsDlgOpt ) )
1554     {
1555         setGroupName( u"Charts", CuiResId(SID_SCH_EDITOPTIONS_RES[0].first) );
1556         nGroup = AddGroup( CuiResId(SID_SCH_EDITOPTIONS_RES[0].first), nullptr, nullptr, SID_SCH_EDITOPTIONS );
1557         for ( size_t i = 1; i < std::size(SID_SCH_EDITOPTIONS_RES); ++i )
1558         {
1559             nPageId = static_cast<sal_uInt16>(SID_SCH_EDITOPTIONS_RES[i].second);
1560             if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1561                AddTabPage( nPageId, CuiResId(SID_SCH_EDITOPTIONS_RES[i].first), nGroup );
1562         }
1563     }
1564 
1565     // Internet options
1566     if ( lcl_isOptionHidden( SID_INET_DLG, aOptionsDlgOpt ) )
1567         return;
1568 
1569     setGroupName(u"Internet", CuiResId(SID_INET_DLG_RES[0].first));
1570     nGroup = AddGroup(CuiResId(SID_INET_DLG_RES[0].first), nullptr, nullptr, SID_INET_DLG );
1571 
1572     for ( size_t i = 1; i < std::size(SID_INET_DLG_RES); ++i )
1573     {
1574         nPageId = static_cast<sal_uInt16>(SID_INET_DLG_RES[i].second);
1575         if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) )
1576             continue;
1577 #if defined(_WIN32)
1578         // Disable E-mail tab-page on Windows
1579         if ( nPageId == RID_SVXPAGE_INET_MAIL )
1580             continue;
1581 #endif
1582         AddTabPage( nPageId, CuiResId(SID_INET_DLG_RES[i].first), nGroup );
1583     }
1584 }
1585 
1586 static bool isNodeActive( OptionsNode const * pNode, Module* pModule )
1587 {
1588     if ( !pNode )
1589         return false;
1590 
1591     // Node for all modules active?
1592     if ( pNode->m_bAllModules )
1593         return true;
1594 
1595     // OOo-Nodes (Writer, Calc, Impress...) are active if node is already inserted
1596     if ( !getGroupName( pNode->m_sId, false ).isEmpty() )
1597         return true;
1598 
1599     // no module -> not active
1600     if ( !pModule )
1601         return false;
1602 
1603     // search node in active module
1604     if ( pModule->m_bActive )
1605     {
1606         for (auto const& j : pModule->m_aNodeList)
1607             if ( j->m_sId == pNode->m_sId )
1608                 return true;
1609     }
1610     return false;
1611 }
1612 
1613 void OfaTreeOptionsDialog::LoadExtensionOptions( std::u16string_view rExtensionId )
1614 {
1615     std::unique_ptr<Module> pModule;
1616 
1617     // when called by Tools - Options then load nodes of active module
1618     if ( rExtensionId.empty() )
1619     {
1620         pModule = LoadModule( GetModuleIdentifier( Reference< XFrame >() ) );
1621     }
1622 
1623     VectorOfNodes aNodeList = LoadNodes( pModule.get(), rExtensionId );
1624     InsertNodes( aNodeList );
1625 }
1626 
1627 OUString OfaTreeOptionsDialog::GetModuleIdentifier( const Reference< XFrame >& rFrame )
1628 {
1629     OUString sModule;
1630     Reference < XFrame > xCurrentFrame( rFrame );
1631     Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
1632     Reference < XModuleManager2 > xModuleManager = ModuleManager::create(xContext);
1633 
1634     if ( !xCurrentFrame.is() )
1635     {
1636         Reference < XDesktop2 > xDesktop = Desktop::create( xContext );
1637         xCurrentFrame = xDesktop->getCurrentFrame();
1638     }
1639 
1640     if ( xCurrentFrame.is() )
1641     {
1642         try
1643         {
1644             sModule = xModuleManager->identify( xCurrentFrame );
1645         }
1646         catch ( css::frame::UnknownModuleException& )
1647         {
1648             SAL_INFO( "cui.options", "unknown module" );
1649         }
1650         catch ( Exception const & )
1651         {
1652             TOOLS_WARN_EXCEPTION( "cui.options", "OfaTreeOptionsDialog::GetModuleIdentifier(): exception of XModuleManager::identify()");
1653         }
1654     }
1655     return sModule;
1656 }
1657 
1658 std::unique_ptr<Module> OfaTreeOptionsDialog::LoadModule(
1659     std::u16string_view rModuleIdentifier )
1660 {
1661     std::unique_ptr<Module> pModule;
1662     Reference< XNameAccess > xSet(
1663         officecfg::Office::OptionsDialog::Modules::get());
1664 
1665     const Sequence< OUString > seqNames = xSet->getElementNames();
1666     for ( const OUString& rModule : seqNames )
1667     {
1668         if ( rModuleIdentifier == rModule )
1669         {
1670             // current active module found
1671             pModule.reset(new Module);
1672             pModule->m_bActive = true;
1673 
1674             Reference< XNameAccess > xModAccess;
1675             xSet->getByName( rModule ) >>= xModAccess;
1676             if ( xModAccess.is() )
1677             {
1678                 // load the nodes of this module
1679                 Reference< XNameAccess > xNodeAccess;
1680                 xModAccess->getByName( "Nodes" ) >>= xNodeAccess;
1681                 if ( xNodeAccess.is() )
1682                 {
1683                     const Sequence< OUString > xTemp = xNodeAccess->getElementNames();
1684                     Reference< XNameAccess > xAccess;
1685                     sal_Int32 nIndex = -1;
1686                     for ( const OUString& rNode : xTemp)
1687                     {
1688                         xNodeAccess->getByName( rNode ) >>= xAccess;
1689                         if ( xAccess.is() )
1690                         {
1691                             xAccess->getByName( "Index" ) >>= nIndex;
1692                             if ( nIndex < 0 )
1693                                 // append nodes with index < 0
1694                                 pModule->m_aNodeList.push_back(
1695                                  std::unique_ptr<OrderedEntry>(new OrderedEntry(nIndex, rNode)));
1696                             else
1697                             {
1698                                 // search position of the node
1699                                 std::vector<OrderedEntry *>::size_type y = 0;
1700                                 for ( ; y < pModule->m_aNodeList.size(); ++y )
1701                                 {
1702                                     sal_Int32 nNodeIdx = pModule->m_aNodeList[y]->m_nIndex;
1703                                     if ( nNodeIdx < 0 || nNodeIdx > nIndex )
1704                                         break;
1705                                 }
1706                                 // and insert the node on this position
1707                                 pModule->m_aNodeList.insert(
1708                                     pModule->m_aNodeList.begin() + y,
1709                                     std::unique_ptr<OrderedEntry>(new OrderedEntry( nIndex, rNode )) );
1710                             }
1711                         }
1712                     }
1713                 }
1714             }
1715             break;
1716         }
1717     }
1718     return pModule;
1719 }
1720 
1721 VectorOfNodes OfaTreeOptionsDialog::LoadNodes(
1722     Module* pModule, std::u16string_view rExtensionId)
1723 {
1724     VectorOfNodes aOutNodeList;
1725 
1726     Reference< XNameAccess > xSet(
1727         officecfg::Office::OptionsDialog::Nodes::get());
1728     VectorOfNodes aNodeList;
1729     const Sequence< OUString > seqNames = xSet->getElementNames();
1730 
1731     for ( OUString const & sGroupName : seqNames )
1732     {
1733         Reference< XNameAccess > xNodeAccess;
1734         xSet->getByName( sGroupName ) >>= xNodeAccess;
1735 
1736         if ( xNodeAccess.is() )
1737         {
1738             OUString sNodeId, sLabel, sPageURL;
1739             bool bAllModules = false;
1740 
1741             sNodeId = sGroupName;
1742             xNodeAccess->getByName( "Label" ) >>= sLabel;
1743             xNodeAccess->getByName( "OptionsPage" ) >>= sPageURL;
1744             xNodeAccess->getByName( "AllModules" ) >>= bAllModules;
1745 
1746             if ( sLabel.isEmpty() )
1747                 sLabel = sGroupName;
1748             OUString sTemp = getGroupName( sLabel, !rExtensionId.empty() );
1749             if ( !sTemp.isEmpty() )
1750                 sLabel = sTemp;
1751             std::unique_ptr<OptionsNode> pNode(new OptionsNode(sNodeId, sLabel, bAllModules));
1752 
1753             if ( rExtensionId.empty() && !isNodeActive( pNode.get(), pModule ) )
1754             {
1755                 continue;
1756             }
1757 
1758             Reference< XNameAccess > xLeavesSet;
1759             xNodeAccess->getByName( "Leaves" ) >>= xLeavesSet;
1760             if ( xLeavesSet.is() )
1761             {
1762                 const Sequence< OUString > seqLeaves = xLeavesSet->getElementNames();
1763                 for ( OUString const & leafName : seqLeaves )
1764                 {
1765                     Reference< XNameAccess > xLeaveAccess;
1766                     xLeavesSet->getByName( leafName ) >>= xLeaveAccess;
1767 
1768                     if ( xLeaveAccess.is() )
1769                     {
1770                         OUString sId, sLeafLabel, sEventHdl, sLeafURL, sLeafGrpId;
1771                         sal_Int32 nLeafGrpIdx = 0;
1772 
1773                         xLeaveAccess->getByName( "Id" ) >>= sId;
1774                         xLeaveAccess->getByName( "Label" ) >>= sLeafLabel;
1775                         xLeaveAccess->getByName( "OptionsPage" ) >>= sLeafURL;
1776                         xLeaveAccess->getByName( "EventHandlerService" ) >>= sEventHdl;
1777                         xLeaveAccess->getByName( "GroupId" ) >>= sLeafGrpId;
1778                         xLeaveAccess->getByName( "GroupIndex" ) >>= nLeafGrpIdx;
1779 
1780                         if ( rExtensionId.empty() || sId == rExtensionId )
1781                         {
1782                             std::unique_ptr<OptionsLeaf> pLeaf(new OptionsLeaf(
1783                                 sLeafLabel, sLeafURL, sEventHdl, sLeafGrpId, nLeafGrpIdx ));
1784 
1785                             if ( !sLeafGrpId.isEmpty() )
1786                             {
1787                                 bool bAlreadyOpened = false;
1788                                 if ( !pNode->m_aGroupedLeaves.empty() )
1789                                 {
1790                                     for (auto & rGroup : pNode->m_aGroupedLeaves)
1791                                     {
1792                                         if ( !rGroup.empty() &&
1793                                              rGroup[0]->m_sGroupId == sLeafGrpId )
1794                                         {
1795                                             std::vector<std::unique_ptr<OptionsLeaf>>::size_type l = 0;
1796                                             for ( ; l < rGroup.size(); ++l )
1797                                             {
1798                                                 if ( rGroup[l]->m_nGroupIndex >= nLeafGrpIdx )
1799                                                     break;
1800                                             }
1801                                             rGroup.insert( rGroup.begin() + l, std::move(pLeaf) );
1802                                             bAlreadyOpened = true;
1803                                             break;
1804                                         }
1805                                     }
1806                                 }
1807                                 if ( !bAlreadyOpened )
1808                                 {
1809                                     std::vector< std::unique_ptr<OptionsLeaf> > aGroupedLeaves;
1810                                     aGroupedLeaves.push_back( std::move(pLeaf) );
1811                                     pNode->m_aGroupedLeaves.push_back( std::move(aGroupedLeaves) );
1812                                 }
1813                             }
1814                             else
1815                                 pNode->m_aLeaves.push_back( std::move(pLeaf) );
1816                         }
1817                     }
1818                 }
1819             }
1820 
1821             // do not insert nodes without leaves
1822             if ( !pNode->m_aLeaves.empty() || !pNode->m_aGroupedLeaves.empty() )
1823             {
1824                 pModule ? aNodeList.push_back( std::move(pNode) ) : aOutNodeList.push_back( std::move(pNode) );
1825             }
1826         }
1827     }
1828 
1829     if ( pModule && !aNodeList.empty() )
1830     {
1831         for ( auto const & i: pModule->m_aNodeList )
1832         {
1833             OUString sNodeId = i->m_sId;
1834             for ( auto j = aNodeList.begin(); j != aNodeList.end(); ++j )
1835             {
1836                 if ( (*j)->m_sId == sNodeId )
1837                 {
1838                     aOutNodeList.push_back( std::move(*j) );
1839                     aNodeList.erase( j );
1840                     break;
1841                 }
1842             }
1843         }
1844 
1845         for ( auto & i: aNodeList )
1846             aOutNodeList.push_back( std::move(i) );
1847     }
1848     return aOutNodeList;
1849 }
1850 
1851 static sal_uInt16 lcl_getGroupId( std::u16string_view rGroupName, const weld::TreeView& rTreeLB )
1852 {
1853     sal_uInt16 nRet = 0;
1854 
1855     std::unique_ptr<weld::TreeIter> xEntry = rTreeLB.make_iterator();
1856     bool bEntry = rTreeLB.get_iter_first(*xEntry);
1857     while (bEntry)
1858     {
1859         if (!rTreeLB.get_iter_depth(*xEntry))
1860         {
1861             OUString sTemp(rTreeLB.get_text(*xEntry));
1862             if (sTemp == rGroupName)
1863                 return nRet;
1864             nRet++;
1865         }
1866         bEntry = rTreeLB.iter_next(*xEntry);
1867     }
1868 
1869     return USHRT_MAX;
1870 }
1871 
1872 static void lcl_insertLeaf(
1873     OfaTreeOptionsDialog* pDlg, OptionsNode const * pNode, OptionsLeaf const * pLeaf, const weld::TreeView& rTreeLB )
1874 {
1875     sal_uInt16 nGrpId = lcl_getGroupId( pNode->m_sLabel, rTreeLB );
1876     if ( USHRT_MAX == nGrpId )
1877     {
1878         sal_uInt16 nNodeGrpId = getGroupNodeId( pNode->m_sId );
1879         nGrpId = pDlg->AddGroup( pNode->m_sLabel, nullptr, nullptr, nNodeGrpId );
1880     }
1881     OptionsPageInfo* pInfo = pDlg->AddTabPage( 0, pLeaf->m_sLabel, nGrpId );
1882     pInfo->m_sPageURL = pLeaf->m_sPageURL;
1883     pInfo->m_sEventHdl = pLeaf->m_sEventHdl;
1884 }
1885 
1886 void  OfaTreeOptionsDialog::InsertNodes( const VectorOfNodes& rNodeList )
1887 {
1888     for (auto const& node : rNodeList)
1889     {
1890         if ( !node->m_aLeaves.empty() || !node->m_aGroupedLeaves.empty() )
1891         {
1892             for ( auto const & j: node->m_aGroupedLeaves )
1893             {
1894                 for ( size_t k = 0; k < j.size(); ++k )
1895                 {
1896                     lcl_insertLeaf( this, node.get(), j[k].get(), *xTreeLB );
1897                 }
1898             }
1899 
1900             for ( auto const & j: node->m_aLeaves )
1901             {
1902                 lcl_insertLeaf( this, node.get(), j.get(), *xTreeLB );
1903             }
1904         }
1905     }
1906 }
1907 
1908 void OfaTreeOptionsDialog::SetNeedsRestart( svtools::RestartReason eReason)
1909 {
1910     bNeedsRestart = true;
1911     eRestartReason = eReason;
1912 }
1913 
1914 short OfaTreeOptionsDialog::run()
1915 {
1916     std::unique_ptr< SvxDicListChgClamp > pClamp;
1917     if ( !bIsFromExtensionManager )
1918     {
1919         // collect all DictionaryList Events while the dialog is executed
1920         Reference<css::linguistic2::XSearchableDictionaryList> xDictionaryList(LinguMgr::GetDictionaryList());
1921         pClamp.reset( new SvxDicListChgClamp( xDictionaryList ) );
1922     }
1923 
1924     return SfxOkDialogController::run();
1925 }
1926 
1927 // class ExtensionsTabPage -----------------------------------------------
1928 ExtensionsTabPage::ExtensionsTabPage(
1929     weld::Container* pParent, OUString aPageURL,
1930     OUString aEvtHdl, const Reference< awt::XContainerWindowProvider >& rProvider )
1931     : m_pContainer(pParent)
1932     , m_sPageURL(std::move(aPageURL))
1933     , m_sEventHdl(std::move(aEvtHdl))
1934     , m_xWinProvider(rProvider)
1935 {
1936 }
1937 
1938 ExtensionsTabPage::~ExtensionsTabPage()
1939 {
1940     Hide();
1941     DeactivatePage();
1942 
1943     if ( m_xPage.is() )
1944     {
1945         try
1946         {
1947             m_xPage->dispose();
1948         }
1949         catch (const Exception&)
1950         {
1951         }
1952         m_xPage.clear();
1953     }
1954 
1955     if ( m_xPageParent.is() )
1956     {
1957         try
1958         {
1959             m_xPageParent->dispose();
1960         }
1961         catch (const Exception&)
1962         {
1963         }
1964         m_xPageParent.clear();
1965     }
1966 }
1967 
1968 void ExtensionsTabPage::CreateDialogWithHandler()
1969 {
1970     try
1971     {
1972         bool bWithHandler = !m_sEventHdl.isEmpty();
1973         if ( bWithHandler )
1974         {
1975             Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
1976             m_xEventHdl.set( xFactory->createInstance( m_sEventHdl ), UNO_QUERY );
1977         }
1978 
1979         if ( !bWithHandler || m_xEventHdl.is() )
1980         {
1981             m_xPageParent = m_pContainer->CreateChildFrame();
1982             Reference<awt::XWindowPeer> xParent(m_xPageParent, UNO_QUERY);
1983             m_xPage =
1984                 m_xWinProvider->createContainerWindow(
1985                     m_sPageURL, OUString(), xParent, m_xEventHdl );
1986 
1987             Reference< awt::XControl > xPageControl( m_xPage, UNO_QUERY );
1988             if ( xPageControl.is() )
1989             {
1990                 Reference< awt::XWindowPeer > xWinPeer( xPageControl->getPeer() );
1991                 if ( xWinPeer.is() )
1992                 {
1993                     VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWinPeer );
1994                     if ( pWindow )
1995                         pWindow->SetStyle( pWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL );
1996                 }
1997             }
1998         }
1999     }
2000     catch (const Exception&)
2001     {
2002         TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::CreateDialogWithHandler(): exception of XDialogProvider2::createDialogWithHandler()");
2003     }
2004 }
2005 
2006 bool ExtensionsTabPage::DispatchAction( const OUString& rAction )
2007 {
2008     bool bRet = false;
2009     if ( m_xEventHdl.is() )
2010     {
2011         try
2012         {
2013             bRet = m_xEventHdl->callHandlerMethod( m_xPage, Any( rAction ), "external_event" );
2014         }
2015         catch ( Exception const & )
2016         {
2017             TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::DispatchAction(): exception of XDialogEventHandler::callHandlerMethod()" );
2018         }
2019     }
2020     return bRet;
2021 }
2022 
2023 void ExtensionsTabPage::Show()
2024 {
2025     if (!m_xPageParent.is())
2026         return;
2027 
2028     VclPtr<vcl::Window> xPageParent = VCLUnoHelper::GetWindow(m_xPageParent);
2029     if (xPageParent)
2030     {
2031         // NoActivate otherwise setVisible will call Window::Show which will grab
2032         // focus to the page by default
2033         xPageParent->Show(true, ShowFlags::NoActivate);
2034     }
2035 
2036     m_xPageParent->setVisible(true);
2037 }
2038 
2039 void ExtensionsTabPage::Hide()
2040 {
2041     if (!m_xPageParent.is())
2042         return;
2043     m_xPageParent->setVisible(false);
2044 }
2045 
2046 void ExtensionsTabPage::ActivatePage()
2047 {
2048     if ( !m_xPage.is() )
2049     {
2050         CreateDialogWithHandler();
2051 
2052         if ( m_xPage.is() )
2053         {
2054             auto aWindowRect = m_xPageParent->getPosSize();
2055             m_xPage->setPosSize(0, 0, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POSSIZE);
2056             if ( !m_sEventHdl.isEmpty() )
2057                 DispatchAction( "initialize" );
2058         }
2059     }
2060 
2061     if ( m_xPage.is() )
2062     {
2063         m_xPage->setVisible( true );
2064     }
2065 }
2066 
2067 void ExtensionsTabPage::DeactivatePage()
2068 {
2069     if ( m_xPage.is() )
2070         m_xPage->setVisible( false );
2071 }
2072 
2073 void ExtensionsTabPage::ResetPage()
2074 {
2075     DispatchAction( "back" );
2076     ActivatePage();
2077 }
2078 
2079 void ExtensionsTabPage::SavePage()
2080 {
2081     DispatchAction( "ok" );
2082 }
2083 
2084 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2085