diff options
Diffstat (limited to 'cui/source/options/optgdlg.cxx')
-rw-r--r-- | cui/source/options/optgdlg.cxx | 1897 |
1 files changed, 1897 insertions, 0 deletions
diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx new file mode 100644 index 000000000..1972354cc --- /dev/null +++ b/cui/source/options/optgdlg.cxx @@ -0,0 +1,1897 @@ +/* -*- 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 <config_features.h> +#include <config_vclplug.h> +#include <svl/zforlist.hxx> +#include <svl/currencytable.hxx> +#include <svtools/langhelp.hxx> +#include <unotools/lingucfg.hxx> +#if defined(_WIN32) +#include <unotools/resmgr.hxx> +#endif +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <unotools/compatibility.hxx> +#include <unotools/fontoptions.hxx> +#include <svtools/menuoptions.hxx> +#include <svl/languageoptions.hxx> +#include <svtools/miscopt.hxx> +#include <unotools/printwarningoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <sfx2/objsh.hxx> +#include <comphelper/propertysequence.hxx> +#include <svtools/langtab.hxx> +#include <editeng/unolingu.hxx> +#include <editeng/langitem.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/string.hxx> +#include <rtl/ustrbuf.hxx> +#include <editeng/editids.hrc> +#include <svx/svxids.hrc> +#include <svl/intitem.hxx> +#include <svtools/helpopt.hxx> +#include <unotools/searchopt.hxx> +#include <sal/log.hxx> +#include <officecfg/Office/Common.hxx> +#include <officecfg/Setup.hxx> +#include <comphelper/configuration.hxx> +#include <tools/diagnose_ex.h> +#if HAVE_FEATURE_BREAKPAD +#include <desktop/crashreport.hxx> +#endif + +#include <com/sun/star/configuration/theDefaultProvider.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNameReplace.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <com/sun/star/office/Quickstart.hpp> +#include <com/sun/star/linguistic2/XLinguProperties.hpp> + +#include <vcl/vclenum.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <vcl/window.hxx> +#include <vcl/IconThemeInfo.hxx> +#if HAVE_FEATURE_OPENGL +#include <vcl/opengl/OpenGLWrapper.hxx> +#endif +#include <vcl/skia/SkiaHelper.hxx> +#include "optgdlg.hxx" +#include <svtools/apearcfg.hxx> +#include <svtools/optionsdrawinglayer.hxx> +#include <svtools/restartdialog.hxx> +#include <svtools/imgdef.hxx> + +#if defined(_WIN32) +#include <o3tl/char16_t2wchar_t.hxx> +#include <prewin.h> +#include <shobjidl.h> +#include <postwin.h> +#endif +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::util; +using namespace ::utl; + +namespace svt { + +class SkiaCfg +{ +private: + bool mbUseSkia; + bool mbForceSkiaRaster; + bool mbModified; + +public: + SkiaCfg(); + ~SkiaCfg(); + + bool useSkia() const; + bool forceSkiaRaster() const; + + void setUseSkia(bool bSkia); + void setForceSkiaRaster(bool bSkia); + + void reset(); +}; + +SkiaCfg::SkiaCfg(): + mbModified(false) +{ + reset(); +} + +void SkiaCfg::reset() +{ + mbUseSkia = officecfg::Office::Common::VCL::UseSkia::get(); + mbForceSkiaRaster = officecfg::Office::Common::VCL::ForceSkiaRaster::get(); + mbModified = false; +} + +SkiaCfg::~SkiaCfg() +{ + if (!mbModified) + return; + + try + { + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + if (!officecfg::Office::Common::VCL::UseSkia::isReadOnly()) + officecfg::Office::Common::VCL::UseSkia::set(mbUseSkia, batch); + if (!officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()) + officecfg::Office::Common::VCL::ForceSkiaRaster::set(mbForceSkiaRaster, batch); + batch->commit(); + } + catch (...) + { + } +} + +bool SkiaCfg::useSkia() const +{ + return mbUseSkia; +} + +bool SkiaCfg::forceSkiaRaster() const +{ + return mbForceSkiaRaster; +} + +void SkiaCfg::setUseSkia(bool bSkia) +{ + if (bSkia != mbUseSkia) + { + mbUseSkia = bSkia; + mbModified = true; + } +} + +void SkiaCfg::setForceSkiaRaster(bool bSkia) +{ + if (mbForceSkiaRaster != bSkia) + { + mbForceSkiaRaster = bSkia; + mbModified = true; + } +} + +} + +// class OfaMiscTabPage -------------------------------------------------- + +DeactivateRC OfaMiscTabPage::DeactivatePage( SfxItemSet* pSet_ ) +{ + if ( pSet_ ) + FillItemSet( pSet_ ); + return DeactivateRC::LeavePage; +} + +namespace +{ +OUString impl_SystemFileOpenServiceName() +{ + #if defined(_WIN32) + return "com.sun.star.ui.dialogs.SystemFilePicker"; + #elif defined MACOSX + return "com.sun.star.ui.dialogs.AquaFilePicker"; + #else + return OUString(); + #endif +} + +bool lcl_HasSystemFilePicker() +{ + if( Application::hasNativeFileSelection() ) + return true; + + // Otherwise fall-back on querying services + bool bRet = false; + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + + Reference< XContentEnumerationAccess > xEnumAccess( xFactory, UNO_QUERY ); + Reference< XSet > xSet( xFactory, UNO_QUERY ); + + if ( ! xEnumAccess.is() || ! xSet.is() ) + return bRet; + + try + { + OUString aFileService = impl_SystemFileOpenServiceName(); + Reference< XEnumeration > xEnum = xEnumAccess->createContentEnumeration( aFileService ); + if ( xEnum.is() && xEnum->hasMoreElements() ) + bRet = true; + } + catch (const IllegalArgumentException&) + { + } + catch (const ElementExistException&) + { + } + return bRet; +} +} + +OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optgeneralpage.ui", "OptGeneralPage", &rSet) + , m_xExtHelpCB(m_xBuilder->weld_check_button("exthelp")) + , m_xPopUpNoHelpCB(m_xBuilder->weld_check_button("popupnohelp")) + , m_xShowTipOfTheDay(m_xBuilder->weld_check_button("cbShowTipOfTheDay")) + , m_xFileDlgFrame(m_xBuilder->weld_widget("filedlgframe")) + , m_xPrintDlgFrame(m_xBuilder->weld_widget("printdlgframe")) + , m_xFileDlgROImage(m_xBuilder->weld_widget("lockimage")) + , m_xFileDlgCB(m_xBuilder->weld_check_button("filedlg")) + , m_xPrintDlgCB(m_xBuilder->weld_check_button("printdlg")) + , m_xDocStatusCB(m_xBuilder->weld_check_button("docstatus")) + , m_xYearFrame(m_xBuilder->weld_widget("yearframe")) + , m_xYearValueField(m_xBuilder->weld_spin_button("year")) + , m_xToYearFT(m_xBuilder->weld_label("toyear")) + , m_xCollectUsageInfo(m_xBuilder->weld_check_button("collectusageinfo")) + , m_xCrashReport(m_xBuilder->weld_check_button("crashreport")) + , m_xQuickStarterFrame(m_xBuilder->weld_widget("quickstarter")) +#if defined(UNX) + , m_xQuickLaunchCB(m_xBuilder->weld_check_button("systray")) +#else + , m_xQuickLaunchCB(m_xBuilder->weld_check_button("quicklaunch")) +#endif +#if defined(_WIN32) + , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc")) + , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles")) +#endif +{ + if (!lcl_HasSystemFilePicker()) + m_xFileDlgFrame->hide(); + else if (SvtMiscOptions().IsUseSystemFileDialogReadOnly()) + { + m_xFileDlgROImage->show(); + m_xFileDlgCB->set_sensitive(false); + } + +#if !ENABLE_GTK3 + m_xPrintDlgFrame->hide(); +#else + if (!SvtMiscOptions().IsExperimentalMode()) + { + m_xPrintDlgFrame->hide(); + } +#endif + + m_xQuickLaunchCB->show(); + + //Only available in Win or if building the gtk systray +#if !defined(_WIN32) + m_xQuickStarterFrame->hide(); +#endif + +#if defined(_WIN32) + m_xFileAssocFrame->show(); + m_xFileAssocBtn->connect_clicked(LINK(this, OfaMiscTabPage, FileAssocClick)); +#endif + + m_aStrDateInfo = m_xToYearFT->get_label(); + m_xYearValueField->connect_value_changed( LINK( this, OfaMiscTabPage, TwoFigureHdl ) ); + + SetExchangeSupport(); +} + +OfaMiscTabPage::~OfaMiscTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaMiscTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique<OfaMiscTabPage>( pPage, pController, *rAttrSet ); +} + +bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create()); + + SvtHelpOptions aHelpOptions; + if ( m_xPopUpNoHelpCB->get_state_changed_from_saved() ) + aHelpOptions.SetOfflineHelpPopUp( m_xPopUpNoHelpCB->get_active() ); + + if ( m_xExtHelpCB->get_state_changed_from_saved() ) + aHelpOptions.SetExtendedHelp( m_xExtHelpCB->get_active() ); + + if ( m_xShowTipOfTheDay->get_state_changed_from_saved() ) + { + officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_xShowTipOfTheDay->get_active(), batch); + bModified = true; + } + + if ( m_xFileDlgCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetUseSystemFileDialog( !m_xFileDlgCB->get_active() ); + bModified = true; + } + + if ( m_xPrintDlgCB->get_state_changed_from_saved() ) + { + SvtMiscOptions aMiscOpt; + aMiscOpt.SetUseSystemPrintDialog( !m_xPrintDlgCB->get_active() ); + bModified = true; + } + + if ( m_xDocStatusCB->get_state_changed_from_saved() ) + { + SvtPrintWarningOptions aPrintOptions; + aPrintOptions.SetModifyDocumentOnPrintingAllowed( m_xDocStatusCB->get_active() ); + bModified = true; + } + + const SfxUInt16Item* pUInt16Item = dynamic_cast< const SfxUInt16Item* >( GetOldItem( *rSet, SID_ATTR_YEAR2000 ) ); + sal_uInt16 nNum = static_cast<sal_uInt16>(m_xYearValueField->get_text().toInt32()); + if ( pUInt16Item && pUInt16Item->GetValue() != nNum ) + { + bModified = true; + rSet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, nNum ) ); + } + + if (m_xCollectUsageInfo->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::CollectUsageInformation::set(m_xCollectUsageInfo->get_active(), batch); + bModified = true; + } + +#if HAVE_FEATURE_BREAKPAD + if (m_xCrashReport->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::CrashReport::set(m_xCrashReport->get_active(), batch); + bModified = true; + } +#endif + + batch->commit(); + + if( m_xQuickLaunchCB->get_state_changed_from_saved()) + { + rSet->Put(SfxBoolItem(SID_ATTR_QUICKLAUNCHER, m_xQuickLaunchCB->get_active())); + bModified = true; + } + + return bModified; +} + +void OfaMiscTabPage::Reset( const SfxItemSet* rSet ) +{ + SvtHelpOptions aHelpOptions; + m_xExtHelpCB->set_active( aHelpOptions.IsHelpTips() && aHelpOptions.IsExtendedHelp() ); + m_xExtHelpCB->save_state(); + m_xPopUpNoHelpCB->set_active( aHelpOptions.IsOfflineHelpPopUp() ); + m_xPopUpNoHelpCB->save_state(); + m_xShowTipOfTheDay->set_active( officecfg::Office::Common::Misc::ShowTipOfTheDay::get() ); + m_xShowTipOfTheDay->save_state(); + SvtMiscOptions aMiscOpt; + m_xFileDlgCB->set_active( !aMiscOpt.UseSystemFileDialog() ); + m_xFileDlgCB->save_state(); + m_xPrintDlgCB->set_active( !aMiscOpt.UseSystemPrintDialog() ); + m_xPrintDlgCB->save_state(); + + SvtPrintWarningOptions aPrintOptions; + m_xDocStatusCB->set_active(aPrintOptions.IsModifyDocumentOnPrintingAllowed()); + m_xDocStatusCB->save_state(); + + const SfxPoolItem* pItem = nullptr; + if ( SfxItemState::SET == rSet->GetItemState( SID_ATTR_YEAR2000, false, &pItem ) ) + { + m_xYearValueField->set_value( static_cast<const SfxUInt16Item*>(pItem)->GetValue() ); + TwoFigureHdl(*m_xYearValueField); + } + else + m_xYearFrame->set_sensitive(false); + + m_xCollectUsageInfo->set_active(officecfg::Office::Common::Misc::CollectUsageInformation::get()); + m_xCollectUsageInfo->set_sensitive(!officecfg::Office::Common::Misc::CollectUsageInformation::isReadOnly()); + m_xCollectUsageInfo->save_state(); + +#if HAVE_FEATURE_BREAKPAD + m_xCrashReport->set_active(officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::IsDumpEnable()); + m_xCrashReport->set_sensitive(!officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable()); + m_xCrashReport->save_state(); +#else + m_xCrashReport->hide(); +#endif + + SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem ); + if ( SfxItemState::SET == eState ) + m_xQuickLaunchCB->set_active( static_cast<const SfxBoolItem*>(pItem)->GetValue() ); + else if ( SfxItemState::DISABLED == eState ) + { + // quickstart not installed + m_xQuickStarterFrame->hide(); + } + + m_xQuickLaunchCB->save_state(); +} + +IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void ) +{ + OUString aOutput( m_aStrDateInfo ); + OUString aStr( m_xYearValueField->get_text() ); + sal_Int32 nNum = aStr.toInt32(); + if ( aStr.getLength() != 4 || nNum < m_xYearValueField->get_min() || nNum > m_xYearValueField->get_max() ) + aOutput += "????"; + else + { + nNum += 99; + aOutput += OUString::number( nNum ); + } + m_xToYearFT->set_label( aOutput ); +} + +#if defined(_WIN32) +IMPL_STATIC_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void) +{ + const bool bUninit = SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + IApplicationAssociationRegistrationUI* pIf = nullptr; + HRESULT res = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI, nullptr, + CLSCTX_INPROC_SERVER, IID_IApplicationAssociationRegistrationUI, + reinterpret_cast<LPVOID*>(&pIf)); + + if (SUCCEEDED(res) && pIf) + { + // LaunchAdvancedAssociationUI only works for applications registered under + // Software\RegisteredApplications. See scp2/source/ooo/registryitem_ooo.scp + const OUString expanded = Translate::ExpandVariables("%PRODUCTNAME %PRODUCTVERSION"); + // This will only show "To change your default apps, go to Settings > Apps > Default apps" + // on Win10; this is expected. At least this will self-document it to users. + pIf->LaunchAdvancedAssociationUI(o3tl::toW(expanded.getStr())); + pIf->Release(); + } + if (bUninit) + CoUninitialize(); +} +#endif + +class CanvasSettings +{ +public: + CanvasSettings(); + + bool IsHardwareAccelerationEnabled() const; + bool IsHardwareAccelerationAvailable() const; + bool IsHardwareAccelerationRO() const; + void EnabledHardwareAcceleration( bool _bEnabled ) const; + +private: + typedef std::vector< std::pair<OUString,Sequence<OUString> > > ServiceVector; + + Reference<XNameAccess> mxForceFlagNameAccess; + ServiceVector maAvailableImplementations; + mutable bool mbHWAccelAvailable; + mutable bool mbHWAccelChecked; +}; + +CanvasSettings::CanvasSettings() : + mxForceFlagNameAccess(), + mbHWAccelAvailable(false), + mbHWAccelChecked(false) +{ + try + { + Reference<XMultiServiceFactory> xConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + + Sequence<Any> aArgs1(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas"))} + })); + mxForceFlagNameAccess.set( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + aArgs1 ), + UNO_QUERY_THROW ); + + Sequence<Any> aArgs2(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas/CanvasServiceList"))} + })); + Reference<XNameAccess> xNameAccess( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess", + aArgs2 ), UNO_QUERY_THROW ); + Reference<XHierarchicalNameAccess> xHierarchicalNameAccess( + xNameAccess, UNO_QUERY_THROW); + + Sequence<OUString> serviceNames = xNameAccess->getElementNames(); + const OUString* pCurr = serviceNames.getConstArray(); + const OUString* const pEnd = pCurr + serviceNames.getLength(); + while( pCurr != pEnd ) + { + Reference<XNameAccess> xEntryNameAccess( + xHierarchicalNameAccess->getByHierarchicalName(*pCurr), + UNO_QUERY ); + + if( xEntryNameAccess.is() ) + { + Sequence<OUString> preferredImplementations; + if( xEntryNameAccess->getByName("PreferredImplementations") >>= preferredImplementations ) + maAvailableImplementations.emplace_back(*pCurr,preferredImplementations ); + } + + ++pCurr; + } + } + catch (const Exception&) + { + } +} + +bool CanvasSettings::IsHardwareAccelerationAvailable() const +{ + if (SkiaHelper::isVCLSkiaEnabled() && Application::GetToolkitName() != "gtk3") + { + mbHWAccelAvailable = false; + return false; + } +#if HAVE_FEATURE_OPENGL + if (OpenGLWrapper::isVCLOpenGLEnabled() && Application::GetToolkitName() != "gtk3") + { + mbHWAccelAvailable = false; + return false; + } +#endif + if( !mbHWAccelChecked ) + { + mbHWAccelChecked = true; + + Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory(); + + // check whether any of the service lists has an + // implementation that presents the "HardwareAcceleration" property + for (auto const& availableImpl : maAvailableImplementations) + { + const OUString* pCurrImpl = availableImpl.second.getConstArray(); + const OUString* const pEndImpl = pCurrImpl + availableImpl.second.getLength(); + + while( pCurrImpl != pEndImpl ) + { + try + { + Reference<XPropertySet> xPropSet( xFactory->createInstance( + pCurrImpl->trim() ), + UNO_QUERY_THROW ); + bool bHasAccel(false); + if( xPropSet->getPropertyValue("HardwareAcceleration") >>= bHasAccel ) + if( bHasAccel ) + { + mbHWAccelAvailable = true; + return mbHWAccelAvailable; + } + } + catch (const Exception&) + { + } + + ++pCurrImpl; + } + } + } + + return mbHWAccelAvailable; +} + +bool CanvasSettings::IsHardwareAccelerationEnabled() const +{ + bool bForceLastEntry(false); + if( !mxForceFlagNameAccess.is() ) + return true; + + if( !(mxForceFlagNameAccess->getByName("ForceSafeServiceImpl") >>= bForceLastEntry) ) + return true; + + return !bForceLastEntry; +} + +bool CanvasSettings::IsHardwareAccelerationRO() const +{ + Reference< XPropertySet > xSet(mxForceFlagNameAccess, UNO_QUERY); + if (!xSet.is()) + return true; + + Reference< XPropertySetInfo > xInfo = xSet->getPropertySetInfo(); + Property aProp = xInfo->getPropertyByName("ForceSafeServiceImpl"); + return ((aProp.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY); +} + +void CanvasSettings::EnabledHardwareAcceleration( bool _bEnabled ) const +{ + Reference< XNameReplace > xNameReplace( + mxForceFlagNameAccess, UNO_QUERY ); + + if( !xNameReplace.is() ) + return; + + xNameReplace->replaceByName( "ForceSafeServiceImpl", Any(!_bEnabled) ); + + Reference< XChangesBatch > xChangesBatch( + mxForceFlagNameAccess, UNO_QUERY ); + + if( !xChangesBatch.is() ) + return; + + xChangesBatch->commitChanges(); +} + +// class OfaViewTabPage -------------------------------------------------- + +static bool DisplayNameCompareLessThan(const vcl::IconThemeInfo& rInfo1, const vcl::IconThemeInfo& rInfo2) +{ + return rInfo1.GetDisplayName().compareTo(rInfo2.GetDisplayName()) < 0; +} + +OfaViewTabPage::OfaViewTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optviewpage.ui", "OptViewPage", &rSet) + , nSizeLB_InitialSelection(0) + , nSidebarSizeLB_InitialSelection(0) + , nNotebookbarSizeLB_InitialSelection(0) + , nStyleLB_InitialSelection(0) + , pAppearanceCfg(new SvtTabAppearanceCfg) + , pCanvasSettings(new CanvasSettings) + , mpDrawinglayerOpt(new SvtOptionsDrawinglayer) + , mpSkiaConfig(new svt::SkiaCfg) + , m_xIconSizeLB(m_xBuilder->weld_combo_box("iconsize")) + , m_xSidebarIconSizeLB(m_xBuilder->weld_combo_box("sidebariconsize")) + , m_xNotebookbarIconSizeLB(m_xBuilder->weld_combo_box("notebookbariconsize")) + , m_xIconStyleLB(m_xBuilder->weld_combo_box("iconstyle")) + , m_xFontAntiAliasing(m_xBuilder->weld_check_button("aafont")) + , m_xAAPointLimitLabel(m_xBuilder->weld_label("aafrom")) + , m_xAAPointLimit(m_xBuilder->weld_metric_spin_button("aanf", FieldUnit::PIXEL)) + , m_xMenuIconBox(m_xBuilder->weld_widget("menuiconsbox")) + , m_xMenuIconsLB(m_xBuilder->weld_combo_box("menuicons")) + , m_xContextMenuShortcutsLB(m_xBuilder->weld_combo_box("contextmenushortcuts")) + , m_xFontShowCB(m_xBuilder->weld_check_button("showfontpreview")) + , m_xUseHardwareAccell(m_xBuilder->weld_check_button("useaccel")) + , m_xUseAntiAliase(m_xBuilder->weld_check_button("useaa")) + , m_xUseSkia(m_xBuilder->weld_check_button("useskia")) + , m_xForceSkiaRaster(m_xBuilder->weld_check_button("forceskiaraster")) + , m_xSkiaStatusEnabled(m_xBuilder->weld_label("skiaenabled")) + , m_xSkiaStatusDisabled(m_xBuilder->weld_label("skiadisabled")) + , m_xMousePosLB(m_xBuilder->weld_combo_box("mousepos")) + , m_xMouseMiddleLB(m_xBuilder->weld_combo_box("mousemiddle")) +{ + if (Application::GetToolkitName() == "gtk3") + { + m_xUseSkia->hide(); + m_xForceSkiaRaster->hide(); + m_xSkiaStatusEnabled->hide(); + m_xSkiaStatusDisabled->hide(); + m_xMenuIconBox->hide(); + } + +#if !HAVE_FEATURE_SKIA || !defined(_WIN32) + // Duplicated also in UpdateSkiaStatus(). + // For now Skia is used mainly on Windows, hide the controls everywhere else. + // It can also be used on Linux, but only with the rarely used 'gen' backend. + m_xUseSkia->hide(); + m_xForceSkiaRaster->hide(); + m_xSkiaStatusEnabled->hide(); + m_xSkiaStatusDisabled->hide(); +#endif + + m_xFontAntiAliasing->connect_toggled( LINK( this, OfaViewTabPage, OnAntialiasingToggled ) ); + + m_xForceSkiaRaster->connect_toggled(LINK(this, OfaViewTabPage, OnForceSkiaRasterToggled)); + + // Set known icon themes + OUString sAutoStr( m_xIconStyleLB->get_text( 0 ) ); + m_xIconStyleLB->clear(); + StyleSettings aStyleSettings = Application::GetSettings().GetStyleSettings(); + mInstalledIconThemes = aStyleSettings.GetInstalledIconThemes(); + std::sort(mInstalledIconThemes.begin(), mInstalledIconThemes.end(), DisplayNameCompareLessThan); + + // Start with the automatically chosen icon theme + OUString autoThemeId = aStyleSettings.GetAutomaticallyChosenIconTheme(); + const vcl::IconThemeInfo& autoIconTheme = vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, autoThemeId); + + OUString entryForAuto = sAutoStr + " (" + + autoIconTheme.GetDisplayName() + + ")"; + m_xIconStyleLB->append("auto", entryForAuto); // index 0 means choose style automatically + + // separate auto and other icon themes + m_xIconStyleLB->append_separator(""); + + for (auto const& installIconTheme : mInstalledIconThemes) + m_xIconStyleLB->append(installIconTheme.GetThemeId(), installIconTheme.GetDisplayName()); + + m_xIconStyleLB->set_active(0); + + // FIXME: should really add code to show a 'lock' icon here. + if (officecfg::Office::Common::VCL::UseSkia::isReadOnly()) + m_xUseSkia->set_sensitive(false); + if (officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()) + m_xForceSkiaRaster->set_sensitive(false); + + UpdateSkiaStatus(); +} + +OfaViewTabPage::~OfaViewTabPage() +{ +} + +IMPL_LINK_NOARG( OfaViewTabPage, OnAntialiasingToggled, weld::ToggleButton&, void ) +{ + bool bAAEnabled = m_xFontAntiAliasing->get_active(); + + m_xAAPointLimitLabel->set_sensitive(bAAEnabled); + m_xAAPointLimit->set_sensitive(bAAEnabled); +} + +IMPL_LINK_NOARG(OfaViewTabPage, OnForceSkiaRasterToggled, weld::ToggleButton&, void) +{ + if (m_xForceSkiaRaster->get_active()) + { + // Forcing Skia raster implies that Skia is on. + m_xUseSkia->set_active(true); + } +} + +std::unique_ptr<SfxTabPage> OfaViewTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique<OfaViewTabPage>(pPage, pController, *rAttrSet); +} + +bool OfaViewTabPage::FillItemSet( SfxItemSet* ) +{ + SvtFontOptions aFontOpt; + SvtMenuOptions aMenuOpt; + + bool bModified = false; + bool bMenuOptModified = false; + bool bRepaintWindows(false); + + SvtMiscOptions aMiscOptions; + const sal_Int32 nSizeLB_NewSelection = m_xIconSizeLB->get_active(); + if( nSizeLB_InitialSelection != nSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + sal_Int16 eSet = SFX_SYMBOLS_SIZE_AUTO; + switch( nSizeLB_NewSelection ) + { + case 0: eSet = SFX_SYMBOLS_SIZE_AUTO; break; + case 1: eSet = SFX_SYMBOLS_SIZE_SMALL; break; + case 2: eSet = SFX_SYMBOLS_SIZE_LARGE; break; + case 3: eSet = SFX_SYMBOLS_SIZE_32; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xIconSizeLB should not be possible!" ); + } + aMiscOptions.SetSymbolsSize( eSet ); + } + + const sal_Int32 nSidebarSizeLB_NewSelection = m_xSidebarIconSizeLB->get_active(); + if( nSidebarSizeLB_InitialSelection != nSidebarSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare; + switch( nSidebarSizeLB_NewSelection ) + { + case 0: eSet = ToolBoxButtonSize::DontCare; break; + case 1: eSet = ToolBoxButtonSize::Small; break; + case 2: eSet = ToolBoxButtonSize::Large; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xSidebarIconSizeLB should not be possible!" ); + } + aMiscOptions.SetSidebarIconSize( eSet ); + } + + const sal_Int32 nNotebookbarSizeLB_NewSelection = m_xNotebookbarIconSizeLB->get_active(); + if( nNotebookbarSizeLB_InitialSelection != nNotebookbarSizeLB_NewSelection ) + { + // from now on it's modified, even if via auto setting the same size was set as now selected in the LB + ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare; + switch( nNotebookbarSizeLB_NewSelection ) + { + case 0: eSet = ToolBoxButtonSize::DontCare; break; + case 1: eSet = ToolBoxButtonSize::Small; break; + case 2: eSet = ToolBoxButtonSize::Large; break; + default: + OSL_FAIL( "OfaViewTabPage::FillItemSet(): This state of m_xNotebookbarIconSizeLB should not be possible!" ); + } + aMiscOptions.SetNotebookbarIconSize( eSet ); + } + + const sal_Int32 nStyleLB_NewSelection = m_xIconStyleLB->get_active(); + if( nStyleLB_InitialSelection != nStyleLB_NewSelection ) + { + aMiscOptions.SetIconTheme(m_xIconStyleLB->get_active_id()); + nStyleLB_InitialSelection = nStyleLB_NewSelection; + } + + bool bAppearanceChanged = false; + + // Mouse Snap Mode + SnapType eOldSnap = pAppearanceCfg->GetSnapMode(); + SnapType eNewSnap = static_cast<SnapType>(m_xMousePosLB->get_active()); + if(eNewSnap > SnapType::NONE) + eNewSnap = SnapType::NONE; + + if ( eNewSnap != eOldSnap ) + { + pAppearanceCfg->SetSnapMode(eNewSnap ); + bAppearanceChanged = true; + } + + // Middle Mouse Button + MouseMiddleButtonAction eOldMiddleMouse = pAppearanceCfg->GetMiddleMouseButton(); + short eNewMiddleMouse = m_xMouseMiddleLB->get_active(); + if(eNewMiddleMouse > 2) + eNewMiddleMouse = 2; + + if ( eNewMiddleMouse != static_cast<short>(eOldMiddleMouse) ) + { + pAppearanceCfg->SetMiddleMouseButton( static_cast<MouseMiddleButtonAction>(eNewMiddleMouse) ); + bAppearanceChanged = true; + } + + if (m_xFontAntiAliasing->get_state_changed_from_saved()) + { + pAppearanceCfg->SetFontAntiAliasing(m_xFontAntiAliasing->get_active()); + bAppearanceChanged = true; + } + + if (m_xAAPointLimit->get_value_changed_from_saved()) + { + pAppearanceCfg->SetFontAntialiasingMinPixelHeight(m_xAAPointLimit->get_value(FieldUnit::PIXEL)); + bAppearanceChanged = true; + } + + if (m_xFontShowCB->get_state_changed_from_saved()) + { + aFontOpt.EnableFontWYSIWYG(m_xFontShowCB->get_active()); + bModified = true; + } + + if (m_xMenuIconsLB->get_value_changed_from_saved()) + { + aMenuOpt.SetMenuIconsState(m_xMenuIconsLB->get_active() == 0 ? + TRISTATE_INDET : + static_cast<TriState>(m_xMenuIconsLB->get_active() - 1)); + bModified = true; + bMenuOptModified = true; + bAppearanceChanged = true; + } + + if (m_xContextMenuShortcutsLB->get_value_changed_from_saved()) + { + aMenuOpt.SetContextMenuShortcuts(m_xContextMenuShortcutsLB->get_active() == 0 ? + TRISTATE_INDET : + static_cast<TriState>(m_xContextMenuShortcutsLB->get_active() - 1)); + bModified = true; + bMenuOptModified = true; + bAppearanceChanged = true; + } + + // #i95644# if disabled, do not use value, see in ::Reset() + if (m_xUseHardwareAccell->get_sensitive()) + { + if(m_xUseHardwareAccell->get_state_changed_from_saved()) + { + pCanvasSettings->EnabledHardwareAcceleration(m_xUseHardwareAccell->get_active()); + bModified = true; + } + } + + // #i95644# if disabled, do not use value, see in ::Reset() + if (m_xUseAntiAliase->get_sensitive()) + { + if (m_xUseAntiAliase->get_active() != mpDrawinglayerOpt->IsAntiAliasing()) + { + mpDrawinglayerOpt->SetAntiAliasing(m_xUseAntiAliase->get_active()); + bModified = true; + bRepaintWindows = true; + } + } + + if (m_xUseSkia->get_state_changed_from_saved() || + m_xForceSkiaRaster->get_state_changed_from_saved()) + { + mpSkiaConfig->setUseSkia(m_xUseSkia->get_active()); + mpSkiaConfig->setForceSkiaRaster(m_xForceSkiaRaster->get_active()); + bModified = true; + } + + if( bMenuOptModified ) + { + // Set changed settings to the application instance + AllSettings aAllSettings = Application::GetSettings(); + StyleSettings aStyleSettings = aAllSettings.GetStyleSettings(); + aAllSettings.SetStyleSettings(aStyleSettings); + Application::MergeSystemSettings( aAllSettings ); + Application::SetSettings(aAllSettings); + } + + if ( bAppearanceChanged ) + { + pAppearanceCfg->Commit(); + pAppearanceCfg->SetApplicationDefaults ( GetpApp() ); + } + + if(bRepaintWindows) + { + vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow(); + + while(pAppWindow) + { + pAppWindow->Invalidate(); + pAppWindow = Application::GetNextTopLevelWindow(pAppWindow); + } + } + + if (m_xUseSkia->get_state_changed_from_saved() || + m_xForceSkiaRaster->get_state_changed_from_saved()) + { + SolarMutexGuard aGuard; + if( svtools::executeRestartDialog( + comphelper::getProcessComponentContext(), nullptr, + svtools::RESTART_REASON_SKIA)) + GetDialogController()->response(RET_OK); + } + + return bModified; +} + +void OfaViewTabPage::Reset( const SfxItemSet* ) +{ + SvtMiscOptions aMiscOptions; + mpSkiaConfig->reset(); + + if (aMiscOptions.GetSymbolsSize() != SFX_SYMBOLS_SIZE_AUTO) + { + nSizeLB_InitialSelection = 1; + + if (aMiscOptions.GetSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE) + nSizeLB_InitialSelection = 2; + else if (aMiscOptions.GetSymbolsSize() == SFX_SYMBOLS_SIZE_32) + nSizeLB_InitialSelection = 3; + } + m_xIconSizeLB->set_active( nSizeLB_InitialSelection ); + m_xIconSizeLB->save_value(); + + if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::Small ) + nSidebarSizeLB_InitialSelection = 1; + else if( aMiscOptions.GetSidebarIconSize() == ToolBoxButtonSize::Large ) + nSidebarSizeLB_InitialSelection = 2; + m_xSidebarIconSizeLB->set_active( nSidebarSizeLB_InitialSelection ); + m_xSidebarIconSizeLB->save_value(); + if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::Small ) + nNotebookbarSizeLB_InitialSelection = 1; + else if( aMiscOptions.GetNotebookbarIconSize() == ToolBoxButtonSize::Large ) + nNotebookbarSizeLB_InitialSelection = 2; + m_xNotebookbarIconSizeLB->set_active(nNotebookbarSizeLB_InitialSelection); + m_xNotebookbarIconSizeLB->save_value(); + + if (aMiscOptions.IconThemeWasSetAutomatically()) { + nStyleLB_InitialSelection = 0; + } + else { + const OUString& selected = aMiscOptions.GetIconTheme(); + const vcl::IconThemeInfo& selectedInfo = + vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, selected); + nStyleLB_InitialSelection = m_xIconStyleLB->find_text(selectedInfo.GetDisplayName()); + } + + m_xIconStyleLB->set_active(nStyleLB_InitialSelection); + m_xIconStyleLB->save_value(); + + // Mouse Snap + m_xMousePosLB->set_active(static_cast<sal_Int32>(pAppearanceCfg->GetSnapMode())); + m_xMousePosLB->save_value(); + + // Mouse Snap + m_xMouseMiddleLB->set_active(static_cast<short>(pAppearanceCfg->GetMiddleMouseButton())); + m_xMouseMiddleLB->save_value(); + + m_xFontAntiAliasing->set_active( pAppearanceCfg->IsFontAntiAliasing() ); + m_xAAPointLimit->set_value(pAppearanceCfg->GetFontAntialiasingMinPixelHeight(), FieldUnit::PIXEL); + + // WorkingSet + SvtFontOptions aFontOpt; + m_xFontShowCB->set_active( aFontOpt.IsFontWYSIWYGEnabled() ); + SvtMenuOptions aMenuOpt; + m_xMenuIconsLB->set_active(aMenuOpt.GetMenuIconsState() == 2 ? 0 : aMenuOpt.GetMenuIconsState() + 1); + m_xMenuIconsLB->save_value(); + + TriState eContextMenuShortcuts = aMenuOpt.GetContextMenuShortcuts(); + bool bContextMenuShortcutsNonDefault = eContextMenuShortcuts == TRISTATE_FALSE || eContextMenuShortcuts == TRISTATE_TRUE; + m_xContextMenuShortcutsLB->set_active(bContextMenuShortcutsNonDefault ? eContextMenuShortcuts + 1 : 0); + m_xContextMenuShortcutsLB->save_value(); + + { // #i95644# HW accel (unified to disable mechanism) + if(pCanvasSettings->IsHardwareAccelerationAvailable()) + { + m_xUseHardwareAccell->set_active(pCanvasSettings->IsHardwareAccelerationEnabled()); + m_xUseHardwareAccell->set_sensitive(!pCanvasSettings->IsHardwareAccelerationRO()); + } + else + { + m_xUseHardwareAccell->set_active(false); + m_xUseHardwareAccell->set_sensitive(false); + } + + m_xUseHardwareAccell->save_state(); + } + + { // #i95644# AntiAliasing + if(mpDrawinglayerOpt->IsAAPossibleOnThisSystem()) + { + m_xUseAntiAliase->set_active(mpDrawinglayerOpt->IsAntiAliasing()); + } + else + { + m_xUseAntiAliase->set_active(false); + m_xUseAntiAliase->set_sensitive(false); + } + + m_xUseAntiAliase->save_state(); + } + m_xUseSkia->set_active(mpSkiaConfig->useSkia()); + m_xForceSkiaRaster->set_active(mpSkiaConfig->forceSkiaRaster()); + + m_xFontAntiAliasing->save_state(); + m_xAAPointLimit->save_value(); + m_xFontShowCB->save_state(); + + m_xUseSkia->save_state(); + m_xForceSkiaRaster->save_state(); + + OnAntialiasingToggled(*m_xFontAntiAliasing); +} + +void OfaViewTabPage::UpdateSkiaStatus() +{ + if (Application::GetToolkitName() == "gtk3") + return; +#if HAVE_FEATURE_SKIA && defined(_WIN32) + // Easier than a custom translation string. + bool bEnabled = SkiaHelper::isVCLSkiaEnabled(); + m_xSkiaStatusEnabled->set_visible(bEnabled); + m_xSkiaStatusDisabled->set_visible(!bEnabled); +#endif +} + +struct LanguageConfig_Impl +{ + SvtLanguageOptions aLanguageOptions; + SvtSysLocaleOptions aSysLocaleOptions; + SvtLinguConfig aLinguConfig; +}; + +static bool bLanguageCurrentDoc_Impl = false; + +// some things we'll need... +static const char sAccessSrvc[] = "com.sun.star.configuration.ConfigurationAccess"; +static const char sAccessUpdSrvc[] = "com.sun.star.configuration.ConfigurationUpdateAccess"; +static const char sInstalledLocalesPath[] = "org.openoffice.Setup/Office/InstalledLocales"; +static const char sUserLocalePath[] = "org.openoffice.Office.Linguistic/General"; +static const char sUserLocaleKey[] = "UILocale"; +static Sequence< OUString > seqInstalledLanguages; + +static OUString lcl_getDatePatternsConfigString( const LocaleDataWrapper& rLocaleWrapper ) +{ + Sequence< OUString > aDateAcceptancePatterns = rLocaleWrapper.getDateAcceptancePatterns(); + sal_Int32 nPatterns = aDateAcceptancePatterns.getLength(); + OUStringBuffer aBuf( nPatterns * 6 ); // 6 := length of Y-M-D; + SAL_WARN_IF( !nPatterns, "cui.options", "No date acceptance pattern"); + if (nPatterns) + { + const OUString* pPatterns = aDateAcceptancePatterns.getConstArray(); + aBuf.append( pPatterns[0]); + for (sal_Int32 i=1; i < nPatterns; ++i) + aBuf.append(';').append( pPatterns[i]); + } + return aBuf.makeStringAndClear(); +} + +namespace +{ + //what ui language will be selected by default if the user override of General::UILocale is unset ? + LanguageTag GetInstalledLocaleForSystemUILanguage() + { + css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames()); + return LanguageTag(getInstalledLocaleForSystemUILanguage(inst, false)).makeFallback(); + } +} + +OfaLanguagesTabPage::OfaLanguagesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet) + : SfxTabPage(pPage, pController, "cui/ui/optlanguagespage.ui", "OptLanguagesPage", &rSet) + , pLangConfig(new LanguageConfig_Impl) + , m_bDatePatternsValid(false) + , m_xUserInterfaceLB(m_xBuilder->weld_combo_box("userinterface")) + , m_xLocaleSettingFT(m_xBuilder->weld_label("localesettingFT")) + , m_xLocaleSettingLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("localesetting"))) + , m_xDecimalSeparatorCB(m_xBuilder->weld_check_button("decimalseparator")) + , m_xCurrencyFT(m_xBuilder->weld_label("defaultcurrency")) + , m_xCurrencyLB(m_xBuilder->weld_combo_box("currencylb")) + , m_xDatePatternsFT(m_xBuilder->weld_label("dataaccpatterns")) + , m_xDatePatternsED(m_xBuilder->weld_entry("datepatterns")) + , m_xWesternLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("westernlanguage"))) + , m_xWesternLanguageFT(m_xBuilder->weld_label("western")) + , m_xAsianLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("asianlanguage"))) + , m_xComplexLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box("complexlanguage"))) + , m_xCurrentDocCB(m_xBuilder->weld_check_button("currentdoc")) + , m_xAsianSupportCB(m_xBuilder->weld_check_button("asiansupport")) + , m_xCTLSupportCB(m_xBuilder->weld_check_button("ctlsupport")) + , m_xIgnoreLanguageChangeCB(m_xBuilder->weld_check_button("ignorelanguagechange")) +{ + // tdf#125483 save original default label + m_sDecimalSeparatorLabel = m_xDecimalSeparatorCB->get_label(); + + // initialize user interface language selection + m_sSystemDefaultString = SvtLanguageTable::GetLanguageString( LANGUAGE_SYSTEM ); + + OUString aUILang = m_sSystemDefaultString + + " - " + + SvtLanguageTable::GetLanguageString(GetInstalledLocaleForSystemUILanguage().getLanguageType()); + + m_xUserInterfaceLB->append("0", aUILang); + m_xUserInterfaceLB->append_separator(""); + try + { + Reference< XMultiServiceFactory > theConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + Sequence< Any > theArgs(1); + Reference< XNameAccess > theNameAccess; + + // find out which locales are currently installed and add them to the listbox + theArgs[0] <<= NamedValue("nodepath", Any(OUString(sInstalledLocalesPath))); + theNameAccess.set( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + seqInstalledLanguages = theNameAccess->getElementNames(); + LanguageType aLang = LANGUAGE_DONTKNOW; + std::vector< std::pair<sal_Int32, OUString> > aUILanguages; + for (sal_Int32 i=0; i<seqInstalledLanguages.getLength(); i++) + { + aLang = LanguageTag::convertToLanguageTypeWithFallback(seqInstalledLanguages[i]); + if (aLang != LANGUAGE_DONTKNOW) + { + OUString aLangStr( SvtLanguageTable::GetLanguageString( aLang ) ); + aUILanguages.emplace_back(i+1, aLangStr); + } + } + + std::sort(aUILanguages.begin(), aUILanguages.end(), [](const auto& l1, const auto& l2) { + static const auto aSorter = comphelper::string::NaturalStringSorter( + comphelper::getProcessComponentContext(), + Application::GetSettings().GetLanguageTag().getLocale()); + return aSorter.compare(l1.second, l2.second) < 0; + }); + + // tdf#114694: append the sorted list after the default entry and separator. + for (const auto & [ nGroupID, sGroupName ] : aUILanguages) + { + m_xUserInterfaceLB->append(OUString::number(nGroupID), sGroupName); + } + + m_xUserInterfaceLB->set_active(0); + + // find out whether the user has a specific locale specified + Sequence< Any > theArgs2(1); + theArgs2[0] <<= NamedValue("nodepath", Any(OUString(sUserLocalePath))); + theNameAccess.set( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs2 ), UNO_QUERY_THROW ); + if (theNameAccess->hasByName(sUserLocaleKey)) + theNameAccess->getByName(sUserLocaleKey) >>= m_sUserLocaleValue; + // select the user specified locale in the listbox + if (!m_sUserLocaleValue.isEmpty()) + { + for (sal_Int32 i = 0, nEntryCount = m_xUserInterfaceLB->get_count(); i < nEntryCount; ++i) + { + sal_Int32 d = m_xUserInterfaceLB->get_id(i).toInt32(); + if ( d > 0 && seqInstalledLanguages.getLength() > d-1 && seqInstalledLanguages[d-1] == m_sUserLocaleValue) + m_xUserInterfaceLB->set_active(i); + } + } + + } + catch (const Exception &) + { + // we'll just leave the box in its default setting and won't + // even give it event handler... + TOOLS_WARN_EXCEPTION("cui.options", "ignoring" ); + } + + m_xWesternLanguageLB->SetLanguageList( + SvxLanguageListFlags::WESTERN | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN); + + m_xAsianLanguageLB->SetLanguageList( + SvxLanguageListFlags::CJK | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN); + + m_xComplexLanguageLB->SetLanguageList( + SvxLanguageListFlags::CTL | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true, + LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX); + + m_xLocaleSettingLB->SetLanguageList( + SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false, false, false, true, + LANGUAGE_USER_SYSTEM_CONFIG, css::i18n::ScriptType::WEAK); + + const NfCurrencyTable& rCurrTab = SvNumberFormatter::GetTheCurrencyTable(); + const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( LANGUAGE_SYSTEM ); + // insert SYSTEM entry + OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol(); + m_xCurrencyLB->append("default", aDefaultCurr); + m_xCurrencyLB->append_separator(""); + + assert(m_xCurrencyLB->find_id("default") != -1); + // all currencies + OUString aTwoSpace( " " ); + sal_uInt16 nCurrCount = rCurrTab.size(); + std::vector< const NfCurrencyEntry* > aCurrencies; + // first entry is SYSTEM, skip it + for ( sal_uInt16 j=1; j < nCurrCount; ++j ) + { + aCurrencies.push_back(&rCurrTab[j]); + } + std::sort(aCurrencies.begin(), aCurrencies.end(), + [](const NfCurrencyEntry* c1, const NfCurrencyEntry* c2) { + return c1->GetBankSymbol().compareTo(c2->GetBankSymbol()) < 0; + }); + + for (auto &v : aCurrencies) + { + OUString aStr_ = v->GetBankSymbol() + + aTwoSpace + + v->GetSymbol(); + aStr_ = ApplyLreOrRleEmbedding( aStr_ ) + + aTwoSpace + + ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( v->GetLanguage() ) ); + m_xCurrencyLB->append(OUString::number(reinterpret_cast<sal_Int64>(v)), aStr_); + } + + m_xCurrencyLB->set_active(0); + + m_xLocaleSettingLB->connect_changed( LINK( this, OfaLanguagesTabPage, LocaleSettingHdl ) ); + m_xDatePatternsED->connect_changed( LINK( this, OfaLanguagesTabPage, DatePatternsHdl ) ); + + Link<weld::ToggleButton&,void> aLink( LINK( this, OfaLanguagesTabPage, SupportHdl ) ); + m_xAsianSupportCB->connect_toggled( aLink ); + m_xCTLSupportCB->connect_toggled( aLink ); + + m_bOldAsian = pLangConfig->aLanguageOptions.IsAnyEnabled(); + m_xAsianSupportCB->set_active(m_bOldAsian); + m_xAsianSupportCB->save_state(); + bool bReadonly = pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_ALLCJK); + m_xAsianSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xAsianSupportCB); + + m_bOldCtl = pLangConfig->aLanguageOptions.IsCTLFontEnabled(); + m_xCTLSupportCB->set_active(m_bOldCtl); + m_xCTLSupportCB->save_state(); + bReadonly = pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_CTLFONT); + m_xCTLSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xCTLSupportCB); + + m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange() ); +} + +OfaLanguagesTabPage::~OfaLanguagesTabPage() +{ +} + +std::unique_ptr<SfxTabPage> OfaLanguagesTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique<OfaLanguagesTabPage>(pPage, pController, *rAttrSet); +} + +static void lcl_Update(std::unique_ptr<SfxVoidItem> pInvalidItems[], std::unique_ptr<SfxBoolItem> pBoolItems[], sal_uInt16 nCount) +{ + SfxViewFrame* pCurrentFrm = SfxViewFrame::Current(); + SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(); + while(pViewFrm) + { + SfxBindings& rBind = pViewFrm->GetBindings(); + for(sal_uInt16 i = 0; i < nCount; i++) + { + if(pCurrentFrm == pViewFrm) + rBind.InvalidateAll(false); + rBind.SetState( *pInvalidItems[i] ); + rBind.SetState( *pBoolItems[i] ); + } + pViewFrm = SfxViewFrame::GetNext(*pViewFrm); + } +} + +bool OfaLanguagesTabPage::FillItemSet( SfxItemSet* rSet ) +{ + // lock configuration broadcasters so that we can coordinate the notifications + pLangConfig->aSysLocaleOptions.BlockBroadcasts( true ); + pLangConfig->aLanguageOptions.BlockBroadcasts( true ); + pLangConfig->aLinguConfig.BlockBroadcasts( true ); + + /* + * Sequence checking only matters when CTL support is enabled. + * + * So we only need to check for sequence checking if + * a) previously it was unchecked and is now checked or + * b) it was already checked but the CTL language has changed + */ + if ( + m_xCTLSupportCB->get_active() && + (m_xCTLSupportCB->get_saved_state() != TRISTATE_TRUE || + m_xComplexLanguageLB->get_active_id_changed_from_saved()) + ) + { + //sequence checking has to be switched on depending on the selected CTL language + LanguageType eCTLLang = m_xComplexLanguageLB->get_active_id(); + bool bOn = MsLangId::needsSequenceChecking( eCTLLang); + pLangConfig->aLanguageOptions.SetCTLSequenceCheckingRestricted(bOn); + pLangConfig->aLanguageOptions.SetCTLSequenceChecking(bOn); + pLangConfig->aLanguageOptions.SetCTLSequenceCheckingTypeAndReplace(bOn); + } + try + { + // handle settings for UI Language + // a change of setting needs to bring up a warning message + OUString aLangString; + sal_Int32 d = m_xUserInterfaceLB->get_active_id().toInt32(); + if( d > 0 && seqInstalledLanguages.getLength() > d-1) + aLangString = seqInstalledLanguages[d-1]; + + /* + if( m_xUserInterfaceLB->GetSelectedEntryPos() > 0) + aLangString = ConvertLanguageToIsoString(m_xUserInterfaceLB->get_active_id()); + */ + Reference< XMultiServiceFactory > theConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + Sequence< Any > theArgs(1); + theArgs[0] <<= NamedValue("nodepath", Any(OUString(sUserLocalePath))); + Reference< XPropertySet >xProp( + theConfigProvider->createInstanceWithArguments(sAccessUpdSrvc, theArgs ), UNO_QUERY_THROW ); + if ( m_sUserLocaleValue != aLangString) + { + // OSL_FAIL("UserInterface language was changed, restart."); + // write new value + xProp->setPropertyValue(sUserLocaleKey, Any(aLangString)); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + // display info + SolarMutexGuard aGuard; + if (svtools::executeRestartDialog( + comphelper::getProcessComponentContext(), GetFrameWeld(), + svtools::RESTART_REASON_LANGUAGE_CHANGE)) + GetDialogController()->response(RET_OK); + + // tell quickstarter to stop being a veto listener + + Reference< XComponentContext > xContext( + comphelper::getProcessComponentContext()); + css::office::Quickstart::createAndSetVeto(xContext, false, false, false/*DisableVeto*/); + } + } + catch (const Exception&) + { + // we'll just leave the box in its default setting and won't + // even give it event handler... + TOOLS_WARN_EXCEPTION("cui.options", "ignoring"); + } + + LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag()); + LanguageType eOldLocale = (aLanguageTag.isSystemLocale() ? LANGUAGE_SYSTEM : + aLanguageTag.makeFallback().getLanguageType()); + LanguageType eNewLocale = m_xLocaleSettingLB->get_active_id(); + + // If the "Default ..." entry was selected that means SYSTEM, the actual + // eNewLocale value is temporary for the dialog only, do not resolve to + // what system currently is. + if (eNewLocale == LANGUAGE_USER_SYSTEM_CONFIG) + eNewLocale = LANGUAGE_SYSTEM; + + if ( eOldLocale != eNewLocale ) + { + // an empty string denotes SYSTEM locale + OUString sNewLang; + if ( eNewLocale != LANGUAGE_SYSTEM ) + sNewLang = LanguageTag::convertToBcp47( eNewLocale); + + // locale nowadays get to AppSettings via notification + // this will happen after releasing the lock on the ConfigurationBroadcaster at + // the end of this method + pLangConfig->aSysLocaleOptions.SetLocaleConfigString( sNewLang ); + rSet->Put( SfxBoolItem( SID_OPT_LOCALE_CHANGED, true ) ); + + SvtScriptType nNewType = SvtLanguageOptions::GetScriptTypeOfLanguage( eNewLocale ); + bool bNewCJK = bool( nNewType & SvtScriptType::ASIAN ); + SvtCompatibilityOptions aCompatOpts; + aCompatOpts.SetDefault( SvtCompatibilityEntry::Index::ExpandWordSpace, !bNewCJK ); + } + + if(m_xDecimalSeparatorCB->get_state_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetDecimalSeparatorAsLocale(m_xDecimalSeparatorCB->get_active()); + + if(m_xIgnoreLanguageChangeCB->get_state_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetIgnoreLanguageChange(m_xIgnoreLanguageChangeCB->get_active()); + + // Configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default. + OUString sOldCurr = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString(); + OUString sId = m_xCurrencyLB->get_active_id(); + const NfCurrencyEntry* pCurr = sId == "default" ? nullptr : reinterpret_cast<const NfCurrencyEntry*>(sId.toInt64()); + OUString sNewCurr; + if ( pCurr ) + sNewCurr = SvtSysLocaleOptions::CreateCurrencyConfigString( + pCurr->GetBankSymbol(), pCurr->GetLanguage() ); + if ( sOldCurr != sNewCurr ) + pLangConfig->aSysLocaleOptions.SetCurrencyConfigString( sNewCurr ); + + // Configured date acceptance patterns, for example Y-M-D;M-D or empty for + // locale default. + if (m_bDatePatternsValid && m_xDatePatternsED->get_value_changed_from_saved()) + pLangConfig->aSysLocaleOptions.SetDatePatternsConfigString( m_xDatePatternsED->get_text()); + + SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current(); + Reference< css::linguistic2::XLinguProperties > xLinguProp = LinguMgr::GetLinguPropertySet(); + bool bCurrentDocCBChecked = m_xCurrentDocCB->get_active(); + if (m_xCurrentDocCB->get_sensitive()) + bLanguageCurrentDoc_Impl = bCurrentDocCBChecked; + bool bCurrentDocCBChanged = m_xCurrentDocCB->get_state_changed_from_saved(); + + bool bValChanged = m_xWesternLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xWesternLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::LATIN), + SID_ATTR_LANGUAGE)); + } + } + bValChanged = m_xAsianLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xAsianLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale_CJK", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale_CJK( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::ASIAN), + SID_ATTR_CHAR_CJK_LANGUAGE)); + } + } + bValChanged = m_xComplexLanguageLB->get_active_id_changed_from_saved(); + if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged) + { + LanguageType eSelectLang = m_xComplexLanguageLB->get_active_id(); + if(!bCurrentDocCBChecked) + { + Any aValue; + Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false); + aValue <<= aLocale; + pLangConfig->aLinguConfig.SetProperty( "DefaultLocale_CTL", aValue ); + if (xLinguProp.is()) + xLinguProp->setDefaultLocale_CTL( aLocale ); + } + if(pCurrentDocShell) + { + rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::COMPLEX), + SID_ATTR_CHAR_CTL_LANGUAGE)); + } + } + + if(m_xAsianSupportCB->get_state_changed_from_saved() ) + { + bool bChecked = m_xAsianSupportCB->get_active(); + pLangConfig->aLanguageOptions.SetAll(bChecked); + + //iterate over all bindings to invalidate vertical text direction + const sal_uInt16 STATE_COUNT = 2; + + std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT]; + pBoolItems[0].reset(new SfxBoolItem(SID_VERTICALTEXT_STATE, false)); + pBoolItems[1].reset(new SfxBoolItem(SID_TEXT_FITTOSIZE_VERTICAL, false)); + + std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT]; + pInvalidItems[0].reset(new SfxVoidItem(SID_VERTICALTEXT_STATE)); + pInvalidItems[1].reset(new SfxVoidItem(SID_TEXT_FITTOSIZE_VERTICAL)); + + lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT); + } + + if ( m_xCTLSupportCB->get_state_changed_from_saved() ) + { + SvtSearchOptions aOpt; + aOpt.SetIgnoreDiacritics_CTL(true); + aOpt.SetIgnoreKashida_CTL(true); + aOpt.Commit(); + pLangConfig->aLanguageOptions.SetCTLFontEnabled( m_xCTLSupportCB->get_active() ); + + const sal_uInt16 STATE_COUNT = 1; + std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT]; + pBoolItems[0].reset(new SfxBoolItem(SID_CTLFONT_STATE, false)); + std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT]; + pInvalidItems[0].reset(new SfxVoidItem(SID_CTLFONT_STATE)); + lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT); + } + + if ( pLangConfig->aSysLocaleOptions.IsModified() ) + pLangConfig->aSysLocaleOptions.Commit(); + + // first release the lock on the ConfigurationBroadcaster for Locale changes + // it seems that our code relies on the fact that before other changes like e.g. currency + // are broadcasted locale changes have been done + pLangConfig->aSysLocaleOptions.BlockBroadcasts( false ); + pLangConfig->aLanguageOptions.BlockBroadcasts( false ); + pLangConfig->aLinguConfig.BlockBroadcasts( false ); + + return false; +} + +void OfaLanguagesTabPage::Reset( const SfxItemSet* rSet ) +{ + LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag()); + if ( aLanguageTag.isSystemLocale() ) + m_xLocaleSettingLB->set_active_id( LANGUAGE_USER_SYSTEM_CONFIG ); + else + m_xLocaleSettingLB->set_active_id( aLanguageTag.makeFallback().getLanguageType()); + bool bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Locale); + m_xLocaleSettingLB->set_sensitive(!bReadonly); + m_xLocaleSettingFT->set_sensitive(!bReadonly); + + + m_xDecimalSeparatorCB->set_active( pLangConfig->aSysLocaleOptions.IsDecimalSeparatorAsLocale()); + m_xDecimalSeparatorCB->save_state(); + + m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange()); + m_xIgnoreLanguageChangeCB->save_state(); + + // let LocaleSettingHdl enable/disable checkboxes for CJK/CTL support + // #i15812# must be done *before* the configured currency is set + // and update the decimal separator used for the given locale + LocaleSettingHdl(*m_xLocaleSettingLB->get_widget()); + + // configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default + OUString aAbbrev; + LanguageType eLang; + const NfCurrencyEntry* pCurr = nullptr; + OUString sCurrency = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString(); + if ( !sCurrency.isEmpty() ) + { + SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( aAbbrev, eLang, sCurrency ); + pCurr = SvNumberFormatter::GetCurrencyEntry( aAbbrev, eLang ); + } + // if pCurr==nullptr the SYSTEM entry is selected + OUString sId = !pCurr ? OUString("default") : OUString::number(reinterpret_cast<sal_Int64>(pCurr)); + m_xCurrencyLB->set_active_id(sId); + bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Currency); + m_xCurrencyLB->set_sensitive(!bReadonly); + m_xCurrencyFT->set_sensitive(!bReadonly); + + // date acceptance patterns + OUString aDatePatternsString = pLangConfig->aSysLocaleOptions.GetDatePatternsConfigString(); + if (aDatePatternsString.isEmpty()) + { + const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); + aDatePatternsString = lcl_getDatePatternsConfigString( rLocaleWrapper); + } + // Let's assume patterns are valid at this point. + m_bDatePatternsValid = true; + m_xDatePatternsED->set_text(aDatePatternsString); + bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DatePatterns); + m_xDatePatternsED->set_sensitive(!bReadonly); + m_xDatePatternsFT->set_sensitive(!bReadonly); + m_xDatePatternsED->save_value(); + + //western/CJK/CLK language + LanguageType eCurLang = LANGUAGE_NONE; + LanguageType eCurLangCJK = LANGUAGE_NONE; + LanguageType eCurLangCTL = LANGUAGE_NONE; + SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current(); + //collect the configuration values first + m_xCurrentDocCB->set_sensitive(false); + + Any aWestLang; + Any aCJKLang; + Any aCTLLang; + try + { + aWestLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale"); + Locale aLocale; + aWestLang >>= aLocale; + + eCurLang = LanguageTag::convertToLanguageType( aLocale, false); + + aCJKLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale_CJK"); + aLocale = Locale(); + aCJKLang >>= aLocale; + eCurLangCJK = LanguageTag::convertToLanguageType( aLocale, false); + + aCTLLang = pLangConfig->aLinguConfig.GetProperty("DefaultLocale_CTL"); + aLocale = Locale(); + aCTLLang >>= aLocale; + eCurLangCTL = LanguageTag::convertToLanguageType( aLocale, false); + } + catch (const Exception&) + { + } + //overwrite them by the values provided by the DocShell + if(pCurrentDocShell) + { + m_xCurrentDocCB->set_sensitive(true); + m_xCurrentDocCB->set_active(bLanguageCurrentDoc_Impl); + const SfxPoolItem* pLang; + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast<const SvxLanguageItem*>(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLang, css::i18n::ScriptType::LATIN) != eTempCurLang) + eCurLang = eTempCurLang; + } + + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_CHAR_CJK_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast<const SvxLanguageItem*>(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCJK, css::i18n::ScriptType::ASIAN) != eTempCurLang) + eCurLangCJK = eTempCurLang; + } + + if( SfxItemState::SET == rSet->GetItemState(SID_ATTR_CHAR_CTL_LANGUAGE, false, &pLang)) + { + LanguageType eTempCurLang = static_cast<const SvxLanguageItem*>(pLang)->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCTL, css::i18n::ScriptType::COMPLEX) != eTempCurLang) + eCurLangCTL = eTempCurLang; + } + } + if(LANGUAGE_NONE == eCurLang || LANGUAGE_DONTKNOW == eCurLang) + m_xWesternLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xWesternLanguageLB->set_active_id(eCurLang); + + if(LANGUAGE_NONE == eCurLangCJK || LANGUAGE_DONTKNOW == eCurLangCJK) + m_xAsianLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xAsianLanguageLB->set_active_id(eCurLangCJK); + + if(LANGUAGE_NONE == eCurLangCTL || LANGUAGE_DONTKNOW == eCurLangCTL) + m_xComplexLanguageLB->set_active_id(LANGUAGE_NONE); + else + m_xComplexLanguageLB->set_active_id(eCurLangCTL); + + m_xWesternLanguageLB->save_active_id(); + m_xAsianLanguageLB->save_active_id(); + m_xComplexLanguageLB->save_active_id(); + m_xIgnoreLanguageChangeCB->save_state(); + m_xCurrentDocCB->save_state(); + + bool bEnable = !pLangConfig->aLinguConfig.IsReadOnly( "DefaultLocale" ); + m_xWesternLanguageFT->set_sensitive( bEnable ); + m_xWesternLanguageLB->set_sensitive( bEnable ); + + // check the box "For the current document only" + // set the focus to the Western Language box + const SfxPoolItem* pLang = nullptr; + if ( SfxItemState::SET == rSet->GetItemState(SID_SET_DOCUMENT_LANGUAGE, false, &pLang ) && static_cast<const SfxBoolItem*>(pLang)->GetValue() ) + { + m_xWesternLanguageLB->grab_focus(); + m_xCurrentDocCB->set_sensitive(true); + m_xCurrentDocCB->set_active(true); + } +} + +IMPL_LINK(OfaLanguagesTabPage, SupportHdl, weld::ToggleButton&, rBox, void) +{ + bool bCheck = rBox.get_active(); + if ( m_xAsianSupportCB.get() == &rBox ) + { + bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly("DefaultLocale_CJK"); + bCheck = ( bCheck && !bReadonly ); + m_xAsianLanguageLB->set_sensitive( bCheck ); + if (rBox.get_sensitive()) + m_bOldAsian = bCheck; + } + else if ( m_xCTLSupportCB.get() == &rBox ) + { + bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly("DefaultLocale_CTL"); + bCheck = ( bCheck && !bReadonly ); + m_xComplexLanguageLB->set_sensitive( bCheck ); + if (rBox.get_sensitive()) + m_bOldCtl = bCheck; + } + else + SAL_WARN( "cui.options", "OfaLanguagesTabPage::SupportHdl(): wrong rBox" ); +} + +namespace +{ + void lcl_checkLanguageCheckBox(weld::CheckButton& _rCB, bool _bNewValue, bool _bOldValue) + { + if ( _bNewValue ) + _rCB.set_active(true); + else + _rCB.set_active( _bOldValue ); +// #i15082# do not call save_state() in running dialog... +// _rCB.save_state(); + _rCB.set_sensitive( !_bNewValue ); + } +} + +IMPL_LINK_NOARG(OfaLanguagesTabPage, LocaleSettingHdl, weld::ComboBox&, void) +{ + LanguageType eLang = m_xLocaleSettingLB->get_active_id(); + SvtScriptType nType = SvtLanguageOptions::GetScriptTypeOfLanguage(eLang); + // first check if CTL must be enabled + // #103299# - if CTL font setting is not readonly + if(!pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_CTLFONT)) + { + bool bIsCTLFixed = bool(nType & SvtScriptType::COMPLEX); + lcl_checkLanguageCheckBox(*m_xCTLSupportCB, bIsCTLFixed, m_bOldCtl); + SupportHdl(*m_xCTLSupportCB); + } + // second check if CJK must be enabled + // #103299# - if CJK support is not readonly + if(!pLangConfig->aLanguageOptions.IsReadOnly(SvtLanguageOptions::E_ALLCJK)) + { + bool bIsCJKFixed = bool(nType & SvtScriptType::ASIAN); + lcl_checkLanguageCheckBox(*m_xAsianSupportCB, bIsCJKFixed, m_bOldAsian); + SupportHdl(*m_xAsianSupportCB); + } + + const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( + (eLang == LANGUAGE_USER_SYSTEM_CONFIG) ? MsLangId::getSystemLanguage() : eLang); + const OUString aDefaultID = "default"; + // Update the "Default ..." currency. + m_xCurrencyLB->remove_id(aDefaultID); + OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol(); + m_xCurrencyLB->insert(0, aDefaultCurr, &aDefaultID, nullptr, nullptr); + assert(m_xCurrencyLB->find_id(aDefaultID) != -1); + m_xCurrencyLB->set_active_text(aDefaultCurr); + + // obtain corresponding locale data + LanguageTag aLanguageTag( eLang); + LocaleDataWrapper aLocaleWrapper( aLanguageTag ); + + // update the decimal separator key of the related CheckBox + OUString sTempLabel(m_sDecimalSeparatorLabel); + sTempLabel = sTempLabel.replaceFirst("%1", aLocaleWrapper.getNumDecimalSep() ); + m_xDecimalSeparatorCB->set_label(sTempLabel); + + // update the date acceptance patterns + OUString aDatePatternsString = lcl_getDatePatternsConfigString( aLocaleWrapper); + m_bDatePatternsValid = true; + m_xDatePatternsED->set_text( aDatePatternsString); +} + +IMPL_LINK( OfaLanguagesTabPage, DatePatternsHdl, weld::Entry&, rEd, void ) +{ + const OUString aPatterns(rEd.get_text()); + OUStringBuffer aBuf( aPatterns); + sal_Int32 nChar = 0; + bool bValid = true; + bool bModified = false; + if (!aPatterns.isEmpty()) + { + for (sal_Int32 nIndex=0; nIndex >= 0 && bValid; ++nChar) + { + const OUString aPat( aPatterns.getToken( 0, ';', nIndex)); + if (aPat.isEmpty() && nIndex < 0) + { + // Indicating failure when about to append a pattern is too + // confusing. Empty patterns are ignored anyway when sequencing + // to SvtSysLocale. + continue; // for + } + else if (aPat.getLength() < 2) + bValid = false; + else + { + bool bY, bM, bD; + bY = bM = bD = false; + bool bSep = true; + for (sal_Int32 i = 0; i < aPat.getLength() && bValid; /*nop*/) + { + const sal_Int32 j = i; + const sal_uInt32 c = aPat.iterateCodePoints( &i); + // Only one Y,M,D per pattern, separated by any character(s). + switch (c) + { + case 'y': + case 'Y': + if (bY || !bSep) + bValid = false; + else if (c == 'y') + { + aBuf[nChar] = 'Y'; + bModified = true; + } + bY = true; + bSep = false; + break; + case 'm': + case 'M': + if (bM || !bSep) + bValid = false; + else if (c == 'm') + { + aBuf[nChar] = 'M'; + bModified = true; + } + bM = true; + bSep = false; + break; + case 'd': + case 'D': + if (bD || !bSep) + bValid = false; + else if (c == 'd') + { + aBuf[nChar] = 'D'; + bModified = true; + } + bD = true; + bSep = false; + break; + default: + // A pattern must not start with a separator (but + // may end with). + if (!(bY || bM || bD)) + bValid = false; + bSep = true; + } + nChar += i-j; + } + // At least one of Y,M,D + bValid &= (bY || bM || bD); + } + } + } + if (bModified) + rEd.replace_selection(aBuf.makeStringAndClear()); + if (bValid) + rEd.set_message_type(weld::EntryMessageType::Normal); + else + rEd.set_message_type(weld::EntryMessageType::Error); + m_bDatePatternsValid = bValid; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |