diff options
Diffstat (limited to '')
-rw-r--r-- | cui/source/options/treeopt.cxx | 2115 |
1 files changed, 2115 insertions, 0 deletions
diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx new file mode 100644 index 000000000..5973f422a --- /dev/null +++ b/cui/source/options/treeopt.cxx @@ -0,0 +1,2115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <string_view> + +#include <config_features.h> +#include <config_feature_opencl.h> +#include <config_feature_desktop.h> +#include <config_gpgme.h> + +#include <officecfg/Office/Common.hxx> + +#include <svx/dialogs.hrc> +#include <svx/svxids.hrc> + +#include <treeopt.hrc> +#include <helpids.h> + +#include "cfgchart.hxx" +#include "connpoolconfig.hxx" +#include "connpooloptions.hxx" +#include <cuioptgenrl.hxx> +#include <dbregister.hxx> +#include "dbregisterednamesconfig.hxx" +#include <dialmgr.hxx> +#include "fontsubs.hxx" +#include "optaccessibility.hxx" +#include <optasian.hxx> +#include "optchart.hxx" +#include "optcolor.hxx" +#include "optctl.hxx" +#include "optfltr.hxx" +#include "optgdlg.hxx" +#include "opthtml.hxx" +#include "optinet2.hxx" +#include "optjava.hxx" +#include "optjsearch.hxx" +#include <optlingu.hxx> +#if HAVE_FEATURE_OPENCL +#include "optopencl.hxx" +#endif +#include <optpath.hxx> +#include "optsave.hxx" +#include "optupdt.hxx" +#include "personalization.hxx" +#include <treeopt.hxx> +#include "optbasic.hxx" +#include "optlanguagetool.hxx" + +#include <com/sun/star/awt/XContainerWindowEventHandler.hpp> +#include <com/sun/star/awt/ContainerWindowProvider.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/frame/UnknownModuleException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/linguistic2/LinguProperties.hpp> +#include <com/sun/star/setup/UpdateCheck.hpp> +#include <comphelper/getexpandeduri.hxx> +#include <comphelper/processfactory.hxx> +#include <editeng/langitem.hxx> +#include <editeng/optitems.hxx> +#include <editeng/unolingu.hxx> +#include <linguistic/misc.hxx> +#include <officecfg/Office/OptionsDialog.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/module.hxx> +#include <sfx2/printopt.hxx> +#include <sfx2/shell.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/flagitem.hxx> +#include <svl/intitem.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <svx/databaseregistrationui.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/urlobj.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/configmgr.hxx> +#include <unotools/moduleoptions.hxx> +#include <unotools/optionsdlg.hxx> +#include <unotools/viewoptions.hxx> +#include <utility> +#include <vcl/help.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <vcl/window.hxx> +#include <sal/log.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +LastPageSaver* OfaTreeOptionsDialog::pLastPageSaver = nullptr; + +// some stuff for easier changes for SvtViewOptions +constexpr OUStringLiteral VIEWOPT_DATANAME = u"page data"; + +static void SetViewOptUserItem( SvtViewOptions& rOpt, const OUString& rData ) +{ + rOpt.SetUserItem( VIEWOPT_DATANAME, Any( rData ) ); +} + +static OUString GetViewOptUserItem( const SvtViewOptions& rOpt ) +{ + Any aAny( rOpt.GetUserItem( VIEWOPT_DATANAME ) ); + OUString aUserData; + aAny >>= aUserData; + + return aUserData; +} + +namespace { + +struct ModuleToGroupNameMap_Impl +{ + std::u16string_view m_pModule; + OUString m_sGroupName; + sal_uInt16 m_nNodeId; +}; +} + +static ModuleToGroupNameMap_Impl ModuleMap[] = +{ + { u"ProductName", OUString(), SID_GENERAL_OPTIONS }, + { u"LanguageSettings", OUString(), SID_LANGUAGE_OPTIONS }, + { u"Internet", OUString(), SID_INET_DLG }, + { u"LoadSave", OUString(), SID_FILTER_DLG }, + { u"Writer", OUString(), SID_SW_EDITOPTIONS }, + { u"WriterWeb", OUString(), SID_SW_ONLINEOPTIONS }, + { u"Math", OUString(), SID_SM_EDITOPTIONS }, + { u"Calc", OUString(), SID_SC_EDITOPTIONS }, + { u"Impress", OUString(), SID_SD_EDITOPTIONS }, + { u"Draw", OUString(), SID_SD_GRAPHIC_OPTIONS }, + { u"Charts", OUString(), SID_SCH_EDITOPTIONS }, + { u"Base", OUString(), SID_SB_STARBASEOPTIONS }, +}; + +static void setGroupName( std::u16string_view rModule, const OUString& rGroupName ) +{ + for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + rEntry.m_sGroupName = rGroupName; + break; + } + } +} + +static OUString getGroupName( std::u16string_view rModule, bool bForced ) +{ + OUString sGroupName; + for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + sGroupName = rEntry.m_sGroupName; + break; + } + } + + if ( sGroupName.isEmpty() && bForced ) + { + if ( rModule == u"Writer" ) + sGroupName = CuiResId(SID_SW_EDITOPTIONS_RES[0].first); + else if ( rModule == u"WriterWeb" ) + sGroupName = CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first); + else if ( rModule == u"Calc" ) + sGroupName = CuiResId(SID_SC_EDITOPTIONS_RES[0].first); + else if ( rModule == u"Impress" ) + sGroupName = CuiResId(SID_SD_EDITOPTIONS_RES[0].first); + else if ( rModule == u"Draw" ) + sGroupName = CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first); + else if ( rModule == u"Math" ) + sGroupName = CuiResId(SID_SM_EDITOPTIONS_RES[0].first); + else if ( rModule == u"Base" ) + sGroupName = CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first); + } + return sGroupName; +} + +static void deleteGroupNames() +{ + for (ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + rEntry.m_sGroupName.clear(); +} + +static sal_uInt16 getGroupNodeId( std::u16string_view rModule ) +{ + sal_uInt16 nNodeId = 0xFFFF; + for (const ModuleToGroupNameMap_Impl& rEntry : ModuleMap) + { + if ( rEntry.m_pModule == rModule ) + { + nNodeId = rEntry.m_nNodeId; + break; + } + } + + return nNodeId; +} + +namespace { + +class MailMergeCfg_Impl : public utl::ConfigItem +{ +private: + // variables + bool bIsEmailSupported; + + virtual void ImplCommit() override; + +public: + MailMergeCfg_Impl(); + + virtual void Notify( const css::uno::Sequence< OUString >& _rPropertyNames) override; + + bool IsEmailSupported() const {return bIsEmailSupported;} + +}; + +} + +MailMergeCfg_Impl::MailMergeCfg_Impl() : + utl::ConfigItem("Office.Writer/MailMergeWizard"), + bIsEmailSupported(false) +{ + Sequence<OUString> aNames { "EMailSupported" }; + const Sequence< Any > aValues = GetProperties(aNames); + const Any* pValues = aValues.getConstArray(); + if(aValues.hasElements() && pValues[0].hasValue()) + pValues[0] >>= bIsEmailSupported; +} + +void MailMergeCfg_Impl::ImplCommit() +{ +} + +void MailMergeCfg_Impl::Notify( const css::uno::Sequence< OUString >& ) +{ +} + +//typedef SfxTabPage* (*FNCreateTabPage)(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rAttrSet); +static std::unique_ptr<SfxTabPage> CreateGeneralTabPage(sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) +{ + CreateTabPage fnCreate = nullptr; + switch(nId) + { + case RID_SFXPAGE_SAVE: fnCreate = &SvxSaveTabPage::Create; break; + case RID_SFXPAGE_PATH: fnCreate = &SvxPathTabPage::Create; break; + case RID_SFXPAGE_GENERAL: fnCreate = &SvxGeneralTabPage::Create; break; + case RID_SFXPAGE_PRINTOPTIONS: fnCreate = &SfxCommonPrintOptionsTabPage::Create; break; + case OFA_TP_LANGUAGES: fnCreate = &OfaLanguagesTabPage::Create; break; + case RID_SFXPAGE_LINGU: fnCreate = &SvxLinguTabPage::Create; break; + case OFA_TP_VIEW: fnCreate = &OfaViewTabPage::Create; break; + case OFA_TP_MISC: fnCreate = &OfaMiscTabPage::Create; break; + case RID_SVXPAGE_ASIAN_LAYOUT: fnCreate = &SvxAsianLayoutPage::Create; break; + case RID_SVX_FONT_SUBSTITUTION: fnCreate = &SvxFontSubstTabPage::Create; break; + case RID_SVXPAGE_INET_PROXY: fnCreate = &SvxProxyTabPage::Create; break; + case RID_SVXPAGE_INET_SECURITY: fnCreate = &SvxSecurityTabPage::Create; break; + case RID_SVXPAGE_INET_MAIL: fnCreate = &SvxEMailTabPage::Create; break; +#if HAVE_FEATURE_DESKTOP + case RID_SVXPAGE_PERSONALIZATION: fnCreate = &SvxPersonalizationTabPage::Create; break; +#endif + case RID_SVXPAGE_COLORCONFIG: fnCreate = &SvxColorOptionsTabPage::Create; break; + case RID_OFAPAGE_HTMLOPT: fnCreate = &OfaHtmlTabPage::Create; break; + case SID_OPTFILTER_MSOFFICE: fnCreate = &OfaMSFilterTabPage::Create; break; + case RID_OFAPAGE_MSFILTEROPT2: fnCreate = &OfaMSFilterTabPage2::Create; break; + case RID_SVXPAGE_JSEARCH_OPTIONS: fnCreate = &SvxJSearchOptionsPage::Create ; break; + case SID_SB_CONNECTIONPOOLING: fnCreate = &::offapp::ConnectionPoolOptionsPage::Create; break; + case SID_SB_DBREGISTEROPTIONS: fnCreate = &svx::DbRegistrationOptionsPage::Create; break; + case RID_SVXPAGE_ACCESSIBILITYCONFIG: fnCreate = &SvxAccessibilityOptionsTabPage::Create; break; + case RID_SVXPAGE_OPTIONS_CTL: fnCreate = &SvxCTLOptionsPage::Create ; break; + case RID_SVXPAGE_LANGTOOL_OPTIONS: fnCreate = &OptLanguageToolTabPage::Create ; break; + case RID_SVXPAGE_OPTIONS_JAVA: fnCreate = &SvxJavaOptionsPage::Create ; break; +#if HAVE_FEATURE_OPENCL + case RID_SVXPAGE_OPENCL: fnCreate = &SvxOpenCLTabPage::Create ; break; +#endif + case RID_SVXPAGE_ONLINEUPDATE: fnCreate = &SvxOnlineUpdateTabPage::Create; break; + case RID_OPTPAGE_CHART_DEFCOLORS: fnCreate = &SvxDefaultColorOptPage::Create; break; +#if HAVE_FEATURE_SCRIPTING + case RID_SVXPAGE_BASICIDE_OPTIONS: fnCreate = &SvxBasicIDEOptionsPage::Create; break; +#endif + } + + return fnCreate ? (*fnCreate)( pPage, pController, &rSet ) : nullptr; +} + +namespace { + +struct OptionsMapping_Impl +{ + const char* m_pGroupName; + const char* m_pPageName; + sal_uInt16 m_nPageId; +}; + +} + +OptionsMapping_Impl const OptionsMap_Impl[] = +{ +// GROUP PAGE PAGE-ID + { "ProductName", nullptr, SID_GENERAL_OPTIONS }, + { "ProductName", "UserData", RID_SFXPAGE_GENERAL }, + { "ProductName", "General", OFA_TP_MISC }, + { "ProductName", "View", OFA_TP_VIEW }, + { "ProductName", "Print", RID_SFXPAGE_PRINTOPTIONS }, + { "ProductName", "Paths", RID_SFXPAGE_PATH }, + { "ProductName", "Fonts", RID_SVX_FONT_SUBSTITUTION }, + { "ProductName", "Security", RID_SVXPAGE_INET_SECURITY }, + { "ProductName", "Personalization", RID_SVXPAGE_PERSONALIZATION }, + { "ProductName", "Appearance", RID_SVXPAGE_COLORCONFIG }, + { "ProductName", "Accessibility", RID_SVXPAGE_ACCESSIBILITYCONFIG }, + { "ProductName", "Java", RID_SVXPAGE_OPTIONS_JAVA }, + { "ProductName", "BasicIDEOptions", RID_SVXPAGE_BASICIDE_OPTIONS }, + { "ProductName", "OnlineUpdate", RID_SVXPAGE_ONLINEUPDATE }, + { "LanguageSettings", nullptr, SID_LANGUAGE_OPTIONS }, + { "LanguageSettings", "Languages", OFA_TP_LANGUAGES }, + { "LanguageSettings", "WritingAids", RID_SFXPAGE_LINGU }, + { "LanguageSettings", "SearchingInJapanese", RID_SVXPAGE_JSEARCH_OPTIONS }, + { "LanguageSettings", "AsianLayout", RID_SVXPAGE_ASIAN_LAYOUT }, + { "LanguageSettings", "ComplexTextLayout", RID_SVXPAGE_OPTIONS_CTL }, + { "Internet", nullptr, SID_INET_DLG }, + { "Internet", "Proxy", RID_SVXPAGE_INET_PROXY }, + { "Internet", "Email", RID_SVXPAGE_INET_MAIL }, + { "LoadSave", nullptr, SID_FILTER_DLG }, + { "LoadSave", "General", RID_SFXPAGE_SAVE }, + { "LoadSave", "VBAProperties", SID_OPTFILTER_MSOFFICE }, + { "LoadSave", "MicrosoftOffice", RID_OFAPAGE_MSFILTEROPT2 }, + { "LoadSave", "HTMLCompatibility", RID_OFAPAGE_HTMLOPT }, + { "Writer", nullptr, SID_SW_EDITOPTIONS }, + { "Writer", "General", RID_SW_TP_OPTLOAD_PAGE }, + { "Writer", "View", RID_SW_TP_CONTENT_OPT }, + { "Writer", "FormattingAids", RID_SW_TP_OPTSHDWCRSR }, + { "Writer", "Grid", RID_SVXPAGE_GRID }, + { "Writer", "BasicFontsWestern", RID_SW_TP_STD_FONT }, + { "Writer", "BasicFontsAsian", RID_SW_TP_STD_FONT_CJK }, + { "Writer", "BasicFontsCTL", RID_SW_TP_STD_FONT_CTL }, + { "Writer", "Print", RID_SW_TP_OPTPRINT_PAGE }, + { "Writer", "Table", RID_SW_TP_OPTTABLE_PAGE }, + { "Writer", "Changes", RID_SW_TP_REDLINE_OPT }, + { "Writer", "Comparison", RID_SW_TP_COMPARISON_OPT }, + { "Writer", "Compatibility", RID_SW_TP_OPTCOMPATIBILITY_PAGE }, + { "Writer", "AutoCaption", RID_SW_TP_OPTCAPTION_PAGE }, + { "Writer", "MailMerge", RID_SW_TP_MAILCONFIG }, + { "WriterWeb", nullptr, SID_SW_ONLINEOPTIONS }, + { "WriterWeb", "View", RID_SW_TP_HTML_CONTENT_OPT }, + { "WriterWeb", "FormattingAids", RID_SW_TP_HTML_OPTSHDWCRSR }, + { "WriterWeb", "Grid", RID_SW_TP_HTML_OPTGRID_PAGE }, + { "WriterWeb", "Print", RID_SW_TP_HTML_OPTPRINT_PAGE }, + { "WriterWeb", "Table", RID_SW_TP_HTML_OPTTABLE_PAGE }, + { "WriterWeb", "Background", RID_SW_TP_BACKGROUND }, + { "Math", nullptr, SID_SM_EDITOPTIONS }, + { "Math", "Settings", SID_SM_TP_PRINTOPTIONS }, + { "Calc", nullptr, SID_SC_EDITOPTIONS }, + { "Calc", "General", SID_SC_TP_LAYOUT }, + { "Calc", "View", SID_SC_TP_CONTENT }, + { "Calc", "Calculate", SID_SC_TP_CALC }, + { "Calc", "Formula", SID_SC_TP_FORMULA }, + { "Calc", "SortLists", SID_SC_TP_USERLISTS }, + { "Calc", "Changes", SID_SC_TP_CHANGES }, + { "Calc", "Compatibility", SID_SC_TP_COMPATIBILITY }, + { "Calc", "Grid", SID_SC_TP_GRID }, + { "Calc", "Print", RID_SC_TP_PRINT }, + { "Impress", nullptr, SID_SD_EDITOPTIONS }, + { "Impress", "General", SID_SI_TP_MISC }, + { "Impress", "View", SID_SI_TP_CONTENTS }, + { "Impress", "Grid", SID_SI_TP_SNAP }, + { "Impress", "Print", SID_SI_TP_PRINT }, + { "Draw", nullptr, SID_SD_GRAPHIC_OPTIONS }, + { "Draw", "General", SID_SD_TP_MISC }, + { "Draw", "View", SID_SD_TP_CONTENTS }, + { "Draw", "Grid", SID_SD_TP_SNAP }, + { "Draw", "Print", SID_SD_TP_PRINT }, + { "Charts", nullptr, SID_SCH_EDITOPTIONS }, + { "Charts", "DefaultColors", RID_OPTPAGE_CHART_DEFCOLORS }, + { "Base", nullptr, SID_SB_STARBASEOPTIONS }, + { "Base", "Connections", SID_SB_CONNECTIONPOOLING }, + { "Base", "Databases", SID_SB_DBREGISTEROPTIONS }, + { nullptr, nullptr, 0 } +}; + +static bool lcl_getStringFromID( sal_uInt16 _nPageId, OUString& _rGroupName, OUString& _rPageName ) +{ + bool bRet = false; + + sal_uInt16 nIdx = 0; + while ( OptionsMap_Impl[nIdx].m_pGroupName != nullptr ) + { + if ( _nPageId == OptionsMap_Impl[nIdx].m_nPageId ) + { + bRet = true; + _rGroupName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pGroupName ); + if ( OptionsMap_Impl[nIdx].m_pPageName != nullptr ) + _rPageName = OUString::createFromAscii( OptionsMap_Impl[nIdx].m_pPageName ); + break; + } + ++nIdx; + } + + return bRet; +} + +static bool lcl_isOptionHidden( sal_uInt16 _nPageId, const SvtOptionsDialogOptions& _rOptOptions ) +{ + bool bIsHidden = false; + OUString sGroupName, sPageName; + if ( lcl_getStringFromID( _nPageId, sGroupName, sPageName ) ) + { + if ( sPageName.isEmpty() ) + bIsHidden = _rOptOptions.IsGroupHidden( sGroupName ); + else + bIsHidden = _rOptOptions.IsPageHidden( sPageName, sGroupName ); + } + return bIsHidden; +} + +struct OptionsPageInfo +{ + std::unique_ptr<SfxTabPage> m_xPage; + sal_uInt16 m_nPageId; + OUString m_sPageURL; + OUString m_sEventHdl; + std::unique_ptr<ExtensionsTabPage> m_xExtPage; + + explicit OptionsPageInfo( sal_uInt16 nId ) : m_nPageId( nId ) {} +}; + +struct OptionsGroupInfo +{ + std::optional<SfxItemSet> m_pInItemSet; + std::unique_ptr<SfxItemSet> m_pOutItemSet; + SfxShell* m_pShell; // used to create the page + SfxModule* m_pModule; // used to create the ItemSet + sal_uInt16 m_nDialogId; // Id of the former dialog + + OptionsGroupInfo( SfxShell* pSh, SfxModule* pMod, sal_uInt16 nId ) : + m_pShell( pSh ), + m_pModule( pMod ), m_nDialogId( nId ) {} +}; + +#define INI_LIST() \ + , m_pParent ( pParent )\ + , sTitle ( m_xDialog->get_title() )\ + , bForgetSelection ( false )\ + , bIsFromExtensionManager( false ) \ + , bIsForSetDocumentLanguage( false ) \ + , bNeedsRestart ( false ) \ + , eRestartReason( svtools::RESTART_REASON_NONE ) + +void OfaTreeOptionsDialog::InitWidgets() +{ + xOkPB = m_xBuilder->weld_button("ok"); + xApplyPB = m_xBuilder->weld_button("apply"); + xBackPB = m_xBuilder->weld_button("revert"); + xTreeLB = m_xBuilder->weld_tree_view("pages"); + xTabBox = m_xBuilder->weld_container("box"); + Size aSize(xTreeLB->get_approximate_digit_width() * 82, xTreeLB->get_height_rows(30)); +#if HAVE_FEATURE_GPGME + // tdf#115015: make enough space for crypto settings (approx. 14 text edits + padding) + aSize.setHeight((weld::GetMinimumEditHeight() + 6) * 14); +#endif + xTabBox->set_size_request(aSize.Width(), aSize.Height()); + xTreeLB->set_size_request(xTreeLB->get_approximate_digit_width() * 35, aSize.Height()); +} + +// Ctor() with Frame ----------------------------------------------------- +OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, const Reference< XFrame >& _xFrame, bool bActivateLastSelection) + : SfxOkDialogController(pParent, "cui/ui/optionsdialog.ui", "OptionsDialog") + INI_LIST() +{ + InitWidgets(); + + InitTreeAndHandler(); + Initialize( _xFrame ); + LoadExtensionOptions( u"" ); + if (bActivateLastSelection) + ActivateLastSelection(); + + xTreeLB->set_accessible_name(m_xDialog->get_title()); +} + +// Ctor() with ExtensionId ----------------------------------------------- +OfaTreeOptionsDialog::OfaTreeOptionsDialog(weld::Window* pParent, std::u16string_view rExtensionId) + : SfxOkDialogController(pParent, "cui/ui/optionsdialog.ui", "OptionsDialog") + INI_LIST() +{ + InitWidgets(); + + bIsFromExtensionManager = ( !rExtensionId.empty() ); + InitTreeAndHandler(); + LoadExtensionOptions( rExtensionId ); + ActivateLastSelection(); +} + +OfaTreeOptionsDialog::~OfaTreeOptionsDialog() +{ + xCurrentPageEntry.reset(); + + std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + // first children + while (bEntry) + { + // if Child (has parent), then OptionsPageInfo + if (xTreeLB->get_iter_depth(*xEntry)) + { + OptionsPageInfo *pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry)); + if(pPageInfo->m_xPage) + { + pPageInfo->m_xPage->FillUserData(); + OUString aPageData(pPageInfo->m_xPage->GetUserData()); + if ( !aPageData.isEmpty() ) + { + SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) ); + SetViewOptUserItem( aTabPageOpt, aPageData ); + } + pPageInfo->m_xPage.reset(); + } + + if (pPageInfo->m_nPageId == RID_SFXPAGE_LINGU) + { + // write personal dictionaries + Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); + if (xDicList.is()) + { + linguistic::SaveDictionaries( xDicList ); + } + } + + pPageInfo->m_xExtPage.reset(); + + delete pPageInfo; + } + bEntry = xTreeLB->iter_next(*xEntry); + } + + // and parents + bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + { + OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xEntry)); + delete pGroupInfo; + } + bEntry = xTreeLB->iter_next(*xEntry); + } + deleteGroupNames(); +} + +OptionsPageInfo* OfaTreeOptionsDialog::AddTabPage( + sal_uInt16 nId, const OUString& rPageName, sal_uInt16 nGroup ) +{ + std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(); + if (!xTreeLB->get_iter_first(*xParent)) + return nullptr; + xTreeLB->iter_nth_sibling(*xParent, nGroup); + + OptionsPageInfo* pPageInfo = new OptionsPageInfo( nId ); + OUString sId(weld::toId(pPageInfo)); + xTreeLB->insert(xParent.get(), -1, &rPageName, &sId, nullptr, nullptr, false, nullptr); + return pPageInfo; +} + +// the ItemSet* is passed on to the dialog's ownership +sal_uInt16 OfaTreeOptionsDialog::AddGroup(const OUString& rGroupName, + SfxShell* pCreateShell, + SfxModule* pCreateModule, + sal_uInt16 nDialogId ) +{ + OptionsGroupInfo* pInfo = + new OptionsGroupInfo( pCreateShell, pCreateModule, nDialogId ); + OUString sId(weld::toId(pInfo)); + xTreeLB->append(sId, rGroupName); + + sal_uInt16 nRet = 0; + std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + nRet++; + bEntry = xTreeLB->iter_next(*xEntry); + } + return nRet - 1; +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, ShowPageHdl_Impl, weld::TreeView&, void) +{ + SelectHdl_Impl(); +} + +void OfaTreeOptionsDialog::ResetCurrentPageFromConfig() +{ + if (!(xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry))) + return; + + OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry)); + if (pPageInfo->m_xPage) + { + std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xCurrentPageEntry.get()); + xTreeLB->iter_parent(*xParent); + OptionsGroupInfo* pGroupInfo = + weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent)); + pPageInfo->m_xPage->Reset( &*pGroupInfo->m_pInItemSet ); + } + else if ( pPageInfo->m_xExtPage ) + pPageInfo->m_xExtPage->ResetPage(); +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, BackHdl_Impl, weld::Button&, void) +{ + ResetCurrentPageFromConfig(); +} + +void OfaTreeOptionsDialog::ApplyOptions() +{ + std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (xTreeLB->get_iter_depth(*xEntry)) + { + OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry)); + if ( pPageInfo->m_xPage && !pPageInfo->m_xPage->HasExchangeSupport() ) + { + std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xEntry.get()); + xTreeLB->iter_parent(*xParent); + OptionsGroupInfo* pGroupInfo = + weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent)); + pPageInfo->m_xPage->FillItemSet(pGroupInfo->m_pOutItemSet.get()); + } + + if ( pPageInfo->m_xExtPage ) + { + pPageInfo->m_xExtPage->DeactivatePage(); + pPageInfo->m_xExtPage->SavePage(); + } + if ( pPageInfo->m_xPage && RID_OPTPAGE_CHART_DEFCOLORS == pPageInfo->m_nPageId ) + { + SvxDefaultColorOptPage* pPage = static_cast<SvxDefaultColorOptPage *>(pPageInfo->m_xPage.get()); + pPage->SaveChartOptions(); + } + } + bEntry = xTreeLB->iter_next(*xEntry); + } +} + +IMPL_LINK_NOARG(OfaTreeOptionsDialog, HelpHdl_Impl, weld::Widget&, bool) +{ + Help* pHelp = Application::GetHelp(); + if (pHelp && xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + { + OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry)); + if (pPageInfo->m_xPage) + { + OString sHelpId(pPageInfo->m_xPage->GetHelpId()); + pHelp->Start(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), m_xDialog.get()); + return false; + } + } + return true; +} + +IMPL_LINK(OfaTreeOptionsDialog, ApplyHdl_Impl, weld::Button&, rButton, void) +{ + bool bOkPressed = &rButton == xOkPB.get(); + + OptionsGroupInfo* pGroupInfo = nullptr; + + if (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + { + OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry)); + if ( pPageInfo->m_xPage ) + { + std::unique_ptr<weld::TreeIter> xParent = xTreeLB->make_iterator(xCurrentPageEntry.get()); + xTreeLB->iter_parent(*xParent); + + pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent)); + if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId + && pPageInfo->m_xPage->HasExchangeSupport() ) + { + DeactivateRC nLeave = pPageInfo->m_xPage->DeactivatePage(pGroupInfo->m_pOutItemSet.get()); + if ( nLeave == DeactivateRC::KeepPage ) + { + // the page mustn't be left, so return early + assert(xTreeLB->is_selected(*xCurrentPageEntry)); // presumably this must be true here + if (bOkPressed) + return; + } + } + } + } + + ApplyOptions(); + ApplyItemSets(); + utl::ConfigManager::storeConfigItems(); + + if (bOkPressed) + m_xDialog->response(RET_OK); + else + { + // tdf#137930 rebuild the in and out itemsets to reflect the current + // post-apply state + if (pGroupInfo && pGroupInfo->m_pInItemSet) + { + // tdf#138596 seeing as the SfxTabPages keep pointers to the m_pInItemSet + // we update the contents of the existing SfxItemSets to match + // the current settings, rather than create new ones + auto xInItemSet = pGroupInfo->m_pShell + ? pGroupInfo->m_pShell->CreateItemSet( pGroupInfo->m_nDialogId ) + : CreateItemSet( pGroupInfo->m_nDialogId ); + pGroupInfo->m_pInItemSet->Set(*xInItemSet, false); + pGroupInfo->m_pOutItemSet->ClearItem(); + } + + // for the Apply case, now that the settings are saved to config, + // reload the current page so it knows what the config now states + ResetCurrentPageFromConfig(); + // reselect it to undo possible DeactivatePage above + xCurrentPageEntry.reset(); + SelectHdl_Impl(); + } + + if (!bNeedsRestart) + return; + + SolarMutexGuard aGuard; + weld::Window* pParent; + if (!bOkPressed) + pParent = m_xDialog.get(); + else + { + m_xDialog->hide(); + pParent = m_pParent; + } + bool bRestart = ::svtools::executeRestartDialog(comphelper::getProcessComponentContext(), + pParent, eRestartReason); + if (bRestart && !bOkPressed) + m_xDialog->response(RET_OK); +} + +void OfaTreeOptionsDialog::ApplyItemSets() +{ + std::unique_ptr<weld::TreeIter> xEntry = xTreeLB->make_iterator(); + bool bEntry = xTreeLB->get_iter_first(*xEntry); + while (bEntry) + { + if (!xTreeLB->get_iter_depth(*xEntry)) + { + OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xEntry)); + if(pGroupInfo->m_pOutItemSet) + { + if(pGroupInfo->m_pShell) + pGroupInfo->m_pShell->ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet); + else + ApplyItemSet( pGroupInfo->m_nDialogId, *pGroupInfo->m_pOutItemSet); + } + } + bEntry = xTreeLB->iter_next(*xEntry); + } +} + +void OfaTreeOptionsDialog::InitTreeAndHandler() +{ + xTreeLB->set_help_id(HID_OFADLG_TREELISTBOX); + xTreeLB->connect_changed( LINK( this, OfaTreeOptionsDialog, ShowPageHdl_Impl ) ); + xBackPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, BackHdl_Impl ) ); + xApplyPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, ApplyHdl_Impl ) ); + xOkPB->connect_clicked( LINK( this, OfaTreeOptionsDialog, ApplyHdl_Impl ) ); + m_xDialog->connect_help( LINK( this, OfaTreeOptionsDialog, HelpHdl_Impl ) ); +} + +void OfaTreeOptionsDialog::ActivatePage( sal_uInt16 nResId ) +{ + bIsForSetDocumentLanguage = false; + if ( nResId == OFA_TP_LANGUAGES_FOR_SET_DOCUMENT_LANGUAGE ) + { + bIsForSetDocumentLanguage = true; + nResId = OFA_TP_LANGUAGES; + } + + DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" ); + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + bForgetSelection = true; + sal_uInt16 nTemp = pLastPageSaver->m_nLastPageId; + pLastPageSaver->m_nLastPageId = nResId; + ActivateLastSelection(); + pLastPageSaver->m_nLastPageId = nTemp; +} + +void OfaTreeOptionsDialog::ActivatePage( const OUString& rPageURL ) +{ + DBG_ASSERT( !bIsFromExtensionManager, "OfaTreeOptionsDialog::ActivatePage(): call from extension manager" ); + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + bForgetSelection = true; + pLastPageSaver->m_nLastPageId = 0; + pLastPageSaver->m_sLastPageURL_Tools = rPageURL; + ActivateLastSelection(); +} + +void OfaTreeOptionsDialog::ActivateLastSelection() +{ + std::unique_ptr<weld::TreeIter> xEntry; + + if (pLastPageSaver) + { + OUString sLastURL = bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr + : pLastPageSaver->m_sLastPageURL_Tools; + if ( sLastURL.isEmpty() ) + { + sLastURL = !bIsFromExtensionManager ? pLastPageSaver->m_sLastPageURL_ExtMgr + : pLastPageSaver->m_sLastPageURL_Tools; + } + + bool bMustExpand = ( INetURLObject( sLastURL ).GetProtocol() == INetProtocol::File ); + + std::unique_ptr<weld::TreeIter> xTemp = xTreeLB->make_iterator(); + bool bTemp = xTreeLB->get_iter_first(*xTemp); + while (bTemp) + { + // restore only selection of a leaf + if (xTreeLB->get_iter_depth(*xTemp) && xTreeLB->get_id(*xTemp).toInt64()) + { + OptionsPageInfo* pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xTemp)); + OUString sPageURL = pPageInfo->m_sPageURL; + if ( bMustExpand ) + { + sPageURL = comphelper::getExpandedUri( + comphelper::getProcessComponentContext(), sPageURL); + } + + if ( ( !bIsFromExtensionManager + && pPageInfo->m_nPageId && pPageInfo->m_nPageId == pLastPageSaver->m_nLastPageId ) + || ( !pPageInfo->m_nPageId && sLastURL == sPageURL ) ) + { + xEntry = xTreeLB->make_iterator(xTemp.get()); + break; + } + } + bTemp = xTreeLB->iter_next(*xTemp); + } + } + + if (!xEntry) + { + xEntry = xTreeLB->make_iterator(); + if (!xTreeLB->get_iter_first(*xEntry) || !xTreeLB->iter_next(*xEntry)) + xEntry.reset(); + } + + if (!xEntry) + return; + + std::unique_ptr<weld::TreeIter> xParent(xTreeLB->make_iterator(xEntry.get())); + xTreeLB->iter_parent(*xParent); + xTreeLB->expand_row(*xParent); + xTreeLB->scroll_to_row(*xParent); + xTreeLB->scroll_to_row(*xEntry); + xTreeLB->set_cursor(*xEntry); + xTreeLB->select(*xEntry); + xTreeLB->grab_focus(); + SelectHdl_Impl(); +} + +void OfaTreeOptionsDialog::InitItemSets(OptionsGroupInfo& rGroupInfo) +{ + if (!rGroupInfo.m_pInItemSet) + rGroupInfo.m_pInItemSet.emplace( rGroupInfo.m_pShell + ? *rGroupInfo.m_pShell->CreateItemSet( rGroupInfo.m_nDialogId ) + : *CreateItemSet( rGroupInfo.m_nDialogId ) ); + if (!rGroupInfo.m_pOutItemSet) + rGroupInfo.m_pOutItemSet = std::make_unique<SfxItemSet>( + *rGroupInfo.m_pInItemSet->GetPool(), + rGroupInfo.m_pInItemSet->GetRanges()); +} + +void OfaTreeOptionsDialog::SelectHdl_Impl() +{ + std::unique_ptr<weld::TreeIter> xEntry(xTreeLB->make_iterator()); + + if (!xTreeLB->get_cursor(xEntry.get())) + return; + + if (xCurrentPageEntry && xCurrentPageEntry->equal(*xEntry)) + return; + + std::unique_ptr<weld::TreeIter> xParent(xTreeLB->make_iterator(xEntry.get())); + bool bParent = xTreeLB->iter_parent(*xParent); + + // If the user has selected a category, automatically switch to a suitable + // default sub-page instead. + if (!bParent) + return; + + BuilderPage* pNewPage = nullptr; + OptionsPageInfo* pOptPageInfo = (xCurrentPageEntry && xTreeLB->get_iter_depth(*xCurrentPageEntry)) + ? weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xCurrentPageEntry)) : nullptr; + + if (pOptPageInfo && pOptPageInfo->m_xPage && pOptPageInfo->m_xPage->IsVisible()) + { + std::unique_ptr<weld::TreeIter> xCurParent(xTreeLB->make_iterator(xCurrentPageEntry.get())); + xTreeLB->iter_parent(*xCurParent); + + OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xCurParent)); + DeactivateRC nLeave = DeactivateRC::LeavePage; + if ( RID_SVXPAGE_COLOR != pOptPageInfo->m_nPageId && pOptPageInfo->m_xPage->HasExchangeSupport() ) + nLeave = pOptPageInfo->m_xPage->DeactivatePage( pGroupInfo->m_pOutItemSet.get() ); + + if ( nLeave == DeactivateRC::KeepPage ) + { + // we cannot leave this page, this is may be from a user clicking a different entry + // in the tree so reselect the current page + xTreeLB->select(*xCurrentPageEntry); + return; + } + else + pOptPageInfo->m_xPage->set_visible(false); + } + else if ( pOptPageInfo && pOptPageInfo->m_xExtPage ) + { + pOptPageInfo->m_xExtPage->Hide(); + pOptPageInfo->m_xExtPage->DeactivatePage(); + } + + OptionsPageInfo *pPageInfo = weld::fromId<OptionsPageInfo*>(xTreeLB->get_id(*xEntry)); + OptionsGroupInfo* pGroupInfo = weld::fromId<OptionsGroupInfo*>(xTreeLB->get_id(*xParent)); + if(!pPageInfo->m_xPage && pPageInfo->m_nPageId > 0) + { + InitItemSets(*pGroupInfo); + + pPageInfo->m_xPage = ::CreateGeneralTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet); + + if(!pPageInfo->m_xPage && pGroupInfo->m_pModule) + pPageInfo->m_xPage = pGroupInfo->m_pModule->CreateTabPage(pPageInfo->m_nPageId, xTabBox.get(), this, *pGroupInfo->m_pInItemSet); + + DBG_ASSERT( pPageInfo->m_xPage, "tabpage could not created"); + if ( pPageInfo->m_xPage ) + { + SvtViewOptions aTabPageOpt( EViewType::TabPage, OUString::number( pPageInfo->m_nPageId) ); + pPageInfo->m_xPage->SetUserData( GetViewOptUserItem( aTabPageOpt ) ); + pPageInfo->m_xPage->Reset( &*pGroupInfo->m_pInItemSet ); + } + } + else if ( 0 == pPageInfo->m_nPageId && !pPageInfo->m_xExtPage ) + { + if ( !m_xContainerWinProvider.is() ) + { + m_xContainerWinProvider = awt::ContainerWindowProvider::create( ::comphelper::getProcessComponentContext() ); + } + + pPageInfo->m_xExtPage = std::make_unique<ExtensionsTabPage>( + xTabBox.get(), pPageInfo->m_sPageURL, pPageInfo->m_sEventHdl, m_xContainerWinProvider); + } + + if ( pPageInfo->m_xPage ) + { + if ( RID_SVXPAGE_COLOR != pPageInfo->m_nPageId && + pPageInfo->m_xPage->HasExchangeSupport()) + { + pPageInfo->m_xPage->ActivatePage(*pGroupInfo->m_pOutItemSet); + } + pPageInfo->m_xPage->set_visible(true); + } + else if ( pPageInfo->m_xExtPage ) + { + pPageInfo->m_xExtPage->Show(); + pPageInfo->m_xExtPage->ActivatePage(); + } + + { + OUString sTitleText = sTitle + + " - " + xTreeLB->get_text(*xParent) + + " - " + xTreeLB->get_text(*xEntry); + m_xDialog->set_title(sTitleText); + } + + xCurrentPageEntry = std::move(xEntry); + + if ( !bForgetSelection ) + { + if ( !pLastPageSaver ) + pLastPageSaver = new LastPageSaver; + if ( !bIsFromExtensionManager ) + pLastPageSaver->m_nLastPageId = pPageInfo->m_nPageId; + if ( pPageInfo->m_xExtPage ) + { + if ( bIsFromExtensionManager ) + pLastPageSaver->m_sLastPageURL_ExtMgr = pPageInfo->m_sPageURL; + else + pLastPageSaver->m_sLastPageURL_Tools = pPageInfo->m_sPageURL; + } + } + pNewPage = pPageInfo->m_xPage.get(); + + // fdo#58170 use current page's layout child HelpId, unless there isn't a current page + OString sHelpId(pNewPage ? pNewPage->GetHelpId() : OString()); + if (sHelpId.isEmpty()) + sHelpId = HID_OFADLG_TREELISTBOX; + xTreeLB->set_help_id(sHelpId); +} + +std::optional<SfxItemSet> OfaTreeOptionsDialog::CreateItemSet( sal_uInt16 nId ) +{ + Reference< XLinguProperties > xProp( LinguMgr::GetLinguPropertySet() ); + std::optional<SfxItemSet> pRet; + switch(nId) + { + case SID_GENERAL_OPTIONS: + { + pRet.emplace( + SfxGetpApp()->GetPool(), + svl::Items< + SID_HTML_MODE, SID_HTML_MODE, + SID_ATTR_METRIC, SID_ATTR_METRIC, + SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK, + SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER, + SID_ATTR_YEAR2000, SID_ATTR_YEAR2000> ); + + SfxItemSetFixed<SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER> aOptSet( SfxGetpApp()->GetPool() ); + SfxApplication::GetOptions(aOptSet); + pRet->Put(aOptSet); + + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + const SfxUInt16Item* pItem = nullptr; + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + + // miscellaneous - Year2000 + if( SfxItemState::DEFAULT <= pDispatch->QueryState( SID_ATTR_YEAR2000, pItem ) ) + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, pItem->GetValue() ) ); + else + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, officecfg::Office::Common::DateFormat::TwoDigitYear::get() ) ); + } + else + pRet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, officecfg::Office::Common::DateFormat::TwoDigitYear::get() ) ); + + + // miscellaneous - Tabulator + pRet->Put(SfxBoolItem(SID_PRINTER_NOTFOUND_WARN, officecfg::Office::Common::Print::Warning::NotFound::get())); + + SfxPrinterChangeFlags nFlag = officecfg::Office::Common::Print::Warning::PaperSize::get() ? SfxPrinterChangeFlags::CHG_SIZE : SfxPrinterChangeFlags::NONE; + nFlag |= officecfg::Office::Common::Print::Warning::PaperOrientation::get() ? SfxPrinterChangeFlags::CHG_ORIENTATION : SfxPrinterChangeFlags::NONE; + pRet->Put( SfxFlagItem( SID_PRINTER_CHANGESTODOC, static_cast<int>(nFlag) )); + + } + break; + case SID_LANGUAGE_OPTIONS : + { + pRet.emplace( + SfxGetpApp()->GetPool(), + svl::Items< + SID_ATTR_CHAR_CJK_LANGUAGE, SID_ATTR_CHAR_CJK_LANGUAGE, + SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_LANGUAGE, + SID_SET_DOCUMENT_LANGUAGE, SID_SET_DOCUMENT_LANGUAGE, + SID_ATTR_LANGUAGE, SID_ATTR_LANGUAGE, + SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK, + SID_OPT_LOCALE_CHANGED, SID_OPT_LOCALE_CHANGED>); + + // for linguistic + SfxHyphenRegionItem aHyphen( SID_ATTR_HYPHENREGION ); + + sal_Int16 nMinLead = 2, + nMinTrail = 2; + if (xProp.is()) + { + nMinLead = xProp->getHyphMinLeading(); + nMinTrail = xProp->getHyphMinTrailing(); + } + aHyphen.GetMinLead() = static_cast<sal_uInt8>(nMinLead); + aHyphen.GetMinTrail() = static_cast<sal_uInt8>(nMinTrail); + + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + const SvxLanguageItem* pLangItem = nullptr; + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_LANGUAGE, pLangItem)) + pRet->Put(*pLangItem, SID_ATTR_LANGUAGE); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CJK_LANGUAGE, pLangItem)) + pRet->Put(*pLangItem, SID_ATTR_CHAR_CJK_LANGUAGE); + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_ATTR_CHAR_CTL_LANGUAGE, pLangItem)) + pRet->Put(*pLangItem, SID_ATTR_CHAR_CTL_LANGUAGE); + + pRet->Put(aHyphen); + const SfxPoolItem* pItem = nullptr; + if(SfxItemState::DEFAULT <= pDispatch->QueryState(SID_AUTOSPELL_CHECK, pItem)) + { + pRet->Put(std::unique_ptr<SfxPoolItem>(pItem->Clone())); + } + else + { + bool bVal = false; + if (xProp.is()) + { + bVal = xProp->getIsSpellAuto(); + } + + pRet->Put(SfxBoolItem(SID_AUTOSPELL_CHECK, bVal)); + } + } + pRet->Put( SfxBoolItem( SID_SET_DOCUMENT_LANGUAGE, bIsForSetDocumentLanguage ) ); + } + break; + case SID_INET_DLG : + pRet.emplace( SfxGetpApp()->GetPool(), + svl::Items< + //SID_OPTIONS_START - ..END + SID_SAVEREL_INET, SID_SAVEREL_FSYS, + SID_INET_NOPROXY, SID_INET_FTP_PROXY_PORT, + SID_SECURE_URL, SID_SECURE_URL> ); + SfxApplication::GetOptions(*pRet); + break; + case SID_FILTER_DLG: + pRet.emplace( + SfxGetpApp()->GetPool(), + svl::Items< + SID_ATTR_WARNALIENFORMAT, SID_ATTR_WARNALIENFORMAT, + SID_ATTR_DOCINFO, SID_ATTR_AUTOSAVEMINUTE, + SID_SAVEREL_INET, SID_SAVEREL_FSYS, + SID_ATTR_PRETTYPRINTING, SID_ATTR_PRETTYPRINTING> ); + SfxApplication::GetOptions(*pRet); + break; + + case SID_SB_STARBASEOPTIONS: + pRet.emplace( SfxGetpApp()->GetPool(), + svl::Items<SID_SB_POOLING_ENABLED, SID_SB_DB_REGISTER> ); + ::offapp::ConnectionPoolConfig::GetOptions(*pRet); + svx::DbRegisteredNamesConfig::GetOptions(*pRet); + break; + + case SID_SCH_EDITOPTIONS: + { + SvxChartOptions aChartOpt; + pRet.emplace( SfxGetpApp()->GetPool(), svl::Items<SID_SCH_EDITOPTIONS, SID_SCH_EDITOPTIONS> ); + pRet->Put( SvxChartColorTableItem( SID_SCH_EDITOPTIONS, aChartOpt.GetDefaultColors() ) ); + break; + } + } + return pRet; +} + +void OfaTreeOptionsDialog::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) +{ + switch(nId) + { + case SID_GENERAL_OPTIONS: + { + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + + SfxItemSetFixed<SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER> aOptSet(SfxGetpApp()->GetPool()); + aOptSet.Put(rSet); + if(aOptSet.Count()) + SfxGetpApp()->SetOptions( aOptSet ); + // get dispatcher anew, because SetOptions() might have destroyed the dispatcher + SfxViewFrame *pViewFrame = SfxViewFrame::Current(); + +// evaluate Year2000 + sal_uInt16 nY2K = USHRT_MAX; + const SfxUInt16Item* pYearItem = rSet.GetItemIfSet( SID_ATTR_YEAR2000, false ); + if( pYearItem ) + nY2K = pYearItem->GetValue(); + if( USHRT_MAX != nY2K ) + { + if ( pViewFrame ) + { + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + pDispatch->ExecuteList(SID_ATTR_YEAR2000, + SfxCallMode::ASYNCHRON, { pYearItem }); + } + officecfg::Office::Common::DateFormat::TwoDigitYear::set(nY2K, batch); + } + +// evaluate print + if(const SfxBoolItem* pWarnItem = rSet.GetItemIfSet(SID_PRINTER_NOTFOUND_WARN, false)) + officecfg::Office::Common::Print::Warning::NotFound::set(pWarnItem->GetValue(), batch); + + if(const SfxFlagItem* pFlag = rSet.GetItemIfSet(SID_PRINTER_CHANGESTODOC, false)) + { + bool bPaperSizeWarning = bool(static_cast<SfxPrinterChangeFlags>(pFlag->GetValue()) & SfxPrinterChangeFlags::CHG_SIZE); + officecfg::Office::Common::Print::Warning::PaperSize::set(bPaperSizeWarning, batch); + bool bPaperOrientationWarning = bool(static_cast<SfxPrinterChangeFlags>(pFlag->GetValue()) & SfxPrinterChangeFlags::CHG_ORIENTATION); + officecfg::Office::Common::Print::Warning::PaperOrientation::set(bPaperOrientationWarning, batch); + } + +// evaluate help options + bool bHelpTips = officecfg::Office::Common::Help::Tip::get(); + if ( bHelpTips != Help::IsQuickHelpEnabled() ) + bHelpTips ? Help::EnableQuickHelp() : Help::DisableQuickHelp(); + bool bExtendedHelp = officecfg::Office::Common::Help::ExtendedTip::get(); + if ( bExtendedHelp != Help::IsBalloonHelpEnabled() ) + bExtendedHelp ? Help::EnableBalloonHelp() : Help::DisableBalloonHelp(); + + batch->commit(); + } + break; + case SID_LANGUAGE_OPTIONS : + { + OfaTreeOptionsDialog::ApplyLanguageOptions(rSet); + } + break; + case SID_INET_DLG : + case SID_FILTER_DLG: + SfxGetpApp()->SetOptions( rSet ); + break; + + case SID_SB_STARBASEOPTIONS: + ::offapp::ConnectionPoolConfig::SetOptions( rSet ); + svx::DbRegisteredNamesConfig::SetOptions(rSet); + break; + + case SID_SCH_EDITOPTIONS: + // nothing to do. Chart options only apply to newly created charts + break; + + default: + { + OSL_FAIL( "Unhandled option in ApplyItemSet" ); + } + break; + } + +} +void OfaTreeOptionsDialog::ApplyLanguageOptions(const SfxItemSet& rSet) +{ + bool bSaveSpellCheck = false; + const SfxPoolItem* pItem = nullptr; + + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + Reference< XLinguProperties > xProp = LinguProperties::create( xContext ); + if ( const SfxHyphenRegionItem* pHyphenItem = rSet.GetItemIfSet(SID_ATTR_HYPHENREGION, false ) ) + { + xProp->setHyphMinLeading( static_cast<sal_Int16>(pHyphenItem->GetMinLead()) ); + xProp->setHyphMinTrailing( static_cast<sal_Int16>(pHyphenItem->GetMinTrail()) ); + bSaveSpellCheck = true; + } + + SfxViewFrame *pViewFrame = SfxViewFrame::Current(); + if ( pViewFrame ) + { + SfxDispatcher* pDispatch = pViewFrame->GetDispatcher(); + pItem = nullptr; + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CTL_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + if(SfxItemState::SET == rSet.GetItemState( SID_ATTR_CHAR_CJK_LANGUAGE, false, &pItem )) + { + pDispatch->ExecuteList(pItem->Which(), SfxCallMode::SYNCHRON, { pItem }); + bSaveSpellCheck = true; + } + + if( SfxItemState::SET == rSet.GetItemState(SID_AUTOSPELL_CHECK, false, &pItem )) + { + bool bOnlineSpelling = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + pDispatch->ExecuteList(SID_AUTOSPELL_CHECK, + SfxCallMode::ASYNCHRON|SfxCallMode::RECORD, { pItem }); + + xProp->setIsSpellAuto( bOnlineSpelling ); + } + + if( bSaveSpellCheck ) + { + //! the config item has changed since we modified the + //! property set it uses + pDispatch->Execute(SID_SPELLCHECKER_CHANGED, SfxCallMode::ASYNCHRON); + } + } + + if( SfxItemState::SET == rSet.GetItemState(SID_OPT_LOCALE_CHANGED, false, &pItem )) + { + SfxViewFrame* _pViewFrame = SfxViewFrame::GetFirst(); + while ( _pViewFrame ) + { + _pViewFrame->GetDispatcher()->ExecuteList(pItem->Which(), + SfxCallMode::ASYNCHRON, { pItem }); + _pViewFrame = SfxViewFrame::GetNext( *_pViewFrame ); + } + } +} + +static OUString getCurrentFactory_Impl( const Reference< XFrame >& _xFrame ) +{ + OUString sIdentifier; + Reference < XFrame > xCurrentFrame( _xFrame ); + Reference < XModuleManager2 > xModuleManager = ModuleManager::create(::comphelper::getProcessComponentContext()); + if ( !xCurrentFrame.is() ) + { + Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() ); + xCurrentFrame = xDesktop->getCurrentFrame(); + } + + if ( xCurrentFrame.is() ) + { + try + { + sIdentifier = xModuleManager->identify( xCurrentFrame ); + } + catch ( css::frame::UnknownModuleException& ) + { + SAL_INFO( "cui.options", "unknown module" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "getActiveModule_Impl(): exception of XModuleManager::identify()" ); + } + } + + return sIdentifier; +} + +void OfaTreeOptionsDialog::Initialize( const Reference< XFrame >& _xFrame ) +{ + sal_uInt16 nGroup = 0; + + SvtOptionsDialogOptions aOptionsDlgOpt; + sal_uInt16 nPageId; + + // %PRODUCTNAME options + if ( !lcl_isOptionHidden( SID_GENERAL_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName(u"ProductName", CuiResId(SID_GENERAL_OPTIONS_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_GENERAL_OPTIONS_RES[0].first), nullptr, nullptr, SID_GENERAL_OPTIONS ); + const sal_uInt16 nEnd = static_cast<sal_uInt16>(std::size(SID_GENERAL_OPTIONS_RES)); + + for (sal_uInt16 i = 1; i < nEnd; ++i) + { + OUString sNewTitle = CuiResId(SID_GENERAL_OPTIONS_RES[i].first); + nPageId = SID_GENERAL_OPTIONS_RES[i].second; + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + // Disable Online Update page if service not installed + if( RID_SVXPAGE_ONLINEUPDATE == nPageId ) + { + try + { + Reference < XInterface > xService( setup::UpdateCheck::create( ::comphelper::getProcessComponentContext() ) ); + if( ! xService.is() ) + continue; + } + catch ( css::uno::DeploymentException& ) + { + continue; + } + } + + // Disable Basic IDE options, if experimental features are not enabled + if( RID_SVXPAGE_BASICIDE_OPTIONS == nPageId ) + { + if( ! officecfg::Office::Common::Misc::ExperimentalMode::get() ) + continue; + } + + AddTabPage( nPageId, sNewTitle, nGroup ); + } + } + + // Load and Save options + if ( !lcl_isOptionHidden( SID_FILTER_DLG, aOptionsDlgOpt ) ) + { + setGroupName( u"LoadSave", CuiResId(SID_FILTER_DLG_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_FILTER_DLG_RES[0].first), nullptr, nullptr, SID_FILTER_DLG ); + for ( size_t i = 1; i < std::size(SID_FILTER_DLG_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_FILTER_DLG_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_FILTER_DLG_RES[i].first), nGroup ); + } + } + + // Language options + SvtCTLOptions aCTLLanguageOptions; + if ( !lcl_isOptionHidden( SID_LANGUAGE_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName(u"LanguageSettings", CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_LANGUAGE_OPTIONS_RES[0].first), nullptr, nullptr, SID_LANGUAGE_OPTIONS ); + for (size_t i = 1; i < std::size(SID_LANGUAGE_OPTIONS_RES); ++i) + { + nPageId = static_cast<sal_uInt16>(SID_LANGUAGE_OPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + if ( ( RID_SVXPAGE_JSEARCH_OPTIONS != nPageId || SvtCJKOptions::IsJapaneseFindEnabled() ) && + ( RID_SVXPAGE_ASIAN_LAYOUT != nPageId || SvtCJKOptions::IsAsianTypographyEnabled() ) && + ( RID_SVXPAGE_OPTIONS_CTL != nPageId || aCTLLanguageOptions.IsCTLFontEnabled() ) ) + AddTabPage(nPageId, CuiResId(SID_LANGUAGE_OPTIONS_RES[i].first), nGroup); + } + } + + OUString aFactory = getCurrentFactory_Impl( _xFrame ); + DBG_ASSERT( GetModuleIdentifier( _xFrame ) == aFactory, "S H I T!!!" ); + + // Writer and Writer/Web options + SvtModuleOptions aModuleOpt; + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) ) + { + // text document + if ( aFactory == "com.sun.star.text.TextDocument" + || aFactory == "com.sun.star.text.WebDocument" + || aFactory == "com.sun.star.text.GlobalDocument" ) + { + SfxModule* pSwMod = SfxApplication::GetModule(SfxToolsModule::Writer); + if ( !lcl_isOptionHidden( SID_SW_EDITOPTIONS, aOptionsDlgOpt ) ) + { + if ( aFactory == "com.sun.star.text.WebDocument" ) + setGroupName( u"WriterWeb", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) ); + else + setGroupName( u"Writer", CuiResId(SID_SW_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup(CuiResId(SID_SW_EDITOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_EDITOPTIONS ); + for ( size_t i = 1; i < std::size(SID_SW_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SW_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + if ( ( RID_SW_TP_STD_FONT_CJK != nPageId || SvtCJKOptions::IsCJKFontEnabled() ) && + ( RID_SW_TP_STD_FONT_CTL != nPageId || aCTLLanguageOptions.IsCTLFontEnabled() ) && + ( RID_SW_TP_MAILCONFIG != nPageId || MailMergeCfg_Impl().IsEmailSupported() ) ) + AddTabPage( nPageId, CuiResId(SID_SW_EDITOPTIONS_RES[i].first), nGroup ); + } +#ifdef DBG_UTIL + AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup ); +#endif + } + + // HTML documents + if ( !lcl_isOptionHidden( SID_SW_ONLINEOPTIONS, aOptionsDlgOpt ) ) + { + nGroup = AddGroup(CuiResId(SID_SW_ONLINEOPTIONS_RES[0].first), pSwMod, pSwMod, SID_SW_ONLINEOPTIONS ); + for( size_t i = 1; i < std::size(SID_SW_ONLINEOPTIONS_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SW_ONLINEOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage(nPageId, CuiResId(SID_SW_ONLINEOPTIONS_RES[i].first), nGroup); + } +#ifdef DBG_UTIL + AddTabPage( RID_SW_TP_OPTTEST_PAGE, "Internal Test", nGroup ); +#endif + } + } + } + + // Calc options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) ) + { + if ( aFactory == "com.sun.star.sheet.SpreadsheetDocument" ) + { + if ( !lcl_isOptionHidden( SID_SC_EDITOPTIONS, aOptionsDlgOpt ) ) + { + SfxModule* pScMod = SfxApplication::GetModule( SfxToolsModule::Calc ); + setGroupName( u"Calc", CuiResId(SID_SC_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SC_EDITOPTIONS_RES[0].first), pScMod, pScMod, SID_SC_EDITOPTIONS ); + const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SC_EDITOPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SC_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SC_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Impress options + SfxModule* pSdMod = SfxApplication::GetModule( SfxToolsModule::Draw ); + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) ) + { + if ( aFactory == "com.sun.star.presentation.PresentationDocument" ) + { + if ( !lcl_isOptionHidden( SID_SD_EDITOPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( u"Impress", CuiResId(SID_SD_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SD_EDITOPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_EDITOPTIONS ); + const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SD_EDITOPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SD_EDITOPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SD_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Draw options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) ) + { + if ( aFactory == "com.sun.star.drawing.DrawingDocument" ) + { + if ( !lcl_isOptionHidden( SID_SD_GRAPHIC_OPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( u"Draw", CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[0].first), pSdMod, pSdMod, SID_SD_GRAPHIC_OPTIONS ); + const sal_uInt16 nCount = static_cast<sal_uInt16>(std::size(SID_SD_GRAPHIC_OPTIONS_RES)); + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SD_GRAPHIC_OPTIONS_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; + + AddTabPage( nPageId, CuiResId(SID_SD_GRAPHIC_OPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Math options + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::MATH ) ) + { + if ( aFactory == "com.sun.star.formula.FormulaProperties" ) + { + if ( !lcl_isOptionHidden( SID_SM_EDITOPTIONS, aOptionsDlgOpt ) ) + { + SfxModule* pSmMod = SfxApplication::GetModule(SfxToolsModule::Math); + setGroupName( u"Math", CuiResId(SID_SM_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup(CuiResId(SID_SM_EDITOPTIONS_RES[0].first), pSmMod, pSmMod, SID_SM_EDITOPTIONS ); + for ( size_t i = 1; i < std::size(SID_SM_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SM_EDITOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SM_EDITOPTIONS_RES[i].first), nGroup ); + } + } + } + } + + // Database - needed only if there is an application which integrates with databases + if ( !lcl_isOptionHidden( SID_SB_STARBASEOPTIONS, aOptionsDlgOpt ) && + ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) + || aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) + || aModuleOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) + ) ) + { + setGroupName( u"Base", CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SB_STARBASEOPTIONS_RES[0].first), nullptr, nullptr, SID_SB_STARBASEOPTIONS ); + for ( size_t i = 1; i < std::size(SID_SB_STARBASEOPTIONS_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SB_STARBASEOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SB_STARBASEOPTIONS_RES[i].first), nGroup ); + } + } + + // Chart options (always installed and active) + if ( !lcl_isOptionHidden( SID_SCH_EDITOPTIONS, aOptionsDlgOpt ) ) + { + setGroupName( u"Charts", CuiResId(SID_SCH_EDITOPTIONS_RES[0].first) ); + nGroup = AddGroup( CuiResId(SID_SCH_EDITOPTIONS_RES[0].first), nullptr, nullptr, SID_SCH_EDITOPTIONS ); + for ( size_t i = 1; i < std::size(SID_SCH_EDITOPTIONS_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_SCH_EDITOPTIONS_RES[i].second); + if ( !lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + AddTabPage( nPageId, CuiResId(SID_SCH_EDITOPTIONS_RES[i].first), nGroup ); + } + } + + // Internet options + if ( lcl_isOptionHidden( SID_INET_DLG, aOptionsDlgOpt ) ) + return; + + setGroupName(u"Internet", CuiResId(SID_INET_DLG_RES[0].first)); + nGroup = AddGroup(CuiResId(SID_INET_DLG_RES[0].first), nullptr, nullptr, SID_INET_DLG ); + + for ( size_t i = 1; i < std::size(SID_INET_DLG_RES); ++i ) + { + nPageId = static_cast<sal_uInt16>(SID_INET_DLG_RES[i].second); + if ( lcl_isOptionHidden( nPageId, aOptionsDlgOpt ) ) + continue; +#if defined(_WIN32) + // Disable E-mail tab-page on Windows + if ( nPageId == RID_SVXPAGE_INET_MAIL ) + continue; +#endif + AddTabPage( nPageId, CuiResId(SID_INET_DLG_RES[i].first), nGroup ); + } +} + +static bool isNodeActive( OptionsNode const * pNode, Module* pModule ) +{ + if ( !pNode ) + return false; + + // Node for all modules active? + if ( pNode->m_bAllModules ) + return true; + + // OOo-Nodes (Writer, Calc, Impress...) are active if node is already inserted + if ( !getGroupName( pNode->m_sId, false ).isEmpty() ) + return true; + + // no module -> not active + if ( !pModule ) + return false; + + // search node in active module + if ( pModule->m_bActive ) + { + for (auto const& j : pModule->m_aNodeList) + if ( j->m_sId == pNode->m_sId ) + return true; + } + return false; +} + +void OfaTreeOptionsDialog::LoadExtensionOptions( std::u16string_view rExtensionId ) +{ + std::unique_ptr<Module> pModule; + + // when called by Tools - Options then load nodes of active module + if ( rExtensionId.empty() ) + { + pModule = LoadModule( GetModuleIdentifier( Reference< XFrame >() ) ); + } + + VectorOfNodes aNodeList = LoadNodes( pModule.get(), rExtensionId ); + InsertNodes( aNodeList ); +} + +OUString OfaTreeOptionsDialog::GetModuleIdentifier( const Reference< XFrame >& rFrame ) +{ + OUString sModule; + Reference < XFrame > xCurrentFrame( rFrame ); + Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); + Reference < XModuleManager2 > xModuleManager = ModuleManager::create(xContext); + + if ( !xCurrentFrame.is() ) + { + Reference < XDesktop2 > xDesktop = Desktop::create( xContext ); + xCurrentFrame = xDesktop->getCurrentFrame(); + } + + if ( xCurrentFrame.is() ) + { + try + { + sModule = xModuleManager->identify( xCurrentFrame ); + } + catch ( css::frame::UnknownModuleException& ) + { + SAL_INFO( "cui.options", "unknown module" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "OfaTreeOptionsDialog::GetModuleIdentifier(): exception of XModuleManager::identify()"); + } + } + return sModule; +} + +std::unique_ptr<Module> OfaTreeOptionsDialog::LoadModule( + std::u16string_view rModuleIdentifier ) +{ + std::unique_ptr<Module> pModule; + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Modules::get()); + + const Sequence< OUString > seqNames = xSet->getElementNames(); + for ( const OUString& rModule : seqNames ) + { + if ( rModuleIdentifier == rModule ) + { + // current active module found + pModule.reset(new Module); + pModule->m_bActive = true; + + Reference< XNameAccess > xModAccess; + xSet->getByName( rModule ) >>= xModAccess; + if ( xModAccess.is() ) + { + // load the nodes of this module + Reference< XNameAccess > xNodeAccess; + xModAccess->getByName( "Nodes" ) >>= xNodeAccess; + if ( xNodeAccess.is() ) + { + const Sequence< OUString > xTemp = xNodeAccess->getElementNames(); + Reference< XNameAccess > xAccess; + sal_Int32 nIndex = -1; + for ( const OUString& rNode : xTemp) + { + xNodeAccess->getByName( rNode ) >>= xAccess; + if ( xAccess.is() ) + { + xAccess->getByName( "Index" ) >>= nIndex; + if ( nIndex < 0 ) + // append nodes with index < 0 + pModule->m_aNodeList.push_back( + std::unique_ptr<OrderedEntry>(new OrderedEntry(nIndex, rNode))); + else + { + // search position of the node + std::vector<OrderedEntry *>::size_type y = 0; + for ( ; y < pModule->m_aNodeList.size(); ++y ) + { + sal_Int32 nNodeIdx = pModule->m_aNodeList[y]->m_nIndex; + if ( nNodeIdx < 0 || nNodeIdx > nIndex ) + break; + } + // and insert the node on this position + pModule->m_aNodeList.insert( + pModule->m_aNodeList.begin() + y, + std::unique_ptr<OrderedEntry>(new OrderedEntry( nIndex, rNode )) ); + } + } + } + } + } + break; + } + } + return pModule; +} + +VectorOfNodes OfaTreeOptionsDialog::LoadNodes( + Module* pModule, std::u16string_view rExtensionId) +{ + VectorOfNodes aOutNodeList; + + Reference< XNameAccess > xSet( + officecfg::Office::OptionsDialog::Nodes::get()); + VectorOfNodes aNodeList; + const Sequence< OUString > seqNames = xSet->getElementNames(); + + for ( OUString const & sGroupName : seqNames ) + { + Reference< XNameAccess > xNodeAccess; + xSet->getByName( sGroupName ) >>= xNodeAccess; + + if ( xNodeAccess.is() ) + { + OUString sNodeId, sLabel, sPageURL; + bool bAllModules = false; + + sNodeId = sGroupName; + xNodeAccess->getByName( "Label" ) >>= sLabel; + xNodeAccess->getByName( "OptionsPage" ) >>= sPageURL; + xNodeAccess->getByName( "AllModules" ) >>= bAllModules; + + if ( sLabel.isEmpty() ) + sLabel = sGroupName; + OUString sTemp = getGroupName( sLabel, !rExtensionId.empty() ); + if ( !sTemp.isEmpty() ) + sLabel = sTemp; + std::unique_ptr<OptionsNode> pNode(new OptionsNode(sNodeId, sLabel, bAllModules)); + + if ( rExtensionId.empty() && !isNodeActive( pNode.get(), pModule ) ) + { + continue; + } + + Reference< XNameAccess > xLeavesSet; + xNodeAccess->getByName( "Leaves" ) >>= xLeavesSet; + if ( xLeavesSet.is() ) + { + const Sequence< OUString > seqLeaves = xLeavesSet->getElementNames(); + for ( OUString const & leafName : seqLeaves ) + { + Reference< XNameAccess > xLeaveAccess; + xLeavesSet->getByName( leafName ) >>= xLeaveAccess; + + if ( xLeaveAccess.is() ) + { + OUString sId, sLeafLabel, sEventHdl, sLeafURL, sLeafGrpId; + sal_Int32 nLeafGrpIdx = 0; + + xLeaveAccess->getByName( "Id" ) >>= sId; + xLeaveAccess->getByName( "Label" ) >>= sLeafLabel; + xLeaveAccess->getByName( "OptionsPage" ) >>= sLeafURL; + xLeaveAccess->getByName( "EventHandlerService" ) >>= sEventHdl; + xLeaveAccess->getByName( "GroupId" ) >>= sLeafGrpId; + xLeaveAccess->getByName( "GroupIndex" ) >>= nLeafGrpIdx; + + if ( rExtensionId.empty() || sId == rExtensionId ) + { + std::unique_ptr<OptionsLeaf> pLeaf(new OptionsLeaf( + sLeafLabel, sLeafURL, sEventHdl, sLeafGrpId, nLeafGrpIdx )); + + if ( !sLeafGrpId.isEmpty() ) + { + bool bAlreadyOpened = false; + if ( !pNode->m_aGroupedLeaves.empty() ) + { + for (auto & rGroup : pNode->m_aGroupedLeaves) + { + if ( !rGroup.empty() && + rGroup[0]->m_sGroupId == sLeafGrpId ) + { + std::vector<std::unique_ptr<OptionsLeaf>>::size_type l = 0; + for ( ; l < rGroup.size(); ++l ) + { + if ( rGroup[l]->m_nGroupIndex >= nLeafGrpIdx ) + break; + } + rGroup.insert( rGroup.begin() + l, std::move(pLeaf) ); + bAlreadyOpened = true; + break; + } + } + } + if ( !bAlreadyOpened ) + { + std::vector< std::unique_ptr<OptionsLeaf> > aGroupedLeaves; + aGroupedLeaves.push_back( std::move(pLeaf) ); + pNode->m_aGroupedLeaves.push_back( std::move(aGroupedLeaves) ); + } + } + else + pNode->m_aLeaves.push_back( std::move(pLeaf) ); + } + } + } + } + + // do not insert nodes without leaves + if ( !pNode->m_aLeaves.empty() || !pNode->m_aGroupedLeaves.empty() ) + { + pModule ? aNodeList.push_back( std::move(pNode) ) : aOutNodeList.push_back( std::move(pNode) ); + } + } + } + + if ( pModule && !aNodeList.empty() ) + { + for ( auto const & i: pModule->m_aNodeList ) + { + OUString sNodeId = i->m_sId; + for ( auto j = aNodeList.begin(); j != aNodeList.end(); ++j ) + { + if ( (*j)->m_sId == sNodeId ) + { + aOutNodeList.push_back( std::move(*j) ); + aNodeList.erase( j ); + break; + } + } + } + + for ( auto & i: aNodeList ) + aOutNodeList.push_back( std::move(i) ); + } + return aOutNodeList; +} + +static sal_uInt16 lcl_getGroupId( std::u16string_view rGroupName, const weld::TreeView& rTreeLB ) +{ + sal_uInt16 nRet = 0; + + std::unique_ptr<weld::TreeIter> xEntry = rTreeLB.make_iterator(); + bool bEntry = rTreeLB.get_iter_first(*xEntry); + while (bEntry) + { + if (!rTreeLB.get_iter_depth(*xEntry)) + { + OUString sTemp(rTreeLB.get_text(*xEntry)); + if (sTemp == rGroupName) + return nRet; + nRet++; + } + bEntry = rTreeLB.iter_next(*xEntry); + } + + return USHRT_MAX; +} + +static void lcl_insertLeaf( + OfaTreeOptionsDialog* pDlg, OptionsNode const * pNode, OptionsLeaf const * pLeaf, const weld::TreeView& rTreeLB ) +{ + sal_uInt16 nGrpId = lcl_getGroupId( pNode->m_sLabel, rTreeLB ); + if ( USHRT_MAX == nGrpId ) + { + sal_uInt16 nNodeGrpId = getGroupNodeId( pNode->m_sId ); + nGrpId = pDlg->AddGroup( pNode->m_sLabel, nullptr, nullptr, nNodeGrpId ); + } + OptionsPageInfo* pInfo = pDlg->AddTabPage( 0, pLeaf->m_sLabel, nGrpId ); + pInfo->m_sPageURL = pLeaf->m_sPageURL; + pInfo->m_sEventHdl = pLeaf->m_sEventHdl; +} + +void OfaTreeOptionsDialog::InsertNodes( const VectorOfNodes& rNodeList ) +{ + for (auto const& node : rNodeList) + { + if ( !node->m_aLeaves.empty() || !node->m_aGroupedLeaves.empty() ) + { + for ( auto const & j: node->m_aGroupedLeaves ) + { + for ( size_t k = 0; k < j.size(); ++k ) + { + lcl_insertLeaf( this, node.get(), j[k].get(), *xTreeLB ); + } + } + + for ( auto const & j: node->m_aLeaves ) + { + lcl_insertLeaf( this, node.get(), j.get(), *xTreeLB ); + } + } + } +} + +void OfaTreeOptionsDialog::SetNeedsRestart( svtools::RestartReason eReason) +{ + bNeedsRestart = true; + eRestartReason = eReason; +} + +short OfaTreeOptionsDialog::run() +{ + std::unique_ptr< SvxDicListChgClamp > pClamp; + if ( !bIsFromExtensionManager ) + { + // collect all DictionaryList Events while the dialog is executed + Reference<css::linguistic2::XSearchableDictionaryList> xDictionaryList(LinguMgr::GetDictionaryList()); + pClamp.reset( new SvxDicListChgClamp( xDictionaryList ) ); + } + + return SfxOkDialogController::run(); +} + +// class ExtensionsTabPage ----------------------------------------------- +ExtensionsTabPage::ExtensionsTabPage( + weld::Container* pParent, OUString aPageURL, + OUString aEvtHdl, const Reference< awt::XContainerWindowProvider >& rProvider ) + : m_pContainer(pParent) + , m_sPageURL(std::move(aPageURL)) + , m_sEventHdl(std::move(aEvtHdl)) + , m_xWinProvider(rProvider) +{ +} + +ExtensionsTabPage::~ExtensionsTabPage() +{ + Hide(); + DeactivatePage(); + + if ( m_xPage.is() ) + { + try + { + m_xPage->dispose(); + } + catch (const Exception&) + { + } + m_xPage.clear(); + } + + if ( m_xPageParent.is() ) + { + try + { + m_xPageParent->dispose(); + } + catch (const Exception&) + { + } + m_xPageParent.clear(); + } +} + +void ExtensionsTabPage::CreateDialogWithHandler() +{ + try + { + bool bWithHandler = !m_sEventHdl.isEmpty(); + if ( bWithHandler ) + { + Reference < XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + m_xEventHdl.set( xFactory->createInstance( m_sEventHdl ), UNO_QUERY ); + } + + if ( !bWithHandler || m_xEventHdl.is() ) + { + m_xPageParent = m_pContainer->CreateChildFrame(); + Reference<awt::XWindowPeer> xParent(m_xPageParent, UNO_QUERY); + m_xPage = + m_xWinProvider->createContainerWindow( + m_sPageURL, OUString(), xParent, m_xEventHdl ); + + Reference< awt::XControl > xPageControl( m_xPage, UNO_QUERY ); + if ( xPageControl.is() ) + { + Reference< awt::XWindowPeer > xWinPeer( xPageControl->getPeer() ); + if ( xWinPeer.is() ) + { + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWinPeer ); + if ( pWindow ) + pWindow->SetStyle( pWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL ); + } + } + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::CreateDialogWithHandler(): exception of XDialogProvider2::createDialogWithHandler()"); + } +} + +bool ExtensionsTabPage::DispatchAction( const OUString& rAction ) +{ + bool bRet = false; + if ( m_xEventHdl.is() ) + { + try + { + bRet = m_xEventHdl->callHandlerMethod( m_xPage, Any( rAction ), "external_event" ); + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "cui.options", "ExtensionsTabPage::DispatchAction(): exception of XDialogEventHandler::callHandlerMethod()" ); + } + } + return bRet; +} + +void ExtensionsTabPage::Show() +{ + if (!m_xPageParent.is()) + return; + + VclPtr<vcl::Window> xPageParent = VCLUnoHelper::GetWindow(m_xPageParent); + if (xPageParent) + { + // NoActivate otherwise setVisible will call Window::Show which will grab + // focus to the page by default + xPageParent->Show(true, ShowFlags::NoActivate); + } + + m_xPageParent->setVisible(true); +} + +void ExtensionsTabPage::Hide() +{ + if (!m_xPageParent.is()) + return; + m_xPageParent->setVisible(false); +} + +void ExtensionsTabPage::ActivatePage() +{ + if ( !m_xPage.is() ) + { + CreateDialogWithHandler(); + + if ( m_xPage.is() ) + { + auto aWindowRect = m_xPageParent->getPosSize(); + m_xPage->setPosSize(0, 0, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POSSIZE); + if ( !m_sEventHdl.isEmpty() ) + DispatchAction( "initialize" ); + } + } + + if ( m_xPage.is() ) + { + m_xPage->setVisible( true ); + } +} + +void ExtensionsTabPage::DeactivatePage() +{ + if ( m_xPage.is() ) + m_xPage->setVisible( false ); +} + +void ExtensionsTabPage::ResetPage() +{ + DispatchAction( "back" ); + ActivatePage(); +} + +void ExtensionsTabPage::SavePage() +{ + DispatchAction( "ok" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |