From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- cui/source/options/optgdlg.cxx | 1806 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1806 insertions(+) create mode 100644 cui/source/options/optgdlg.cxx (limited to 'cui/source/options/optgdlg.cxx') diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx new file mode 100644 index 000000000..b9402dfb2 --- /dev/null +++ b/cui/source/options/optgdlg.cxx @@ -0,0 +1,1806 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#if defined(_WIN32) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_FEATURE_BREAKPAD +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "optgdlg.hxx" +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#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; + +// 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_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_xCrashReport(m_xBuilder->weld_check_button("crashreport")) + , m_xQuickStarterFrame(m_xBuilder->weld_widget("quickstarter")) + , m_xHelpImproveLabel(m_xBuilder->weld_label("label7")) //"Help Improve" +#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")) + , m_xPerformFileExtCheck(m_xBuilder->weld_check_button("cbPerformFileExtCheck")) +#endif +{ + if (!lcl_HasSystemFilePicker()) + m_xFileDlgFrame->hide(); + else if (officecfg::Office::Common::Misc::UseSystemFileDialog::isReadOnly()) + { + m_xFileDlgROImage->show(); + m_xFileDlgCB->set_sensitive(false); + } + + m_xQuickLaunchCB->show(); + + //Only available in Win or if building the gtk systray +#if !defined(_WIN32) + m_xQuickStarterFrame->hide(); + //Hide frame label in case of no content + m_xHelpImproveLabel->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 OfaMiscTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique( pPage, pController, *rAttrSet ); +} + +bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet ) +{ + bool bModified = false; + std::shared_ptr batch(comphelper::ConfigurationChanges::create()); + + if ( m_xPopUpNoHelpCB->get_state_changed_from_saved() ) + officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::set(m_xPopUpNoHelpCB->get_active(), batch); + + if ( m_xExtHelpCB->get_state_changed_from_saved() ) + officecfg::Office::Common::Help::ExtendedTip::set(m_xExtHelpCB->get_active(), batch); + + 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() ) + { + officecfg::Office::Common::Misc::UseSystemFileDialog::set( !m_xFileDlgCB->get_active(), batch ); + bModified = true; + } + + if (m_xDocStatusCB->get_state_changed_from_saved()) + { + officecfg::Office::Common::Print::PrintingModifiesDocument::set(m_xDocStatusCB->get_active(), batch); + bModified = true; + } + + const SfxUInt16Item* pUInt16Item = GetOldItem( *rSet, SID_ATTR_YEAR2000 ); + sal_uInt16 nNum = static_cast(m_xYearValueField->get_text().toInt32()); + if ( pUInt16Item && pUInt16Item->GetValue() != nNum ) + { + bModified = true; + rSet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, nNum ) ); + } + +#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 + +#if defined(_WIN32) + if (m_xPerformFileExtCheck->get_state_changed_from_saved()) + { + officecfg::Office::Common::Misc::PerformFileExtCheck::set( + m_xPerformFileExtCheck->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 ) +{ + m_xExtHelpCB->set_active( officecfg::Office::Common::Help::Tip::get() && + officecfg::Office::Common::Help::ExtendedTip::get() ); + m_xExtHelpCB->save_state(); + m_xPopUpNoHelpCB->set_active( officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::get() ); + m_xPopUpNoHelpCB->save_state(); + m_xShowTipOfTheDay->set_active( officecfg::Office::Common::Misc::ShowTipOfTheDay::get() ); + m_xShowTipOfTheDay->save_state(); + m_xFileDlgCB->set_active( !officecfg::Office::Common::Misc::UseSystemFileDialog::get() ); + m_xFileDlgCB->save_state(); + + m_xDocStatusCB->set_active(officecfg::Office::Common::Print::PrintingModifiesDocument::get()); + m_xDocStatusCB->save_state(); + + if ( const SfxUInt16Item* pYearItem = rSet->GetItemIfSet( SID_ATTR_YEAR2000, false ) ) + { + m_xYearValueField->set_value( pYearItem->GetValue() ); + TwoFigureHdl(*m_xYearValueField); + } + else + m_xYearFrame->set_sensitive(false); + +#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 + + const SfxPoolItem* pItem = nullptr; + SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem ); + if ( SfxItemState::SET == eState ) + m_xQuickLaunchCB->set_active( static_cast(pItem)->GetValue() ); + else if ( SfxItemState::DISABLED == eState ) + { + // quickstart not installed + m_xQuickStarterFrame->hide(); + } + + m_xQuickLaunchCB->save_state(); + +#if defined(_WIN32) + m_xPerformFileExtCheck->set_active( + officecfg::Office::Common::Misc::PerformFileExtCheck::get()); + m_xPerformFileExtCheck->save_state(); + m_xPerformFileExtCheck->set_sensitive(!officecfg::Office::Common::Misc::PerformFileExtCheck::isReadOnly()); +#endif +} + +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) +{ + vcl::fileregistration::LaunchRegistrationUI(); +} +#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 > > ServiceVector; + + Reference mxForceFlagNameAccess; + ServiceVector maAvailableImplementations; + mutable bool mbHWAccelAvailable; + mutable bool mbHWAccelChecked; +}; + +CanvasSettings::CanvasSettings() : + mbHWAccelAvailable(false), + mbHWAccelChecked(false) +{ + try + { + Reference xConfigProvider( + css::configuration::theDefaultProvider::get( + comphelper::getProcessComponentContext())); + + Sequence aArgs1(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas"))} + })); + mxForceFlagNameAccess.set( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + aArgs1 ), + UNO_QUERY_THROW ); + + Sequence aArgs2(comphelper::InitAnyPropertySequence( + { + {"nodepath", Any(OUString("/org.openoffice.Office.Canvas/CanvasServiceList"))} + })); + Reference xNameAccess( + xConfigProvider->createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationAccess", + aArgs2 ), UNO_QUERY_THROW ); + Reference xHierarchicalNameAccess( + xNameAccess, UNO_QUERY_THROW); + + Sequence serviceNames = xNameAccess->getElementNames(); + const OUString* pCurr = serviceNames.getConstArray(); + const OUString* const pEnd = pCurr + serviceNames.getLength(); + while( pCurr != pEnd ) + { + Reference xEntryNameAccess( + xHierarchicalNameAccess->getByHierarchicalName(*pCurr), + UNO_QUERY ); + + if( xEntryNameAccess.is() ) + { + Sequence preferredImplementations; + if( xEntryNameAccess->getByName("PreferredImplementations") >>= preferredImplementations ) + maAvailableImplementations.emplace_back(*pCurr,preferredImplementations ); + } + + ++pCurr; + } + } + catch (const Exception&) + { + } +} + +bool CanvasSettings::IsHardwareAccelerationAvailable() const +{ + 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 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) + , 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")) + , m_xMoreIcons(m_xBuilder->weld_button("btnMoreIcons")) + , m_xRunGPTests(m_xBuilder->weld_button("btn_rungptest")) +{ + if (Application::GetToolkitName().startsWith("gtk")) + m_xMenuIconBox->hide(); + + m_xFontAntiAliasing->connect_toggled( LINK( this, OfaViewTabPage, OnAntialiasingToggled ) ); + + m_xUseSkia->connect_toggled(LINK(this, OfaViewTabPage, OnUseSkiaToggled)); + + // 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); + + m_xMoreIcons->set_from_icon_name("cmd/sc_additionsdialog.png"); + m_xMoreIcons->connect_clicked(LINK(this, OfaViewTabPage, OnMoreIconsClick)); + m_xRunGPTests->connect_clicked( LINK( this, OfaViewTabPage, OnRunGPTestClick)); +} + +OfaViewTabPage::~OfaViewTabPage() +{ +} + +IMPL_LINK_NOARG(OfaViewTabPage, OnRunGPTestClick, weld::Button&, void) +{ + GraphicsTestsDialog m_xGraphicsTestDialog(m_xContainer.get()); + m_xGraphicsTestDialog.run(); +} + +IMPL_STATIC_LINK_NOARG(OfaViewTabPage, OnMoreIconsClick, weld::Button&, void) +{ + css::uno::Sequence aArgs{ comphelper::makePropertyValue( + "AdditionsTag", OUString("Icons")) }; + comphelper::dispatchCommand(".uno:AdditionsDialog", aArgs); +} + +IMPL_LINK_NOARG( OfaViewTabPage, OnAntialiasingToggled, weld::Toggleable&, void ) +{ + bool bAAEnabled = m_xFontAntiAliasing->get_active(); + + m_xAAPointLimitLabel->set_sensitive(bAAEnabled); + m_xAAPointLimit->set_sensitive(bAAEnabled); +} + +IMPL_LINK_NOARG(OfaViewTabPage, OnUseSkiaToggled, weld::Toggleable&, void) +{ + UpdateSkiaStatus(); +} + +void OfaViewTabPage::HideSkiaWidgets() +{ + m_xUseSkia->hide(); + m_xForceSkiaRaster->hide(); + m_xSkiaStatusEnabled->hide(); + m_xSkiaStatusDisabled->hide(); +} + +void OfaViewTabPage::UpdateSkiaStatus() +{ +#if HAVE_FEATURE_SKIA + bool skiaHidden = true; + + // For now Skia is used mainly on Windows, enable the controls there. + if (Application::GetToolkitName() == "win") + skiaHidden = false; + // It can also be used on Linux, but only with the rarely used 'gen' backend. + if (Application::GetToolkitName() == "x11") + skiaHidden = false; + // OSX backend has Skia support too. + if (Application::GetToolkitName() == "osx") + skiaHidden = false; + + if (skiaHidden) + { + HideSkiaWidgets(); + return; + } + + // Easier than a custom translation string. + bool bEnabled = SkiaHelper::isVCLSkiaEnabled(); + m_xSkiaStatusEnabled->set_visible(bEnabled); + m_xSkiaStatusDisabled->set_visible(!bEnabled); + + // FIXME: should really add code to show a 'lock' icon here. + m_xUseSkia->set_sensitive(!officecfg::Office::Common::VCL::UseSkia::isReadOnly()); + m_xForceSkiaRaster->set_sensitive(m_xUseSkia->get_active() && !officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly()); + + // Technically the 'use hardware acceleration' option could be used to mean !forceSkiaRaster, but the implementation + // of the option is so tied to the implementation of the canvas module that it's simpler to ignore it. + UpdateHardwareAccelStatus(); +#else + HideSkiaWidgets(); +#endif +} + +std::unique_ptr OfaViewTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +bool OfaViewTabPage::FillItemSet( SfxItemSet* ) +{ + bool bModified = false; + bool bMenuOptModified = false; + bool bRepaintWindows(false); + std::shared_ptr xChanges(comphelper::ConfigurationChanges::create()); + + 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!" ); + } + officecfg::Office::Common::Misc::SidebarIconSize::set(static_cast(eSet), xChanges); + } + + 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!" ); + } + officecfg::Office::Common::Misc::NotebookbarIconSize::set(static_cast(eSet), xChanges); + } + + 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(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(eOldMiddleMouse) ) + { + pAppearanceCfg->SetMiddleMouseButton( static_cast(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()) + { + officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::set(m_xFontShowCB->get_active(), xChanges); + bModified = true; + } + + if (m_xMenuIconsLB->get_value_changed_from_saved()) + { + officecfg::Office::Common::View::Menu::IsSystemIconsInMenus::set(m_xMenuIconsLB->get_active() == 0, xChanges); + officecfg::Office::Common::View::Menu::ShowIconsInMenues::set(m_xMenuIconsLB->get_active() == 2, xChanges); + bModified = true; + bMenuOptModified = true; + bAppearanceChanged = true; + } + + if (m_xContextMenuShortcutsLB->get_value_changed_from_saved()) + { + officecfg::Office::Common::View::Menu::ShortcutsInContextMenus::set( + m_xContextMenuShortcutsLB->get_active() == 0 ? + TRISTATE_INDET : + static_cast(m_xContextMenuShortcutsLB->get_active() - 1), + xChanges); + 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() != SvtOptionsDrawinglayer::IsAntiAliasing()) + { + SvtOptionsDrawinglayer::SetAntiAliasing(m_xUseAntiAliase->get_active(), /*bTemporary*/false); + bModified = true; + bRepaintWindows = true; + } + } + + if (m_xUseSkia->get_state_changed_from_saved() || + m_xForceSkiaRaster->get_state_changed_from_saved()) + { + officecfg::Office::Common::VCL::UseSkia::set(m_xUseSkia->get_active(), xChanges); + officecfg::Office::Common::VCL::ForceSkiaRaster::set(m_xForceSkiaRaster->get_active(), xChanges); + bModified = true; + } + + xChanges->commit(); + + 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; + + 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(); + + ToolBoxButtonSize eSidebarIconSize = static_cast(officecfg::Office::Common::Misc::SidebarIconSize::get()); + if( eSidebarIconSize == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( eSidebarIconSize == ToolBoxButtonSize::Small ) + nSidebarSizeLB_InitialSelection = 1; + else if( eSidebarIconSize == ToolBoxButtonSize::Large ) + nSidebarSizeLB_InitialSelection = 2; + m_xSidebarIconSizeLB->set_active( nSidebarSizeLB_InitialSelection ); + m_xSidebarIconSizeLB->save_value(); + ToolBoxButtonSize eNotebookbarIconSize = static_cast(officecfg::Office::Common::Misc::NotebookbarIconSize::get()); + if( eNotebookbarIconSize == ToolBoxButtonSize::DontCare ) + ; // do nothing + else if( eNotebookbarIconSize == ToolBoxButtonSize::Small ) + nNotebookbarSizeLB_InitialSelection = 1; + else if( eNotebookbarIconSize == 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(pAppearanceCfg->GetSnapMode())); + m_xMousePosLB->save_value(); + + // Mouse Snap + m_xMouseMiddleLB->set_active(static_cast(pAppearanceCfg->GetMiddleMouseButton())); + m_xMouseMiddleLB->save_value(); + + m_xFontAntiAliasing->set_active( pAppearanceCfg->IsFontAntiAliasing() ); + m_xAAPointLimit->set_value(pAppearanceCfg->GetFontAntialiasingMinPixelHeight(), FieldUnit::PIXEL); + + // WorkingSet + m_xFontShowCB->set_active(officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::get()); + bool bSystemMenuIcons = officecfg::Office::Common::View::Menu::IsSystemIconsInMenus::get(); + bool bMenuIcons = officecfg::Office::Common::View::Menu::ShowIconsInMenues::get(); + m_xMenuIconsLB->set_active(bSystemMenuIcons ? 0 : (bMenuIcons ? 2 : 1)); + m_xMenuIconsLB->save_value(); + + TriState eContextMenuShortcuts = static_cast(officecfg::Office::Common::View::Menu::ShortcutsInContextMenus::get()); + bool bContextMenuShortcutsNonDefault = eContextMenuShortcuts == TRISTATE_FALSE || eContextMenuShortcuts == TRISTATE_TRUE; + m_xContextMenuShortcutsLB->set_active(bContextMenuShortcutsNonDefault ? eContextMenuShortcuts + 1 : 0); + m_xContextMenuShortcutsLB->save_value(); + + UpdateHardwareAccelStatus(); + m_xUseHardwareAccell->save_state(); + + { // #i95644# AntiAliasing + if(SvtOptionsDrawinglayer::IsAAPossibleOnThisSystem()) + { + m_xUseAntiAliase->set_active(SvtOptionsDrawinglayer::IsAntiAliasing()); + } + else + { + m_xUseAntiAliase->set_active(false); + m_xUseAntiAliase->set_sensitive(false); + } + + m_xUseAntiAliase->save_state(); + } + + m_xUseSkia->set_active(officecfg::Office::Common::VCL::UseSkia::get()); + m_xForceSkiaRaster->set_active(officecfg::Office::Common::VCL::ForceSkiaRaster::get()); + m_xUseSkia->save_state(); + m_xForceSkiaRaster->save_state(); + + m_xFontAntiAliasing->save_state(); + m_xAAPointLimit->save_value(); + m_xFontShowCB->save_state(); + + OnAntialiasingToggled(*m_xFontAntiAliasing); + UpdateSkiaStatus(); +} + +void OfaViewTabPage::UpdateHardwareAccelStatus() +{ + // #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); + } +#if HAVE_FEATURE_SKIA + m_xUseHardwareAccell->set_sensitive(!m_xUseSkia->get_active()); +#endif +} + +struct LanguageConfig_Impl +{ + SvtCTLOptions aCTLLanguageOptions; + SvtSysLocaleOptions aSysLocaleOptions; + SvtLinguConfig aLinguConfig; +}; + +static bool bLanguageCurrentDoc_Impl = false; + +// some things we'll need... +constexpr OUStringLiteral sAccessSrvc = u"com.sun.star.configuration.ConfigurationAccess"; +constexpr OUStringLiteral sAccessUpdSrvc = u"com.sun.star.configuration.ConfigurationUpdateAccess"; +constexpr OUStringLiteral sInstalledLocalesPath = u"org.openoffice.Setup/Office/InstalledLocales"; +constexpr OUStringLiteral sUserLocalePath = u"org.openoffice.Office.Linguistic/General"; +constexpr OUStringLiteral sUserLocaleKey = u"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 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())); + // find out which locales are currently installed and add them to the listbox + Sequence< Any > theArgs{ Any(NamedValue("nodepath", Any(OUString(sInstalledLocalesPath)))) }; + Reference< XNameAccess > theNameAccess( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + seqInstalledLanguages = theNameAccess->getElementNames(); + LanguageType aLang = LANGUAGE_DONTKNOW; + std::vector< std::pair > aUILanguages; + for (sal_Int32 i=0; iappend(OUString::number(nGroupID), sGroupName); + } + + m_xUserInterfaceLB->set_active(0); + + // find out whether the user has a specific locale specified + Sequence< Any > theArgs2{ Any(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(weld::toId(v), aStr_); + } + + m_xCurrencyLB->set_active(0); + + m_xLocaleSettingLB->connect_changed( LINK( this, OfaLanguagesTabPage, LocaleSettingHdl ) ); + m_xDatePatternsED->connect_changed( LINK( this, OfaLanguagesTabPage, DatePatternsHdl ) ); + + Link aLink( LINK( this, OfaLanguagesTabPage, SupportHdl ) ); + m_xAsianSupportCB->connect_toggled( aLink ); + m_xCTLSupportCB->connect_toggled( aLink ); + + m_bOldAsian = SvtCJKOptions::IsAnyEnabled(); + m_xAsianSupportCB->set_active(m_bOldAsian); + m_xAsianSupportCB->save_state(); + bool bReadonly = SvtCJKOptions::IsReadOnly(SvtCJKOptions::E_ALL); + m_xAsianSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xAsianSupportCB); + + m_bOldCtl = pLangConfig->aCTLLanguageOptions.IsCTLFontEnabled(); + m_xCTLSupportCB->set_active(m_bOldCtl); + m_xCTLSupportCB->save_state(); + bReadonly = pLangConfig->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::E_CTLFONT); + m_xCTLSupportCB->set_sensitive(!bReadonly); + SupportHdl(*m_xCTLSupportCB); + + m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange() ); +} + +OfaLanguagesTabPage::~OfaLanguagesTabPage() +{ +} + +std::unique_ptr OfaLanguagesTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet ) +{ + return std::make_unique(pPage, pController, *rAttrSet); +} + +static void lcl_Update(std::unique_ptr pInvalidItems[], std::unique_ptr 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->aCTLLanguageOptions.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->aCTLLanguageOptions.SetCTLSequenceCheckingRestricted(bOn); + pLangConfig->aCTLLanguageOptions.SetCTLSequenceChecking(bOn); + pLangConfig->aCTLLanguageOptions.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{ Any(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 : weld::fromId(sId); + 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( u"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( u"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( u"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(); + SvtCJKOptions::SetAll(bChecked); + + //iterate over all bindings to invalidate vertical text direction + const sal_uInt16 STATE_COUNT = 2; + + std::unique_ptr 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 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->aCTLLanguageOptions.SetCTLFontEnabled( m_xCTLSupportCB->get_active() ); + + const sal_uInt16 STATE_COUNT = 1; + std::unique_ptr pBoolItems[STATE_COUNT]; + pBoolItems[0].reset(new SfxBoolItem(SID_CTLFONT_STATE, false)); + std::unique_ptr 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->aCTLLanguageOptions.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 + const NfCurrencyEntry* pCurr = nullptr; + OUString sCurrency = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString(); + if ( !sCurrency.isEmpty() ) + { + LanguageType eLang; + OUString aAbbrev; + SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( aAbbrev, eLang, sCurrency ); + pCurr = SvNumberFormatter::GetCurrencyEntry( aAbbrev, eLang ); + } + // if pCurr==nullptr the SYSTEM entry is selected + OUString sId = !pCurr ? OUString("default") : weld::toId(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(u"DefaultLocale"); + Locale aLocale; + aWestLang >>= aLocale; + + eCurLang = LanguageTag::convertToLanguageType( aLocale, false); + + aCJKLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale_CJK"); + aLocale = Locale(); + aCJKLang >>= aLocale; + eCurLangCJK = LanguageTag::convertToLanguageType( aLocale, false); + + aCTLLang = pLangConfig->aLinguConfig.GetProperty(u"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); + if( const SvxLanguageItem* pLangItem = rSet->GetItemIfSet(SID_ATTR_LANGUAGE, false)) + { + LanguageType eTempCurLang = pLangItem->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLang, css::i18n::ScriptType::LATIN) != eTempCurLang) + eCurLang = eTempCurLang; + } + + if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CJK_LANGUAGE, false)) + { + LanguageType eTempCurLang = pLang->GetValue(); + if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCJK, css::i18n::ScriptType::ASIAN) != eTempCurLang) + eCurLangCJK = eTempCurLang; + } + + if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CTL_LANGUAGE, false)) + { + LanguageType eTempCurLang = 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( u"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 SfxBoolItem* pLang = rSet->GetItemIfSet(SID_SET_DOCUMENT_LANGUAGE, false ); + if ( pLang && pLang->GetValue() ) + { + m_xWesternLanguageLB->grab_focus(); + m_xCurrentDocCB->set_sensitive(true); + m_xCurrentDocCB->set_active(true); + } +} + +IMPL_LINK(OfaLanguagesTabPage, SupportHdl, weld::Toggleable&, rBox, void) +{ + bool bCheck = rBox.get_active(); + if ( m_xAsianSupportCB.get() == &rBox ) + { + bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly(u"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(u"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->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::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(!SvtCJKOptions::IsReadOnly(SvtCJKOptions::E_ALL)) + { + 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::getConfiguredSystemLanguage() : 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 + LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang) )); + + // 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; + if (aPat.getLength() == 3) + { + // Disallow a pattern that would match a numeric input with + // decimal separator, like M.D + const LanguageType eLang = m_xLocaleSettingLB->get_active_id(); + const LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang))); + if ( aPat[1] == aLocaleWrapper.getNumDecimalSep().toChar() + || aPat[1] == aLocaleWrapper.getNumDecimalSepAlt().toChar()) + { + bValid = false; + } + } + 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) + { + // gtk3 keeps the cursor position on equal length set_text() but at + // least the 'gen' backend does not and resets to 0. + const int nCursorPos = rEd.get_position(); + rEd.set_text(aBuf.makeStringAndClear()); + rEd.set_position(nCursorPos); + } + 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: */ -- cgit v1.2.3