Use correct object
[LibreOffice.git] / cui / source / options / optgdlg.cxx
blob65717c944956d518603a978807f2d6f8ce24c1af
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
21 #include <svl/numformat.hxx>
22 #include <svl/zforlist.hxx>
23 #include <svl/currencytable.hxx>
24 #include <svtools/langhelp.hxx>
25 #include <unotools/lingucfg.hxx>
26 #if defined(_WIN32)
27 #include <unotools/resmgr.hxx>
28 #endif
29 #include <sfx2/bindings.hxx>
30 #include <sfx2/viewfrm.hxx>
31 #include <i18nlangtag/mslangid.hxx>
32 #include <i18nlangtag/languagetag.hxx>
33 #include <unotools/compatibility.hxx>
34 #include <svl/languageoptions.hxx>
35 #include <svl/cjkoptions.hxx>
36 #include <svl/ctloptions.hxx>
37 #include <svtools/miscopt.hxx>
38 #include <unotools/syslocaleoptions.hxx>
39 #include <sfx2/objsh.hxx>
40 #include <comphelper/propertysequence.hxx>
41 #include <comphelper/propertyvalue.hxx>
42 #include <svtools/langtab.hxx>
43 #include <editeng/unolingu.hxx>
44 #include <editeng/langitem.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/string.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <editeng/editids.hrc>
49 #include <svx/svxids.hrc>
50 #include <svl/intitem.hxx>
51 #include <svl/voiditem.hxx>
52 #include <GraphicsTestsDialog.hxx>
53 #include <unotools/searchopt.hxx>
54 #include <sal/log.hxx>
55 #include <officecfg/Office/Common.hxx>
56 #include <officecfg/Setup.hxx>
57 #include <comphelper/configuration.hxx>
58 #include <comphelper/diagnose_ex.hxx>
59 #if HAVE_FEATURE_BREAKPAD
60 #include <desktop/crashreport.hxx>
61 #endif
63 #include <com/sun/star/configuration/theDefaultProvider.hpp>
64 #include <com/sun/star/container/XNameAccess.hpp>
65 #include <com/sun/star/container/XNameReplace.hpp>
66 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
67 #include <com/sun/star/beans/NamedValue.hpp>
68 #include <com/sun/star/beans/PropertyAttribute.hpp>
69 #include <com/sun/star/beans/XPropertySet.hpp>
70 #include <com/sun/star/util/XChangesBatch.hpp>
71 #include <com/sun/star/uno/Any.hxx>
72 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
73 #include <com/sun/star/container/XSet.hpp>
74 #include <com/sun/star/i18n/ScriptType.hpp>
75 #include <com/sun/star/office/Quickstart.hpp>
76 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
77 #include <comphelper/dispatchcommand.hxx>
79 #include <vcl/vclenum.hxx>
80 #include <vcl/svapp.hxx>
81 #include <vcl/settings.hxx>
82 #include <vcl/window.hxx>
83 #include <vcl/IconThemeInfo.hxx>
84 #include <vcl/skia/SkiaHelper.hxx>
85 #include <bitmaps.hlst>
87 #include "optgdlg.hxx"
88 #include <svtools/apearcfg.hxx>
89 #include <svtools/optionsdrawinglayer.hxx>
90 #include <svtools/restartdialog.hxx>
91 #include <svtools/imgdef.hxx>
92 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
93 #include <vcl/unohelp2.hxx>
95 #if defined(_WIN32)
96 #include <systools/win32/winstoreutil.hxx>
97 #include <vcl/fileregistration.hxx>
98 #endif
99 using namespace ::com::sun::star::uno;
100 using namespace ::com::sun::star::lang;
101 using namespace ::com::sun::star::beans;
102 using namespace ::com::sun::star::container;
103 using namespace ::com::sun::star::util;
104 using namespace ::utl;
106 // class OfaMiscTabPage --------------------------------------------------
108 DeactivateRC OfaMiscTabPage::DeactivatePage( SfxItemSet* pSet_ )
110 if ( pSet_ )
111 FillItemSet( pSet_ );
112 return DeactivateRC::LeavePage;
115 namespace
117 const OUString & impl_SystemFileOpenServiceName()
119 #if defined(_WIN32)
120 static constexpr OUString gPicker = u"com.sun.star.ui.dialogs.SystemFilePicker"_ustr;
121 return gPicker;
122 #elif defined MACOSX
123 static constexpr OUString gPicker = u"com.sun.star.ui.dialogs.AquaFilePicker"_ustr;
124 return gPicker;
125 #else
126 return EMPTY_OUSTRING;
127 #endif
130 bool lcl_HasSystemFilePicker()
132 if( Application::hasNativeFileSelection() )
133 return true;
135 // Otherwise fall-back on querying services
136 bool bRet = false;
137 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
139 Reference< XContentEnumerationAccess > xEnumAccess( xFactory, UNO_QUERY );
140 Reference< XSet > xSet( xFactory, UNO_QUERY );
142 if ( ! xEnumAccess.is() || ! xSet.is() )
143 return bRet;
147 const OUString& aFileService = impl_SystemFileOpenServiceName();
148 Reference< XEnumeration > xEnum = xEnumAccess->createContentEnumeration( aFileService );
149 if ( xEnum.is() && xEnum->hasMoreElements() )
150 bRet = true;
152 catch (const IllegalArgumentException&)
155 catch (const ElementExistException&)
158 return bRet;
162 OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
163 : SfxTabPage(pPage, pController, u"cui/ui/optgeneralpage.ui"_ustr, u"OptGeneralPage"_ustr, &rSet)
164 , m_xExtHelpCB(m_xBuilder->weld_check_button(u"exthelp"_ustr))
165 , m_xExtHelpImg(m_xBuilder->weld_widget(u"lockexthelp"_ustr))
166 , m_xPopUpNoHelpCB(m_xBuilder->weld_check_button(u"popupnohelp"_ustr))
167 , m_xPopUpNoHelpImg(m_xBuilder->weld_widget(u"lockpopupnohelp"_ustr))
168 , m_xShowTipOfTheDay(m_xBuilder->weld_check_button(u"cbShowTipOfTheDay"_ustr))
169 , m_xShowTipOfTheDayImg(m_xBuilder->weld_widget(u"lockcbShowTipOfTheDay"_ustr))
170 , m_xFileDlgFrame(m_xBuilder->weld_widget(u"filedlgframe"_ustr))
171 , m_xFileDlgROImage(m_xBuilder->weld_widget(u"lockimage"_ustr))
172 , m_xFileDlgCB(m_xBuilder->weld_check_button(u"filedlg"_ustr))
173 , m_xDocStatusCB(m_xBuilder->weld_check_button(u"docstatus"_ustr))
174 , m_xDocStatusImg(m_xBuilder->weld_widget(u"lockdocstatus"_ustr))
175 , m_xYearFrame(m_xBuilder->weld_widget(u"yearframe"_ustr))
176 , m_xYearLabel(m_xBuilder->weld_label(u"yearslabel"_ustr))
177 , m_xYearValueField(m_xBuilder->weld_spin_button(u"year"_ustr))
178 , m_xToYearFT(m_xBuilder->weld_label(u"toyear"_ustr))
179 , m_xYearFrameImg(m_xBuilder->weld_widget(u"lockyears"_ustr))
180 #if HAVE_FEATURE_BREAKPAD
181 , m_xPrivacyFrame(m_xBuilder->weld_widget("privacyframe"))
182 , m_xCrashReport(m_xBuilder->weld_check_button("crashreport"))
183 , m_xCrashReportImg(m_xBuilder->weld_widget("lockcrashreport"))
184 #endif
185 #if defined(_WIN32)
186 , m_xQuickStarterFrame(m_xBuilder->weld_widget("quickstarter"))
187 , m_xQuickLaunchCB(m_xBuilder->weld_check_button("quicklaunch"))
188 , m_xQuickLaunchImg(m_xBuilder->weld_widget("lockquicklaunch"))
189 , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc"))
190 , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles"))
191 , m_xPerformFileExtCheck(m_xBuilder->weld_check_button("cbPerformFileExtCheck"))
192 , m_xPerformFileExtImg(m_xBuilder->weld_widget("lockcbPerformFileExtCheck"))
193 #endif
195 #if HAVE_FEATURE_BREAKPAD
196 m_xPrivacyFrame->show();
197 #endif
199 #if defined(_WIN32)
200 // Store-packaged apps (located under the protected Program Files\WindowsApps) can't use normal
201 // shell shortcuts to their exe. TODO: show a button to open "Startup Apps" system applet?
202 if (!sal::systools::IsStorePackagedApp())
203 m_xQuickStarterFrame->show();
205 m_xFileAssocFrame->show();
206 m_xFileAssocBtn->connect_clicked(LINK(this, OfaMiscTabPage, FileAssocClick));
207 #endif
209 m_aStrDateInfo = m_xToYearFT->get_label();
210 m_xYearValueField->connect_value_changed( LINK( this, OfaMiscTabPage, TwoFigureHdl ) );
212 SetExchangeSupport();
215 OfaMiscTabPage::~OfaMiscTabPage()
219 std::unique_ptr<SfxTabPage> OfaMiscTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
221 return std::make_unique<OfaMiscTabPage>( pPage, pController, *rAttrSet );
224 OUString OfaMiscTabPage::GetAllStrings()
226 OUString sAllStrings;
227 OUString labels[] = { u"label1"_ustr, u"label2"_ustr, u"label4"_ustr, u"label5"_ustr, u"yearslabel"_ustr,
228 u"toyear"_ustr, u"label7"_ustr, u"label8"_ustr, u"label9"_ustr };
230 for (const auto& label : labels)
232 if (const auto pString = m_xBuilder->weld_label(label))
233 sAllStrings += pString->get_label() + " ";
236 OUString checkButton[]
237 = { u"exthelp"_ustr, u"popupnohelp"_ustr, u"cbShowTipOfTheDay"_ustr, u"filedlg"_ustr,
238 u"docstatus"_ustr, u"crashreport"_ustr, u"quicklaunch"_ustr, u"cbPerformFileExtCheck"_ustr };
240 for (const auto& check : checkButton)
242 if (const auto pString = m_xBuilder->weld_check_button(check))
243 sAllStrings += pString->get_label() + " ";
246 if (const auto pString = m_xBuilder->weld_button(u"assocfiles"_ustr))
247 sAllStrings += pString->get_label() + " ";
249 return sAllStrings.replaceAll("_", "");
252 bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet )
254 bool bModified = false;
255 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
257 if ( m_xPopUpNoHelpCB->get_state_changed_from_saved() )
258 officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::set(m_xPopUpNoHelpCB->get_active(), batch);
260 if ( m_xExtHelpCB->get_state_changed_from_saved() )
261 officecfg::Office::Common::Help::ExtendedTip::set(m_xExtHelpCB->get_active(), batch);
263 if ( m_xShowTipOfTheDay->get_state_changed_from_saved() )
265 officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_xShowTipOfTheDay->get_active(), batch);
266 bModified = true;
269 if ( m_xFileDlgCB->get_state_changed_from_saved() )
271 officecfg::Office::Common::Misc::UseSystemFileDialog::set( !m_xFileDlgCB->get_active(), batch );
272 bModified = true;
275 if (m_xDocStatusCB->get_state_changed_from_saved())
277 officecfg::Office::Common::Print::PrintingModifiesDocument::set(m_xDocStatusCB->get_active(), batch);
278 bModified = true;
281 const SfxUInt16Item* pUInt16Item = GetOldItem( *rSet, SID_ATTR_YEAR2000 );
282 sal_uInt16 nNum = static_cast<sal_uInt16>(m_xYearValueField->get_text().toInt32());
283 if ( pUInt16Item && pUInt16Item->GetValue() != nNum )
285 bModified = true;
286 rSet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, nNum ) );
289 #if HAVE_FEATURE_BREAKPAD
290 if (m_xCrashReport->get_state_changed_from_saved())
292 officecfg::Office::Common::Misc::CrashReport::set(m_xCrashReport->get_active(), batch);
293 bModified = true;
295 #endif
297 #if defined(_WIN32)
298 if (m_xPerformFileExtCheck->get_state_changed_from_saved())
300 officecfg::Office::Common::Misc::PerformFileExtCheck::set(
301 m_xPerformFileExtCheck->get_active(), batch);
302 bModified = true;
305 if( m_xQuickLaunchCB->get_state_changed_from_saved())
307 rSet->Put(SfxBoolItem(SID_ATTR_QUICKLAUNCHER, m_xQuickLaunchCB->get_active()));
308 bModified = true;
310 #endif
312 batch->commit();
314 return bModified;
317 void OfaMiscTabPage::Reset( const SfxItemSet* rSet )
319 bool bEnable = !officecfg::Office::Common::Help::ExtendedTip::isReadOnly();
320 m_xExtHelpCB->set_active( officecfg::Office::Common::Help::Tip::get() &&
321 officecfg::Office::Common::Help::ExtendedTip::get() );
322 m_xExtHelpCB->set_sensitive(bEnable);
323 m_xExtHelpImg->set_visible(!bEnable);
324 m_xExtHelpCB->save_state();
326 bEnable = !officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::isReadOnly();
327 m_xPopUpNoHelpCB->set_active( officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::get() );
328 m_xPopUpNoHelpCB->set_sensitive(bEnable);
329 m_xPopUpNoHelpImg->set_visible(!bEnable);
330 m_xPopUpNoHelpCB->save_state();
332 bEnable = !officecfg::Office::Common::Misc::ShowTipOfTheDay::isReadOnly();
333 m_xShowTipOfTheDay->set_active( officecfg::Office::Common::Misc::ShowTipOfTheDay::get() );
334 m_xShowTipOfTheDay->set_sensitive(bEnable);
335 m_xShowTipOfTheDayImg->set_visible(!bEnable);
336 m_xShowTipOfTheDay->save_state();
338 if (!lcl_HasSystemFilePicker())
339 m_xFileDlgFrame->hide();
340 else
342 bEnable = !officecfg::Office::Common::Misc::UseSystemFileDialog::isReadOnly();
343 m_xFileDlgCB->set_sensitive(bEnable);
344 m_xFileDlgROImage->set_visible(!bEnable);
346 m_xFileDlgCB->set_active(!officecfg::Office::Common::Misc::UseSystemFileDialog::get());
347 m_xFileDlgCB->save_state();
349 bEnable = !officecfg::Office::Common::Print::PrintingModifiesDocument::isReadOnly();
350 m_xDocStatusCB->set_active(officecfg::Office::Common::Print::PrintingModifiesDocument::get());
351 m_xDocStatusCB->set_sensitive(bEnable);
352 m_xDocStatusImg->set_visible(!bEnable);
353 m_xDocStatusCB->save_state();
355 bEnable = !officecfg::Office::Common::DateFormat::TwoDigitYear::isReadOnly();
356 m_xYearLabel->set_sensitive(bEnable);
357 m_xYearValueField->set_sensitive(bEnable);
358 m_xToYearFT->set_sensitive(bEnable);
359 m_xYearFrameImg->set_visible(!bEnable);
361 if ( const SfxUInt16Item* pYearItem = rSet->GetItemIfSet( SID_ATTR_YEAR2000, false ) )
363 m_xYearValueField->set_value( pYearItem->GetValue() );
364 TwoFigureHdl(*m_xYearValueField);
366 else
367 m_xYearFrame->set_sensitive(false);
369 #if HAVE_FEATURE_BREAKPAD
370 m_xCrashReport->set_active(officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::IsDumpEnable());
371 m_xCrashReport->set_sensitive(!officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable());
372 m_xCrashReportImg->set_visible(officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable());
373 m_xCrashReport->save_state();
374 #endif
376 #if defined(_WIN32)
377 const SfxPoolItem* pItem = nullptr;
378 SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem );
379 if ( SfxItemState::SET == eState )
380 m_xQuickLaunchCB->set_active( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
381 else if ( SfxItemState::DISABLED == eState )
383 // quickstart not installed
384 m_xQuickStarterFrame->hide();
387 m_xQuickLaunchCB->save_state();
389 m_xPerformFileExtCheck->set_active(
390 officecfg::Office::Common::Misc::PerformFileExtCheck::get());
391 m_xPerformFileExtCheck->save_state();
392 m_xPerformFileExtCheck->set_sensitive(!officecfg::Office::Common::Misc::PerformFileExtCheck::isReadOnly());
393 m_xPerformFileExtImg->set_visible(officecfg::Office::Common::Misc::PerformFileExtCheck::isReadOnly());
394 #endif
397 IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void )
399 OUString aOutput( m_aStrDateInfo );
400 OUString aStr( m_xYearValueField->get_text() );
401 sal_Int32 nNum = aStr.toInt32();
402 if ( aStr.getLength() != 4 || nNum < m_xYearValueField->get_min() || nNum > m_xYearValueField->get_max() )
403 aOutput += "????";
404 else
406 nNum += 99;
407 aOutput += OUString::number( nNum );
409 m_xToYearFT->set_label( aOutput );
412 #if defined(_WIN32)
413 IMPL_STATIC_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void)
415 vcl::fileregistration::LaunchRegistrationUI();
417 #endif
419 class CanvasSettings
421 public:
422 CanvasSettings();
424 bool IsHardwareAccelerationEnabled() const;
425 bool IsHardwareAccelerationAvailable() const;
426 bool IsHardwareAccelerationRO() const;
427 void EnabledHardwareAcceleration( bool _bEnabled ) const;
429 private:
430 typedef std::vector< std::pair<OUString,Sequence<OUString> > > ServiceVector;
432 Reference<XNameAccess> mxForceFlagNameAccess;
433 ServiceVector maAvailableImplementations;
434 mutable bool mbHWAccelAvailable;
435 mutable bool mbHWAccelChecked;
438 CanvasSettings::CanvasSettings() :
439 mbHWAccelAvailable(false),
440 mbHWAccelChecked(false)
444 Reference<XMultiServiceFactory> xConfigProvider(
445 css::configuration::theDefaultProvider::get(
446 comphelper::getProcessComponentContext()));
448 Sequence<Any> aArgs1(comphelper::InitAnyPropertySequence(
450 {"nodepath", Any(u"/org.openoffice.Office.Canvas"_ustr)}
451 }));
452 mxForceFlagNameAccess.set(
453 xConfigProvider->createInstanceWithArguments(
454 u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr,
455 aArgs1 ),
456 UNO_QUERY_THROW );
458 Sequence<Any> aArgs2(comphelper::InitAnyPropertySequence(
460 {"nodepath", Any(u"/org.openoffice.Office.Canvas/CanvasServiceList"_ustr)}
461 }));
462 Reference<XNameAccess> xNameAccess(
463 xConfigProvider->createInstanceWithArguments(
464 u"com.sun.star.configuration.ConfigurationAccess"_ustr,
465 aArgs2 ), UNO_QUERY_THROW );
466 Reference<XHierarchicalNameAccess> xHierarchicalNameAccess(
467 xNameAccess, UNO_QUERY_THROW);
469 for (auto& serviceName : xNameAccess->getElementNames())
471 Reference<XNameAccess> xEntryNameAccess(
472 xHierarchicalNameAccess->getByHierarchicalName(serviceName),
473 UNO_QUERY );
475 if( xEntryNameAccess.is() )
477 Sequence<OUString> preferredImplementations;
478 if( xEntryNameAccess->getByName(u"PreferredImplementations"_ustr) >>= preferredImplementations )
479 maAvailableImplementations.emplace_back(serviceName, preferredImplementations);
483 catch (const Exception&)
488 bool CanvasSettings::IsHardwareAccelerationAvailable() const
490 if( !mbHWAccelChecked )
492 mbHWAccelChecked = true;
494 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
496 // check whether any of the service lists has an
497 // implementation that presents the "HardwareAcceleration" property
498 for (auto const& availableImpl : maAvailableImplementations)
500 for (auto& currImpl : availableImpl.second)
504 Reference<XPropertySet> xPropSet( xFactory->createInstance(
505 currImpl.trim() ),
506 UNO_QUERY_THROW );
507 bool bHasAccel(false);
508 if( xPropSet->getPropertyValue(u"HardwareAcceleration"_ustr) >>= bHasAccel )
509 if( bHasAccel )
511 mbHWAccelAvailable = true;
512 return mbHWAccelAvailable;
515 catch (const Exception&)
522 return mbHWAccelAvailable;
525 bool CanvasSettings::IsHardwareAccelerationEnabled() const
527 bool bForceLastEntry(false);
528 if( !mxForceFlagNameAccess.is() )
529 return true;
531 if( !(mxForceFlagNameAccess->getByName(u"ForceSafeServiceImpl"_ustr) >>= bForceLastEntry) )
532 return true;
534 return !bForceLastEntry;
537 bool CanvasSettings::IsHardwareAccelerationRO() const
539 Reference< XPropertySet > xSet(mxForceFlagNameAccess, UNO_QUERY);
540 if (!xSet.is())
541 return true;
543 Reference< XPropertySetInfo > xInfo = xSet->getPropertySetInfo();
544 Property aProp = xInfo->getPropertyByName(u"ForceSafeServiceImpl"_ustr);
545 return ((aProp.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY);
548 void CanvasSettings::EnabledHardwareAcceleration( bool _bEnabled ) const
550 Reference< XNameReplace > xNameReplace(
551 mxForceFlagNameAccess, UNO_QUERY );
553 if( !xNameReplace.is() )
554 return;
556 xNameReplace->replaceByName( u"ForceSafeServiceImpl"_ustr, Any(!_bEnabled) );
558 Reference< XChangesBatch > xChangesBatch(
559 mxForceFlagNameAccess, UNO_QUERY );
561 if( !xChangesBatch.is() )
562 return;
564 xChangesBatch->commitChanges();
567 // class OfaViewTabPage --------------------------------------------------
569 static bool DisplayNameCompareLessThan(const vcl::IconThemeInfo& rInfo1, const vcl::IconThemeInfo& rInfo2)
571 return rInfo1.GetDisplayName().compareTo(rInfo2.GetDisplayName()) < 0;
574 OfaViewTabPage::OfaViewTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
575 : SfxTabPage(pPage, pController, u"cui/ui/optviewpage.ui"_ustr, u"OptViewPage"_ustr, &rSet)
576 , nSizeLB_InitialSelection(0)
577 , nSidebarSizeLB_InitialSelection(0)
578 , nNotebookbarSizeLB_InitialSelection(0)
579 , nStyleLB_InitialSelection(0)
580 , pCanvasSettings(new CanvasSettings)
581 , m_xIconSizeLabel(m_xBuilder->weld_label(u"label14"_ustr))
582 , m_xIconSizeLB(m_xBuilder->weld_combo_box(u"iconsize"_ustr))
583 , m_xIconSizeImg(m_xBuilder->weld_widget(u"lockiconsize"_ustr))
584 , m_xSidebarIconSizeLabel(m_xBuilder->weld_label(u"label9"_ustr))
585 , m_xSidebarIconSizeLB(m_xBuilder->weld_combo_box(u"sidebariconsize"_ustr))
586 , m_xSidebarIconSizeImg(m_xBuilder->weld_widget(u"locksidebariconsize"_ustr))
587 , m_xNotebookbarIconSizeLabel(m_xBuilder->weld_label(u"label8"_ustr))
588 , m_xNotebookbarIconSizeLB(m_xBuilder->weld_combo_box(u"notebookbariconsize"_ustr))
589 , m_xNotebookbarIconSizeImg(m_xBuilder->weld_widget(u"locknotebookbariconsize"_ustr))
590 , m_xDarkModeFrame(m_xBuilder->weld_widget(u"darkmode"_ustr))
591 , m_xAppearanceStyleLabel(m_xBuilder->weld_label(u"label7"_ustr))
592 , m_xAppearanceStyleLB(m_xBuilder->weld_combo_box(u"appearance"_ustr))
593 , m_xAppearanceStyleImg(m_xBuilder->weld_widget(u"lockappearance"_ustr))
594 , m_xIconStyleLabel(m_xBuilder->weld_label(u"label6"_ustr))
595 , m_xIconStyleLB(m_xBuilder->weld_combo_box(u"iconstyle"_ustr))
596 , m_xIconStyleImg(m_xBuilder->weld_widget(u"lockiconstyle"_ustr))
597 , m_xFontAntiAliasing(m_xBuilder->weld_check_button(u"aafont"_ustr))
598 , m_xFontAntiAliasingImg(m_xBuilder->weld_widget(u"lockaafont"_ustr))
599 , m_xAAPointLimitLabel(m_xBuilder->weld_label(u"aafrom"_ustr))
600 , m_xAAPointLimitLabelImg(m_xBuilder->weld_widget(u"lockaafrom"_ustr))
601 , m_xAAPointLimit(m_xBuilder->weld_metric_spin_button(u"aanf"_ustr, FieldUnit::PIXEL))
602 , m_xFontShowCB(m_xBuilder->weld_check_button(u"showfontpreview"_ustr))
603 , m_xFontShowImg(m_xBuilder->weld_widget(u"lockshowfontpreview"_ustr))
604 , m_xUseHardwareAccell(m_xBuilder->weld_check_button(u"useaccel"_ustr))
605 , m_xUseHardwareAccellImg(m_xBuilder->weld_widget(u"lockuseaccel"_ustr))
606 , m_xUseAntiAliase(m_xBuilder->weld_check_button(u"useaa"_ustr))
607 , m_xUseAntiAliaseImg(m_xBuilder->weld_widget(u"lockuseaa"_ustr))
608 , m_xUseSkia(m_xBuilder->weld_check_button(u"useskia"_ustr))
609 , m_xUseSkiaImg(m_xBuilder->weld_widget(u"lockuseskia"_ustr))
610 , m_xForceSkiaRaster(m_xBuilder->weld_check_button(u"forceskiaraster"_ustr))
611 , m_xForceSkiaRasterImg(m_xBuilder->weld_widget(u"lockforceskiaraster"_ustr))
612 , m_xSkiaStatusEnabled(m_xBuilder->weld_label(u"skiaenabled"_ustr))
613 , m_xSkiaStatusDisabled(m_xBuilder->weld_label(u"skiadisabled"_ustr))
614 , m_xSkiaLog(m_xBuilder->weld_button(u"btnSkialog"_ustr))
615 , m_xMouseMiddleLabel(m_xBuilder->weld_label(u"label12"_ustr))
616 , m_xMouseMiddleLB(m_xBuilder->weld_combo_box(u"mousemiddle"_ustr))
617 , m_xMouseMiddleImg(m_xBuilder->weld_widget(u"lockmousemiddle"_ustr))
618 , m_xMoreIcons(m_xBuilder->weld_button(u"btnMoreIcons"_ustr))
619 , m_xRunGPTests(m_xBuilder->weld_button(u"btn_rungptest"_ustr))
620 , m_sAutoStr(m_xIconStyleLB->get_text(0))
622 OUString sToolKitName(Application::GetToolkitName());
623 const bool bHasDarkMode = sToolKitName.startsWith("gtk") || sToolKitName == "osx" || sToolKitName == "win";
624 if (!bHasDarkMode)
625 m_xDarkModeFrame->hide();
627 m_xFontAntiAliasing->connect_toggled( LINK( this, OfaViewTabPage, OnAntialiasingToggled ) );
629 m_xUseSkia->connect_toggled(LINK(this, OfaViewTabPage, OnUseSkiaToggled));
630 m_xSkiaLog->connect_clicked(LINK(this, OfaViewTabPage, OnCopySkiaLog));
632 UpdateIconThemes();
634 m_xIconStyleLB->set_active(0);
636 m_xMoreIcons->connect_clicked(LINK(this, OfaViewTabPage, OnMoreIconsClick));
637 m_xRunGPTests->connect_clicked(LINK(this, OfaViewTabPage, OnRunGPTestClick));
639 // Hide "Run Graphics Test" button if Experimental Mode is off
640 if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
641 m_xRunGPTests->hide();
644 void OfaViewTabPage::UpdateIconThemes()
646 // Set known icon themes
647 m_xIconStyleLB->clear();
648 StyleSettings aStyleSettings = Application::GetSettings().GetStyleSettings();
649 mInstalledIconThemes = aStyleSettings.GetInstalledIconThemes();
650 std::sort(mInstalledIconThemes.begin(), mInstalledIconThemes.end(), DisplayNameCompareLessThan);
652 // Start with the automatically chosen icon theme
653 OUString autoThemeId = aStyleSettings.GetAutomaticallyChosenIconTheme();
654 const vcl::IconThemeInfo& autoIconTheme = vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, autoThemeId);
656 OUString entryForAuto = m_sAutoStr + " (" + autoIconTheme.GetDisplayName() + ")";
657 m_xIconStyleLB->append(u"auto"_ustr, entryForAuto); // index 0 means choose style automatically
659 // separate auto and other icon themes
660 m_xIconStyleLB->append_separator(u""_ustr);
662 for (auto const& installIconTheme : mInstalledIconThemes)
663 m_xIconStyleLB->append(installIconTheme.GetThemeId(), installIconTheme.GetDisplayName());
666 OfaViewTabPage::~OfaViewTabPage()
670 IMPL_LINK_NOARG(OfaViewTabPage, OnRunGPTestClick, weld::Button&, void)
672 GraphicsTestsDialog m_xGraphicsTestDialog(m_xContainer.get());
673 m_xGraphicsTestDialog.run();
676 IMPL_STATIC_LINK_NOARG(OfaViewTabPage, OnMoreIconsClick, weld::Button&, void)
678 css::uno::Sequence<css::beans::PropertyValue> aArgs{ comphelper::makePropertyValue(
679 u"AdditionsTag"_ustr, u"Icons"_ustr) };
680 comphelper::dispatchCommand(u".uno:AdditionsDialog"_ustr, aArgs);
683 IMPL_LINK_NOARG( OfaViewTabPage, OnAntialiasingToggled, weld::Toggleable&, void )
685 bool bAAEnabled = m_xFontAntiAliasing->get_active() && !officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::isReadOnly();
687 m_xAAPointLimitLabel->set_sensitive(bAAEnabled);
688 m_xAAPointLimit->set_sensitive(bAAEnabled);
691 IMPL_LINK_NOARG(OfaViewTabPage, OnUseSkiaToggled, weld::Toggleable&, void)
693 UpdateSkiaStatus();
696 IMPL_LINK_NOARG(OfaViewTabPage, OnCopySkiaLog, weld::Button&, void)
698 #if HAVE_FEATURE_SKIA
699 css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard =
700 css::datatransfer::clipboard::SystemClipboard::create(
701 comphelper::getProcessComponentContext());
702 OUString sInfo = SkiaHelper::readLog();
703 vcl::unohelper::TextDataObject::CopyStringTo(sInfo, xClipboard);
704 m_xSkiaLog->set_from_icon_name(RID_SVXBMP_COPY);
705 #endif
708 void OfaViewTabPage::HideSkiaWidgets()
710 m_xUseSkia->hide();
711 m_xForceSkiaRaster->hide();
712 m_xSkiaStatusEnabled->hide();
713 m_xSkiaStatusDisabled->hide();
714 m_xSkiaLog->hide();
717 void OfaViewTabPage::UpdateSkiaStatus()
719 #if HAVE_FEATURE_SKIA
720 bool skiaHidden = true;
722 // For now Skia is used mainly on Windows, enable the controls there.
723 if (Application::GetToolkitName() == "win")
724 skiaHidden = false;
725 // It can also be used on Linux, but only with the rarely used 'gen' backend.
726 if (Application::GetToolkitName() == "x11")
727 skiaHidden = false;
728 // OSX backend has Skia support too.
729 if (Application::GetToolkitName() == "osx")
730 skiaHidden = false;
732 if (skiaHidden)
734 HideSkiaWidgets();
735 return;
738 // Easier than a custom translation string.
739 bool bEnabled = SkiaHelper::isVCLSkiaEnabled();
740 m_xSkiaStatusEnabled->set_visible(bEnabled);
741 m_xSkiaStatusDisabled->set_visible(!bEnabled);
743 m_xUseSkia->set_sensitive(!officecfg::Office::Common::VCL::UseSkia::isReadOnly());
744 m_xUseSkiaImg->set_visible(officecfg::Office::Common::VCL::UseSkia::isReadOnly());
745 m_xForceSkiaRaster->set_sensitive(m_xUseSkia->get_active() && !officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly());
746 m_xForceSkiaRasterImg->set_visible(officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly());
747 m_xSkiaLog->set_sensitive(bEnabled);
749 // Technically the 'use hardware acceleration' option could be used to mean !forceSkiaRaster, but the implementation
750 // of the option is so tied to the implementation of the canvas module that it's simpler to ignore it.
751 UpdateHardwareAccelStatus();
752 #else
753 HideSkiaWidgets();
754 #endif
757 std::unique_ptr<SfxTabPage> OfaViewTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
759 return std::make_unique<OfaViewTabPage>(pPage, pController, *rAttrSet);
762 OUString OfaViewTabPage::GetAllStrings()
764 OUString sAllStrings;
765 OUString labels[] = { u"label16"_ustr, u"label7"_ustr, u"label1"_ustr, u"label6"_ustr, u"label15"_ustr,
766 u"label14"_ustr, u"label8"_ustr, u"label9"_ustr, u"label4"_ustr, u"label12"_ustr,
767 u"label2"_ustr, u"skiaenabled"_ustr, u"skiadisabled"_ustr, u"label5"_ustr, u"aafrom"_ustr };
769 for (const auto& label : labels)
771 if (const auto pString = m_xBuilder->weld_label(label))
772 sAllStrings += pString->get_label() + " ";
775 OUString checkButton[]
776 = { u"useaccel"_ustr, u"useaa"_ustr, u"useskia"_ustr, u"forceskiaraster"_ustr, u"showfontpreview"_ustr, u"aafont"_ustr };
778 for (const auto& check : checkButton)
780 if (const auto pString = m_xBuilder->weld_check_button(check))
781 sAllStrings += pString->get_label() + " ";
784 sAllStrings += m_xSkiaLog->get_label() + " " + m_xRunGPTests->get_label() + " ";
786 return sAllStrings.replaceAll("_", "");
789 bool OfaViewTabPage::FillItemSet( SfxItemSet* )
791 bool bModified = false;
792 bool bDarkModeOptModified = false;
793 bool bRepaintWindows(false);
794 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(comphelper::ConfigurationChanges::create());
796 SvtMiscOptions aMiscOptions;
797 const sal_Int32 nSizeLB_NewSelection = m_xIconSizeLB->get_active();
798 if( nSizeLB_InitialSelection != nSizeLB_NewSelection )
800 // from now on it's modified, even if via auto setting the same size was set as now selected in the LB
801 sal_Int16 eSet = SFX_SYMBOLS_SIZE_AUTO;
802 switch( nSizeLB_NewSelection )
804 case 0: eSet = SFX_SYMBOLS_SIZE_AUTO; break;
805 case 1: eSet = SFX_SYMBOLS_SIZE_SMALL; break;
806 case 2: eSet = SFX_SYMBOLS_SIZE_LARGE; break;
807 case 3: eSet = SFX_SYMBOLS_SIZE_32; break;
808 default:
809 SAL_WARN("cui.options", "OfaViewTabPage::FillItemSet(): This state of m_xIconSizeLB should not be possible!");
811 aMiscOptions.SetSymbolsSize( eSet );
814 const sal_Int32 nSidebarSizeLB_NewSelection = m_xSidebarIconSizeLB->get_active();
815 if( nSidebarSizeLB_InitialSelection != nSidebarSizeLB_NewSelection )
817 // from now on it's modified, even if via auto setting the same size was set as now selected in the LB
818 ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare;
819 switch( nSidebarSizeLB_NewSelection )
821 case 0: eSet = ToolBoxButtonSize::DontCare; break;
822 case 1: eSet = ToolBoxButtonSize::Small; break;
823 case 2: eSet = ToolBoxButtonSize::Large; break;
824 default:
825 SAL_WARN("cui.options", "OfaViewTabPage::FillItemSet(): This state of m_xSidebarIconSizeLB should not be possible!");
827 officecfg::Office::Common::Misc::SidebarIconSize::set(static_cast<sal_Int16>(eSet), xChanges);
830 const sal_Int32 nNotebookbarSizeLB_NewSelection = m_xNotebookbarIconSizeLB->get_active();
831 if( nNotebookbarSizeLB_InitialSelection != nNotebookbarSizeLB_NewSelection )
833 // from now on it's modified, even if via auto setting the same size was set as now selected in the LB
834 ToolBoxButtonSize eSet = ToolBoxButtonSize::DontCare;
835 switch( nNotebookbarSizeLB_NewSelection )
837 case 0: eSet = ToolBoxButtonSize::DontCare; break;
838 case 1: eSet = ToolBoxButtonSize::Small; break;
839 case 2: eSet = ToolBoxButtonSize::Large; break;
840 default:
841 SAL_WARN("cui.options", "OfaViewTabPage::FillItemSet(): This state of m_xNotebookbarIconSizeLB should not be possible!");
843 officecfg::Office::Common::Misc::NotebookbarIconSize::set(static_cast<sal_Int16>(eSet), xChanges);
846 const sal_Int32 nStyleLB_NewSelection = m_xIconStyleLB->get_active();
847 if( nStyleLB_InitialSelection != nStyleLB_NewSelection )
849 aMiscOptions.SetIconTheme(m_xIconStyleLB->get_active_id());
850 nStyleLB_InitialSelection = nStyleLB_NewSelection;
853 bool bAppearanceChanged = false;
854 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
856 // Middle Mouse Button
857 MouseMiddleButtonAction eOldMiddleMouse = static_cast<MouseMiddleButtonAction>(officecfg::Office::Common::View::Dialog::MiddleMouseButton::get());
858 short eNewMiddleMouse = m_xMouseMiddleLB->get_active();
859 if(eNewMiddleMouse > 2)
860 eNewMiddleMouse = 2;
862 if ( eNewMiddleMouse != static_cast<short>(eOldMiddleMouse) )
864 officecfg::Office::Common::View::Dialog::MiddleMouseButton::set(eNewMiddleMouse, batch);
865 bAppearanceChanged = true;
868 if (m_xFontAntiAliasing->get_state_changed_from_saved())
870 bool b = m_xFontAntiAliasing->get_active();
871 officecfg::Office::Common::View::FontAntiAliasing::Enabled::set(b, batch);
872 bAppearanceChanged = true;
875 if (m_xAAPointLimit->get_value_changed_from_saved())
877 sal_Int64 i = m_xAAPointLimit->get_value(FieldUnit::PIXEL);
878 officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::set(i, batch);
879 bAppearanceChanged = true;
882 if (m_xFontShowCB->get_state_changed_from_saved())
884 officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::set(m_xFontShowCB->get_active(), xChanges);
885 bModified = true;
888 if (m_xAppearanceStyleLB->get_value_changed_from_saved())
890 bDarkModeOptModified = true;
891 bModified = true;
894 // #i95644# if disabled, do not use value, see in ::Reset()
895 if (m_xUseHardwareAccell->get_sensitive())
897 if(m_xUseHardwareAccell->get_state_changed_from_saved())
899 pCanvasSettings->EnabledHardwareAcceleration(m_xUseHardwareAccell->get_active());
900 bModified = true;
904 // #i95644# if disabled, do not use value, see in ::Reset()
905 if (m_xUseAntiAliase->get_sensitive())
907 if (m_xUseAntiAliase->get_active() != SvtOptionsDrawinglayer::IsAntiAliasing())
909 SvtOptionsDrawinglayer::SetAntiAliasing(m_xUseAntiAliase->get_active(), /*bTemporary*/false);
910 bModified = true;
911 bRepaintWindows = true;
915 if (m_xUseSkia->get_state_changed_from_saved() ||
916 m_xForceSkiaRaster->get_state_changed_from_saved())
918 officecfg::Office::Common::VCL::UseSkia::set(m_xUseSkia->get_active(), xChanges);
919 officecfg::Office::Common::VCL::ForceSkiaRaster::set(m_xForceSkiaRaster->get_active(), xChanges);
920 bModified = true;
923 xChanges->commit();
925 if (bDarkModeOptModified)
926 MiscSettings::SetDarkMode(m_xAppearanceStyleLB->get_active());
928 if ( bAppearanceChanged )
930 batch->commit();
931 SvtTabAppearanceCfg::SetApplicationDefaults ( GetpApp() );
934 if(bRepaintWindows)
936 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow();
938 while(pAppWindow)
940 pAppWindow->Invalidate();
941 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow);
945 if (m_xUseSkia->get_state_changed_from_saved() ||
946 m_xForceSkiaRaster->get_state_changed_from_saved())
948 SolarMutexGuard aGuard;
949 if( svtools::executeRestartDialog(
950 comphelper::getProcessComponentContext(), nullptr,
951 svtools::RESTART_REASON_SKIA))
952 GetDialogController()->response(RET_OK);
955 return bModified;
958 void OfaViewTabPage::Reset( const SfxItemSet* )
960 SvtMiscOptions aMiscOptions;
961 bool bEnable = true;
963 if (SvtMiscOptions::GetSymbolsSize() != SFX_SYMBOLS_SIZE_AUTO)
965 nSizeLB_InitialSelection = 1;
967 if (SvtMiscOptions::GetSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE)
968 nSizeLB_InitialSelection = 2;
969 else if (SvtMiscOptions::GetSymbolsSize() == SFX_SYMBOLS_SIZE_32)
970 nSizeLB_InitialSelection = 3;
972 bEnable = !officecfg::Office::Common::Misc::SymbolSet::isReadOnly();
973 m_xIconSizeLB->set_active( nSizeLB_InitialSelection );
974 m_xIconSizeLabel->set_sensitive(bEnable);
975 m_xIconSizeLB->set_sensitive(bEnable);
976 m_xMoreIcons->set_sensitive(bEnable);
977 m_xIconSizeImg->set_visible(!bEnable);
978 m_xIconSizeLB->save_value();
980 ToolBoxButtonSize eSidebarIconSize = static_cast<ToolBoxButtonSize>(officecfg::Office::Common::Misc::SidebarIconSize::get());
981 if( eSidebarIconSize == ToolBoxButtonSize::DontCare )
982 ; // do nothing
983 else if( eSidebarIconSize == ToolBoxButtonSize::Small )
984 nSidebarSizeLB_InitialSelection = 1;
985 else if( eSidebarIconSize == ToolBoxButtonSize::Large )
986 nSidebarSizeLB_InitialSelection = 2;
988 bEnable = !officecfg::Office::Common::Misc::SidebarIconSize::isReadOnly();
989 m_xSidebarIconSizeLB->set_active( nSidebarSizeLB_InitialSelection );
990 m_xSidebarIconSizeLabel->set_sensitive(bEnable);
991 m_xSidebarIconSizeLB->set_sensitive(bEnable);
992 m_xSidebarIconSizeImg->set_visible(!bEnable);
993 m_xSidebarIconSizeLB->save_value();
995 ToolBoxButtonSize eNotebookbarIconSize = static_cast<ToolBoxButtonSize>(officecfg::Office::Common::Misc::NotebookbarIconSize::get());
996 if( eNotebookbarIconSize == ToolBoxButtonSize::DontCare )
997 ; // do nothing
998 else if( eNotebookbarIconSize == ToolBoxButtonSize::Small )
999 nNotebookbarSizeLB_InitialSelection = 1;
1000 else if( eNotebookbarIconSize == ToolBoxButtonSize::Large )
1001 nNotebookbarSizeLB_InitialSelection = 2;
1003 bEnable = !officecfg::Office::Common::Misc::NotebookbarIconSize::isReadOnly();
1004 m_xNotebookbarIconSizeLB->set_active(nNotebookbarSizeLB_InitialSelection);
1005 m_xNotebookbarIconSizeLabel->set_sensitive(bEnable);
1006 m_xNotebookbarIconSizeLB->set_sensitive(bEnable);
1007 m_xNotebookbarIconSizeImg->set_visible(!bEnable);
1008 m_xNotebookbarIconSizeLB->save_value();
1010 // tdf#153497 set name of automatic icon theme, it may have changed due to "Apply" while this page is visible
1011 UpdateIconThemes();
1013 if (aMiscOptions.IconThemeWasSetAutomatically()) {
1014 nStyleLB_InitialSelection = 0;
1016 else {
1017 const OUString selected = SvtMiscOptions::GetIconTheme();
1018 const vcl::IconThemeInfo& selectedInfo =
1019 vcl::IconThemeInfo::FindIconThemeById(mInstalledIconThemes, selected);
1020 nStyleLB_InitialSelection = m_xIconStyleLB->find_text(selectedInfo.GetDisplayName());
1023 bEnable = !officecfg::Office::Common::Misc::SymbolStyle::isReadOnly();
1024 m_xIconStyleLB->set_active(nStyleLB_InitialSelection);
1025 m_xIconStyleLabel->set_sensitive(bEnable);
1026 m_xIconStyleLB->set_sensitive(bEnable);
1027 m_xIconStyleImg->set_visible(!bEnable);
1028 m_xIconStyleLB->save_value();
1030 bEnable = !officecfg::Office::Common::Misc::Appearance::isReadOnly();
1031 m_xAppearanceStyleLB->set_active(officecfg::Office::Common::Misc::Appearance::get());
1032 m_xAppearanceStyleLabel->set_sensitive(bEnable);
1033 m_xAppearanceStyleLB->set_sensitive(bEnable);
1034 m_xAppearanceStyleImg->set_visible(!bEnable);
1035 m_xAppearanceStyleLB->save_value();
1037 // Middle Mouse Button
1038 bEnable = !officecfg::Office::Common::View::Dialog::MiddleMouseButton::isReadOnly();
1039 sal_Int16 nMiddleMouseButton = officecfg::Office::Common::View::Dialog::MiddleMouseButton::get();
1040 m_xMouseMiddleLB->set_active(static_cast<short>(nMiddleMouseButton));
1041 m_xMouseMiddleLabel->set_sensitive(bEnable);
1042 m_xMouseMiddleLB->set_sensitive(bEnable);
1043 m_xMouseMiddleImg->set_visible(!bEnable);
1044 m_xMouseMiddleLB->save_value();
1046 bEnable = !officecfg::Office::Common::View::FontAntiAliasing::Enabled::isReadOnly();
1047 bool bFontAntiAliasing = officecfg::Office::Common::View::FontAntiAliasing::Enabled::get();
1048 m_xFontAntiAliasing->set_active( bFontAntiAliasing );
1049 m_xFontAntiAliasing->set_sensitive(bEnable);
1050 m_xFontAntiAliasingImg->set_visible(!bEnable);
1052 bEnable = !officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::isReadOnly();
1053 sal_Int16 nFontAntiAliasingMinPixelHeight = officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::get();
1054 m_xAAPointLimit->set_value(nFontAntiAliasingMinPixelHeight, FieldUnit::PIXEL);
1055 m_xAAPointLimit->set_sensitive(bEnable);
1056 m_xAAPointLimitLabelImg->set_visible(!bEnable);
1058 // WorkingSet
1059 bEnable = !officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::isReadOnly();
1060 m_xFontShowCB->set_active(officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::get());
1061 m_xFontShowCB->set_sensitive(bEnable);
1062 m_xFontShowImg->set_visible(!bEnable);
1064 UpdateHardwareAccelStatus();
1065 m_xUseHardwareAccell->save_state();
1067 { // #i95644# AntiAliasing
1068 m_xUseAntiAliase->set_active(SvtOptionsDrawinglayer::IsAntiAliasing());
1069 bEnable = !officecfg::Office::Common::Drawinglayer::AntiAliasing::isReadOnly();
1070 m_xUseAntiAliase->set_sensitive(bEnable);
1071 m_xUseAntiAliaseImg->set_visible(!bEnable);
1072 m_xUseAntiAliase->save_state();
1075 m_xUseSkia->set_active(officecfg::Office::Common::VCL::UseSkia::get());
1076 m_xForceSkiaRaster->set_active(officecfg::Office::Common::VCL::ForceSkiaRaster::get());
1077 m_xUseSkia->save_state();
1078 m_xForceSkiaRaster->save_state();
1080 m_xFontAntiAliasing->save_state();
1081 m_xAAPointLimit->save_value();
1082 m_xFontShowCB->save_state();
1084 OnAntialiasingToggled(*m_xFontAntiAliasing);
1085 UpdateSkiaStatus();
1088 void OfaViewTabPage::UpdateHardwareAccelStatus()
1090 // #i95644# HW accel (unified to disable mechanism)
1091 if(pCanvasSettings->IsHardwareAccelerationAvailable())
1093 m_xUseHardwareAccell->set_active(pCanvasSettings->IsHardwareAccelerationEnabled());
1094 m_xUseHardwareAccell->set_sensitive(!pCanvasSettings->IsHardwareAccelerationRO());
1095 m_xUseHardwareAccellImg->set_visible(pCanvasSettings->IsHardwareAccelerationRO());
1097 else
1099 m_xUseHardwareAccell->set_active(false);
1100 m_xUseHardwareAccell->set_sensitive(false);
1101 m_xUseHardwareAccellImg->set_visible(true);
1103 #if HAVE_FEATURE_SKIA
1104 m_xUseHardwareAccell->set_sensitive(!m_xUseSkia->get_active());
1105 #endif
1108 struct LanguageConfig_Impl
1110 SvtCTLOptions aCTLLanguageOptions;
1111 SvtSysLocaleOptions aSysLocaleOptions;
1112 SvtLinguConfig aLinguConfig;
1115 static bool bLanguageCurrentDoc_Impl = false;
1117 // some things we'll need...
1118 constexpr OUString sAccessSrvc = u"com.sun.star.configuration.ConfigurationAccess"_ustr;
1119 constexpr OUStringLiteral sAccessUpdSrvc = u"com.sun.star.configuration.ConfigurationUpdateAccess";
1120 constexpr OUString sInstalledLocalesPath = u"org.openoffice.Setup/Office/InstalledLocales"_ustr;
1121 constexpr OUString sUserLocalePath = u"org.openoffice.Office.Linguistic/General"_ustr;
1122 constexpr OUString sUserLocaleKey = u"UILocale"_ustr;
1123 static Sequence< OUString > seqInstalledLanguages;
1125 static OUString lcl_getDatePatternsConfigString( const LocaleDataWrapper& rLocaleWrapper )
1127 const Sequence< OUString >& aDateAcceptancePatterns = rLocaleWrapper.getDateAcceptancePatterns();
1128 sal_Int32 nPatterns = aDateAcceptancePatterns.getLength();
1129 OUStringBuffer aBuf( nPatterns * 6 ); // 6 := length of Y-M-D;
1130 SAL_WARN_IF( !nPatterns, "cui.options", "No date acceptance pattern");
1131 if (nPatterns)
1133 aBuf.append(aDateAcceptancePatterns[0]);
1134 for (sal_Int32 i=1; i < nPatterns; ++i)
1135 aBuf.append(";" + aDateAcceptancePatterns[i]);
1137 return aBuf.makeStringAndClear();
1140 namespace
1142 //what ui language will be selected by default if the user override of General::UILocale is unset ?
1143 LanguageTag GetInstalledLocaleForSystemUILanguage()
1145 css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames());
1146 return LanguageTag(getInstalledLocaleForSystemUILanguage(inst, false)).makeFallback();
1150 OfaLanguagesTabPage::OfaLanguagesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
1151 : SfxTabPage(pPage, pController, u"cui/ui/optlanguagespage.ui"_ustr, u"OptLanguagesPage"_ustr, &rSet)
1152 , pLangConfig(new LanguageConfig_Impl)
1153 , m_bDatePatternsValid(false)
1154 , m_xUserInterfaceLB(m_xBuilder->weld_combo_box(u"userinterface"_ustr))
1155 , m_xLocaleSettingFT(m_xBuilder->weld_label(u"localesettingFT"_ustr))
1156 , m_xLocaleSettingLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"localesetting"_ustr)))
1157 , m_xLocaleSettingImg(m_xBuilder->weld_widget(u"locklocalesetting"_ustr))
1158 , m_xDecimalSeparatorFT(m_xBuilder->weld_label(u"label6"_ustr))
1159 , m_xDecimalSeparatorCB(m_xBuilder->weld_check_button(u"decimalseparator"_ustr))
1160 , m_xDecimalSeparatorImg(m_xBuilder->weld_widget(u"lockdecimalseparator"_ustr))
1161 , m_xCurrencyFT(m_xBuilder->weld_label(u"defaultcurrency"_ustr))
1162 , m_xCurrencyLB(m_xBuilder->weld_combo_box(u"currencylb"_ustr))
1163 , m_xCurrencyImg(m_xBuilder->weld_widget(u"lockcurrencylb"_ustr))
1164 , m_xDatePatternsFT(m_xBuilder->weld_label(u"dataaccpatterns"_ustr))
1165 , m_xDatePatternsED(m_xBuilder->weld_entry(u"datepatterns"_ustr))
1166 , m_xDatePatternsImg(m_xBuilder->weld_widget(u"lockdatepatterns"_ustr))
1167 , m_xWesternLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"westernlanguage"_ustr)))
1168 , m_xWesternLanguageFT(m_xBuilder->weld_label(u"western"_ustr))
1169 , m_xWesternLanguageImg(m_xBuilder->weld_widget(u"lockwesternlanguage"_ustr))
1170 , m_xAsianLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"asianlanguage"_ustr)))
1171 , m_xComplexLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"complexlanguage"_ustr)))
1172 , m_xCurrentDocCB(m_xBuilder->weld_check_button(u"currentdoc"_ustr))
1173 , m_xAsianSupportCB(m_xBuilder->weld_check_button(u"asiansupport"_ustr))
1174 , m_xAsianSupportImg(m_xBuilder->weld_widget(u"lockasiansupport"_ustr))
1175 , m_xCTLSupportCB(m_xBuilder->weld_check_button(u"ctlsupport"_ustr))
1176 , m_xCTLSupportImg(m_xBuilder->weld_widget(u"lockctlsupport"_ustr))
1177 , m_xIgnoreLanguageChangeCB(m_xBuilder->weld_check_button(u"ignorelanguagechange"_ustr))
1178 , m_xIgnoreLanguageChangeImg(m_xBuilder->weld_widget(u"lockignorelanguagechange"_ustr))
1180 // tdf#125483 save original default label
1181 m_sDecimalSeparatorLabel = m_xDecimalSeparatorCB->get_label();
1183 // initialize user interface language selection
1184 m_sSystemDefaultString = SvtLanguageTable::GetLanguageString( LANGUAGE_SYSTEM );
1186 OUString aUILang = m_sSystemDefaultString +
1187 " - " +
1188 SvtLanguageTable::GetLanguageString(GetInstalledLocaleForSystemUILanguage().getLanguageType());
1190 m_xUserInterfaceLB->append(u"0"_ustr, aUILang);
1191 m_xUserInterfaceLB->append_separator(u""_ustr);
1194 Reference< XMultiServiceFactory > theConfigProvider(
1195 css::configuration::theDefaultProvider::get(
1196 comphelper::getProcessComponentContext()));
1197 // find out which locales are currently installed and add them to the listbox
1198 Sequence< Any > theArgs{ Any(NamedValue(u"nodepath"_ustr, Any(sInstalledLocalesPath))) };
1199 Reference< XNameAccess > theNameAccess(
1200 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs ), UNO_QUERY_THROW );
1201 seqInstalledLanguages = theNameAccess->getElementNames();
1202 LanguageType aLang = LANGUAGE_DONTKNOW;
1203 std::vector< std::pair<sal_Int32, OUString> > aUILanguages;
1204 for (sal_Int32 i=0; i<seqInstalledLanguages.getLength(); i++)
1206 aLang = LanguageTag::convertToLanguageTypeWithFallback(seqInstalledLanguages[i]);
1207 if (aLang != LANGUAGE_DONTKNOW)
1209 OUString aLangStr( SvtLanguageTable::GetLanguageString( aLang ) );
1210 aUILanguages.emplace_back(i+1, aLangStr);
1214 std::sort(aUILanguages.begin(), aUILanguages.end(), [](const auto& l1, const auto& l2) {
1215 static const auto aSorter = comphelper::string::NaturalStringSorter(
1216 comphelper::getProcessComponentContext(),
1217 Application::GetSettings().GetUILanguageTag().getLocale());
1218 return aSorter.compare(l1.second, l2.second) < 0;
1221 // tdf#114694: append the sorted list after the default entry and separator.
1222 for (const auto & [ nGroupID, sGroupName ] : aUILanguages)
1224 m_xUserInterfaceLB->append(OUString::number(nGroupID), sGroupName);
1227 m_xUserInterfaceLB->set_active(0);
1229 // find out whether the user has a specific locale specified
1230 Sequence< Any > theArgs2{ Any(NamedValue(u"nodepath"_ustr, Any(sUserLocalePath))) };
1231 theNameAccess.set(
1232 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs2 ), UNO_QUERY_THROW );
1233 if (theNameAccess->hasByName(sUserLocaleKey))
1234 theNameAccess->getByName(sUserLocaleKey) >>= m_sUserLocaleValue;
1235 // select the user specified locale in the listbox
1236 if (!m_sUserLocaleValue.isEmpty())
1238 for (sal_Int32 i = 0, nEntryCount = m_xUserInterfaceLB->get_count(); i < nEntryCount; ++i)
1240 sal_Int32 d = m_xUserInterfaceLB->get_id(i).toInt32();
1241 if ( d > 0 && seqInstalledLanguages.getLength() > d-1 && seqInstalledLanguages[d-1] == m_sUserLocaleValue)
1242 m_xUserInterfaceLB->set_active(i);
1247 catch (const Exception &)
1249 // we'll just leave the box in its default setting and won't
1250 // even give it event handler...
1251 TOOLS_WARN_EXCEPTION("cui.options", "ignoring" );
1254 m_xWesternLanguageLB->SetLanguageList(
1255 SvxLanguageListFlags::WESTERN | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1256 LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
1258 m_xAsianLanguageLB->SetLanguageList(
1259 SvxLanguageListFlags::CJK | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1260 LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
1262 m_xComplexLanguageLB->SetLanguageList(
1263 SvxLanguageListFlags::CTL | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1264 LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
1266 m_xLocaleSettingLB->SetLanguageList(
1267 SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false, false, false, true,
1268 LANGUAGE_USER_SYSTEM_CONFIG, css::i18n::ScriptType::WEAK);
1270 const NfCurrencyTable& rCurrTab = SvNumberFormatter::GetTheCurrencyTable();
1271 const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( LANGUAGE_SYSTEM );
1272 // insert SYSTEM entry
1273 OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol();
1274 m_xCurrencyLB->append(u"default"_ustr, aDefaultCurr);
1275 m_xCurrencyLB->append_separator(u""_ustr);
1277 assert(m_xCurrencyLB->find_id(u"default"_ustr) != -1);
1278 // all currencies
1279 OUString aTwoSpace( u" "_ustr );
1280 sal_uInt16 nCurrCount = rCurrTab.size();
1281 std::vector< const NfCurrencyEntry* > aCurrencies;
1282 // first entry is SYSTEM, skip it
1283 for ( sal_uInt16 j=1; j < nCurrCount; ++j )
1285 aCurrencies.push_back(&rCurrTab[j]);
1287 std::sort(aCurrencies.begin(), aCurrencies.end(),
1288 [](const NfCurrencyEntry* c1, const NfCurrencyEntry* c2) {
1289 return c1->GetBankSymbol().compareTo(c2->GetBankSymbol()) < 0;
1292 for (auto &v : aCurrencies)
1294 OUString aStr_ = v->GetBankSymbol() +
1295 aTwoSpace +
1296 v->GetSymbol();
1297 aStr_ = ApplyLreOrRleEmbedding( aStr_ ) +
1298 aTwoSpace +
1299 ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( v->GetLanguage() ) );
1300 m_xCurrencyLB->append(weld::toId(v), aStr_);
1303 m_xCurrencyLB->set_active(0);
1305 m_xLocaleSettingLB->connect_changed( LINK( this, OfaLanguagesTabPage, LocaleSettingHdl ) );
1306 m_xDatePatternsED->connect_changed( LINK( this, OfaLanguagesTabPage, DatePatternsHdl ) );
1308 Link<weld::Toggleable&,void> aLink( LINK( this, OfaLanguagesTabPage, SupportHdl ) );
1309 m_xAsianSupportCB->connect_toggled( aLink );
1310 m_xCTLSupportCB->connect_toggled( aLink );
1312 m_bOldAsian = SvtCJKOptions::IsAnyEnabled();
1313 m_xAsianSupportCB->set_active(m_bOldAsian);
1314 m_xAsianSupportCB->save_state();
1315 bool bReadonly = SvtCJKOptions::IsAnyReadOnly();
1316 m_xAsianSupportCB->set_sensitive(!bReadonly);
1317 m_xAsianSupportImg->set_visible(bReadonly);
1318 SupportHdl(*m_xAsianSupportCB);
1320 m_bOldCtl = SvtCTLOptions::IsCTLFontEnabled();
1321 m_xCTLSupportCB->set_active(m_bOldCtl);
1322 m_xCTLSupportCB->save_state();
1323 bReadonly = pLangConfig->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::E_CTLFONT);
1324 m_xCTLSupportCB->set_sensitive(!bReadonly);
1325 m_xCTLSupportImg->set_visible(bReadonly);
1326 SupportHdl(*m_xCTLSupportCB);
1328 m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange() );
1331 OfaLanguagesTabPage::~OfaLanguagesTabPage()
1335 std::unique_ptr<SfxTabPage> OfaLanguagesTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
1337 return std::make_unique<OfaLanguagesTabPage>(pPage, pController, *rAttrSet);
1340 static void lcl_Update(std::unique_ptr<SfxVoidItem> pInvalidItems[], std::unique_ptr<SfxBoolItem> pBoolItems[], sal_uInt16 nCount)
1342 SfxViewFrame* pCurrentFrm = SfxViewFrame::Current();
1343 SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst();
1344 while(pViewFrm)
1346 SfxBindings& rBind = pViewFrm->GetBindings();
1347 for(sal_uInt16 i = 0; i < nCount; i++)
1349 if(pCurrentFrm == pViewFrm)
1350 rBind.InvalidateAll(false);
1351 rBind.SetState( *pInvalidItems[i] );
1352 rBind.SetState( *pBoolItems[i] );
1354 pViewFrm = SfxViewFrame::GetNext(*pViewFrm);
1358 OUString OfaLanguagesTabPage::GetAllStrings()
1360 OUString sAllStrings;
1361 OUString labels[]
1362 = { u"label1"_ustr, u"label4"_ustr, u"label7"_ustr, u"localesettingFT"_ustr, u"defaultcurrency"_ustr,
1363 u"label6"_ustr, u"dataaccpatterns"_ustr, u"label2"_ustr, u"western"_ustr, u"label3"_ustr };
1365 for (const auto& label : labels)
1367 if (const auto pString = m_xBuilder->weld_label(label))
1368 sAllStrings += pString->get_label() + " ";
1371 OUString checkButton[] = { u"decimalseparator"_ustr, u"asiansupport"_ustr, u"ctlsupport"_ustr, u"currentdoc"_ustr,
1372 u"ignorelanguagechange"_ustr };
1374 for (const auto& check : checkButton)
1376 if (const auto pString = m_xBuilder->weld_check_button(check))
1377 sAllStrings += pString->get_label() + " ";
1380 return sAllStrings.replaceAll("_", "");
1383 bool OfaLanguagesTabPage::FillItemSet( SfxItemSet* rSet )
1385 // lock configuration broadcasters so that we can coordinate the notifications
1386 pLangConfig->aSysLocaleOptions.BlockBroadcasts( true );
1387 pLangConfig->aCTLLanguageOptions.BlockBroadcasts( true );
1388 pLangConfig->aLinguConfig.BlockBroadcasts( true );
1391 * Sequence checking only matters when CTL support is enabled.
1393 * So we only need to check for sequence checking if
1394 * a) previously it was unchecked and is now checked or
1395 * b) it was already checked but the CTL language has changed
1397 if (
1398 m_xCTLSupportCB->get_active() &&
1399 (m_xCTLSupportCB->get_saved_state() != TRISTATE_TRUE ||
1400 m_xComplexLanguageLB->get_active_id_changed_from_saved())
1403 //sequence checking has to be switched on depending on the selected CTL language
1404 LanguageType eCTLLang = m_xComplexLanguageLB->get_active_id();
1405 bool bOn = MsLangId::needsSequenceChecking( eCTLLang);
1406 pLangConfig->aCTLLanguageOptions.SetCTLSequenceCheckingRestricted(bOn);
1407 pLangConfig->aCTLLanguageOptions.SetCTLSequenceChecking(bOn);
1408 pLangConfig->aCTLLanguageOptions.SetCTLSequenceCheckingTypeAndReplace(bOn);
1412 // handle settings for UI Language
1413 // a change of setting needs to bring up a warning message
1414 OUString aLangString;
1415 sal_Int32 d = m_xUserInterfaceLB->get_active_id().toInt32();
1416 if( d > 0 && seqInstalledLanguages.getLength() > d-1)
1417 aLangString = seqInstalledLanguages[d-1];
1420 if( m_xUserInterfaceLB->GetSelectedEntryPos() > 0)
1421 aLangString = ConvertLanguageToIsoString(m_xUserInterfaceLB->get_active_id());
1423 Reference< XMultiServiceFactory > theConfigProvider(
1424 css::configuration::theDefaultProvider::get(
1425 comphelper::getProcessComponentContext()));
1426 Sequence< Any > theArgs{ Any(NamedValue(u"nodepath"_ustr, Any(sUserLocalePath))) };
1427 Reference< XPropertySet >xProp(
1428 theConfigProvider->createInstanceWithArguments(sAccessUpdSrvc, theArgs ), UNO_QUERY_THROW );
1429 if ( m_sUserLocaleValue != aLangString)
1431 // OSL_FAIL("UserInterface language was changed, restart.");
1432 // write new value
1433 xProp->setPropertyValue(sUserLocaleKey, Any(aLangString));
1434 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
1435 // display info
1436 SolarMutexGuard aGuard;
1437 if (svtools::executeRestartDialog(
1438 comphelper::getProcessComponentContext(), GetFrameWeld(),
1439 svtools::RESTART_REASON_LANGUAGE_CHANGE))
1440 GetDialogController()->response(RET_OK);
1442 // tell quickstarter to stop being a veto listener
1444 const Reference< XComponentContext >& xContext(
1445 comphelper::getProcessComponentContext());
1446 css::office::Quickstart::createAndSetVeto(xContext, false, false, false/*DisableVeto*/);
1449 catch (const Exception&)
1451 // we'll just leave the box in its default setting and won't
1452 // even give it event handler...
1453 TOOLS_WARN_EXCEPTION("cui.options", "ignoring");
1456 LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag());
1457 LanguageType eOldLocale = (aLanguageTag.isSystemLocale() ? LANGUAGE_SYSTEM :
1458 aLanguageTag.makeFallback().getLanguageType());
1459 LanguageType eNewLocale = m_xLocaleSettingLB->get_active_id();
1461 // If the "Default ..." entry was selected that means SYSTEM, the actual
1462 // eNewLocale value is temporary for the dialog only, do not resolve to
1463 // what system currently is.
1464 if (eNewLocale == LANGUAGE_USER_SYSTEM_CONFIG)
1465 eNewLocale = LANGUAGE_SYSTEM;
1467 if ( eOldLocale != eNewLocale )
1469 // an empty string denotes SYSTEM locale
1470 OUString sNewLang;
1471 if ( eNewLocale != LANGUAGE_SYSTEM )
1472 sNewLang = LanguageTag::convertToBcp47( eNewLocale);
1474 // locale nowadays get to AppSettings via notification
1475 // this will happen after releasing the lock on the ConfigurationBroadcaster at
1476 // the end of this method
1477 pLangConfig->aSysLocaleOptions.SetLocaleConfigString( sNewLang );
1478 rSet->Put( SfxBoolItem( SID_OPT_LOCALE_CHANGED, true ) );
1480 SvtScriptType nNewType = SvtLanguageOptions::GetScriptTypeOfLanguage( eNewLocale );
1481 bool bNewCJK = bool( nNewType & SvtScriptType::ASIAN );
1482 auto batch = comphelper::ConfigurationChanges::create();
1483 SvtCompatibilityDefault aCompatOpts(batch);
1484 aCompatOpts.set(u"ExpandWordSpace"_ustr, !bNewCJK);
1485 batch->commit();
1488 if(m_xDecimalSeparatorCB->get_state_changed_from_saved())
1489 pLangConfig->aSysLocaleOptions.SetDecimalSeparatorAsLocale(m_xDecimalSeparatorCB->get_active());
1491 if(m_xIgnoreLanguageChangeCB->get_state_changed_from_saved())
1492 pLangConfig->aSysLocaleOptions.SetIgnoreLanguageChange(m_xIgnoreLanguageChangeCB->get_active());
1494 // Configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default.
1495 OUString sOldCurr = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString();
1496 OUString sId = m_xCurrencyLB->get_active_id();
1497 const NfCurrencyEntry* pCurr = sId == "default" ? nullptr : weld::fromId<const NfCurrencyEntry*>(sId);
1498 OUString sNewCurr;
1499 if ( pCurr )
1500 sNewCurr = SvtSysLocaleOptions::CreateCurrencyConfigString(
1501 pCurr->GetBankSymbol(), pCurr->GetLanguage() );
1502 if ( sOldCurr != sNewCurr )
1503 pLangConfig->aSysLocaleOptions.SetCurrencyConfigString( sNewCurr );
1505 // Configured date acceptance patterns, for example Y-M-D;M-D or empty for
1506 // locale default.
1507 if (m_bDatePatternsValid && m_xDatePatternsED->get_value_changed_from_saved())
1508 pLangConfig->aSysLocaleOptions.SetDatePatternsConfigString( m_xDatePatternsED->get_text());
1510 SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current();
1511 Reference< css::linguistic2::XLinguProperties > xLinguProp = LinguMgr::GetLinguPropertySet();
1512 bool bCurrentDocCBChecked = m_xCurrentDocCB->get_active();
1513 if (m_xCurrentDocCB->get_sensitive())
1514 bLanguageCurrentDoc_Impl = bCurrentDocCBChecked;
1515 bool bCurrentDocCBChanged = m_xCurrentDocCB->get_state_changed_from_saved();
1517 bool bValChanged = m_xWesternLanguageLB->get_active_id_changed_from_saved();
1518 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1520 LanguageType eSelectLang = m_xWesternLanguageLB->get_active_id();
1521 if(!bCurrentDocCBChecked)
1523 Any aValue;
1524 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1525 aValue <<= aLocale;
1526 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale", aValue );
1527 if (xLinguProp.is())
1528 xLinguProp->setDefaultLocale( aLocale );
1530 if(pCurrentDocShell)
1532 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::LATIN),
1533 SID_ATTR_LANGUAGE));
1536 bValChanged = m_xAsianLanguageLB->get_active_id_changed_from_saved();
1537 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1539 LanguageType eSelectLang = m_xAsianLanguageLB->get_active_id();
1540 if(!bCurrentDocCBChecked)
1542 Any aValue;
1543 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1544 aValue <<= aLocale;
1545 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale_CJK", aValue );
1546 if (xLinguProp.is())
1547 xLinguProp->setDefaultLocale_CJK( aLocale );
1549 if(pCurrentDocShell)
1551 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::ASIAN),
1552 SID_ATTR_CHAR_CJK_LANGUAGE));
1555 bValChanged = m_xComplexLanguageLB->get_active_id_changed_from_saved();
1556 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1558 LanguageType eSelectLang = m_xComplexLanguageLB->get_active_id();
1559 if(!bCurrentDocCBChecked)
1561 Any aValue;
1562 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1563 aValue <<= aLocale;
1564 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale_CTL", aValue );
1565 if (xLinguProp.is())
1566 xLinguProp->setDefaultLocale_CTL( aLocale );
1568 if(pCurrentDocShell)
1570 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::COMPLEX),
1571 SID_ATTR_CHAR_CTL_LANGUAGE));
1575 if(m_xAsianSupportCB->get_state_changed_from_saved() )
1577 bool bChecked = m_xAsianSupportCB->get_active();
1578 SvtCJKOptions::SetAll(bChecked);
1580 //iterate over all bindings to invalidate vertical text direction
1581 const sal_uInt16 STATE_COUNT = 2;
1583 std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT];
1584 pBoolItems[0].reset(new SfxBoolItem(SID_VERTICALTEXT_STATE, false));
1585 pBoolItems[1].reset(new SfxBoolItem(SID_TEXT_FITTOSIZE_VERTICAL, false));
1587 std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT];
1588 pInvalidItems[0].reset(new SfxVoidItem(SID_VERTICALTEXT_STATE));
1589 pInvalidItems[1].reset(new SfxVoidItem(SID_TEXT_FITTOSIZE_VERTICAL));
1591 lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT);
1594 if ( m_xCTLSupportCB->get_state_changed_from_saved() )
1596 SvtSearchOptions aOpt;
1597 aOpt.SetIgnoreDiacritics_CTL(true);
1598 aOpt.SetIgnoreKashida_CTL(true);
1599 aOpt.Commit();
1600 pLangConfig->aCTLLanguageOptions.SetCTLFontEnabled( m_xCTLSupportCB->get_active() );
1602 const sal_uInt16 STATE_COUNT = 1;
1603 std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT];
1604 pBoolItems[0].reset(new SfxBoolItem(SID_CTLFONT_STATE, false));
1605 std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT];
1606 pInvalidItems[0].reset(new SfxVoidItem(SID_CTLFONT_STATE));
1607 lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT);
1610 if ( pLangConfig->aSysLocaleOptions.IsModified() )
1611 pLangConfig->aSysLocaleOptions.Commit();
1613 // first release the lock on the ConfigurationBroadcaster for Locale changes
1614 // it seems that our code relies on the fact that before other changes like e.g. currency
1615 // are broadcasted locale changes have been done
1616 pLangConfig->aSysLocaleOptions.BlockBroadcasts( false );
1617 pLangConfig->aCTLLanguageOptions.BlockBroadcasts( false );
1618 pLangConfig->aLinguConfig.BlockBroadcasts( false );
1620 return false;
1623 void OfaLanguagesTabPage::Reset( const SfxItemSet* rSet )
1625 LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag());
1626 if ( aLanguageTag.isSystemLocale() )
1627 m_xLocaleSettingLB->set_active_id( LANGUAGE_USER_SYSTEM_CONFIG );
1628 else
1629 m_xLocaleSettingLB->set_active_id( aLanguageTag.makeFallback().getLanguageType());
1630 bool bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Locale);
1631 m_xLocaleSettingLB->set_sensitive(!bReadonly);
1632 m_xLocaleSettingFT->set_sensitive(!bReadonly);
1633 m_xLocaleSettingImg->set_visible(bReadonly);
1636 m_xDecimalSeparatorCB->set_active( pLangConfig->aSysLocaleOptions.IsDecimalSeparatorAsLocale());
1637 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DecimalSeparator);
1638 m_xDecimalSeparatorCB->set_sensitive(!bReadonly);
1639 m_xDecimalSeparatorFT->set_sensitive(!bReadonly);
1640 m_xDecimalSeparatorImg->set_visible(bReadonly);
1641 m_xDecimalSeparatorCB->save_state();
1643 m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange());
1644 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::IgnoreLanguageChange);
1645 m_xIgnoreLanguageChangeCB->set_sensitive(!bReadonly);
1646 m_xIgnoreLanguageChangeImg->set_visible(bReadonly);
1647 m_xIgnoreLanguageChangeCB->save_state();
1649 // let LocaleSettingHdl enable/disable checkboxes for CJK/CTL support
1650 // #i15812# must be done *before* the configured currency is set
1651 // and update the decimal separator used for the given locale
1652 LocaleSettingHdl(*m_xLocaleSettingLB->get_widget());
1654 // configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default
1655 const NfCurrencyEntry* pCurr = nullptr;
1656 OUString sCurrency = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString();
1657 if ( !sCurrency.isEmpty() )
1659 LanguageType eLang;
1660 OUString aAbbrev;
1661 SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( aAbbrev, eLang, sCurrency );
1662 pCurr = SvNumberFormatter::GetCurrencyEntry( aAbbrev, eLang );
1664 // if pCurr==nullptr the SYSTEM entry is selected
1665 OUString sId = !pCurr ? u"default"_ustr : weld::toId(pCurr);
1666 m_xCurrencyLB->set_active_id(sId);
1667 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Currency);
1668 m_xCurrencyLB->set_sensitive(!bReadonly);
1669 m_xCurrencyFT->set_sensitive(!bReadonly);
1670 m_xCurrencyImg->set_visible(bReadonly);
1672 // date acceptance patterns
1673 OUString aDatePatternsString = pLangConfig->aSysLocaleOptions.GetDatePatternsConfigString();
1674 if (aDatePatternsString.isEmpty())
1676 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1677 aDatePatternsString = lcl_getDatePatternsConfigString( rLocaleWrapper);
1678 // Let's assume patterns are valid at this point.
1679 m_bDatePatternsValid = true;
1681 else
1683 bool bModified = false;
1684 m_bDatePatternsValid = validateDatePatterns( bModified, aDatePatternsString);
1686 m_xDatePatternsED->set_text(aDatePatternsString);
1687 m_xDatePatternsED->set_message_type( m_bDatePatternsValid ?
1688 weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
1689 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DatePatterns);
1690 m_xDatePatternsED->set_sensitive(!bReadonly);
1691 m_xDatePatternsFT->set_sensitive(!bReadonly);
1692 m_xDatePatternsImg->set_visible(bReadonly);
1693 m_xDatePatternsED->save_value();
1695 //western/CJK/CLK language
1696 LanguageType eCurLang = LANGUAGE_NONE;
1697 LanguageType eCurLangCJK = LANGUAGE_NONE;
1698 LanguageType eCurLangCTL = LANGUAGE_NONE;
1699 SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current();
1700 //collect the configuration values first
1701 m_xCurrentDocCB->set_sensitive(false);
1703 Any aWestLang;
1704 Any aCJKLang;
1705 Any aCTLLang;
1708 aWestLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale");
1709 Locale aLocale;
1710 aWestLang >>= aLocale;
1712 eCurLang = LanguageTag::convertToLanguageType( aLocale, false);
1714 aCJKLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale_CJK");
1715 aLocale = Locale();
1716 aCJKLang >>= aLocale;
1717 eCurLangCJK = LanguageTag::convertToLanguageType( aLocale, false);
1719 aCTLLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale_CTL");
1720 aLocale = Locale();
1721 aCTLLang >>= aLocale;
1722 eCurLangCTL = LanguageTag::convertToLanguageType( aLocale, false);
1724 catch (const Exception&)
1727 //overwrite them by the values provided by the DocShell
1728 if(pCurrentDocShell)
1730 m_xCurrentDocCB->set_sensitive(true);
1731 m_xCurrentDocCB->set_active(bLanguageCurrentDoc_Impl);
1732 if( const SvxLanguageItem* pLangItem = rSet->GetItemIfSet(SID_ATTR_LANGUAGE, false))
1734 LanguageType eTempCurLang = pLangItem->GetValue();
1735 if (MsLangId::resolveSystemLanguageByScriptType(eCurLang, css::i18n::ScriptType::LATIN) != eTempCurLang)
1736 eCurLang = eTempCurLang;
1739 if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CJK_LANGUAGE, false))
1741 LanguageType eTempCurLang = pLang->GetValue();
1742 if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCJK, css::i18n::ScriptType::ASIAN) != eTempCurLang)
1743 eCurLangCJK = eTempCurLang;
1746 if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CTL_LANGUAGE, false))
1748 LanguageType eTempCurLang = pLang->GetValue();
1749 if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCTL, css::i18n::ScriptType::COMPLEX) != eTempCurLang)
1750 eCurLangCTL = eTempCurLang;
1753 if(LANGUAGE_NONE == eCurLang || LANGUAGE_DONTKNOW == eCurLang)
1754 m_xWesternLanguageLB->set_active_id(LANGUAGE_NONE);
1755 else
1756 m_xWesternLanguageLB->set_active_id(eCurLang);
1758 if(LANGUAGE_NONE == eCurLangCJK || LANGUAGE_DONTKNOW == eCurLangCJK)
1759 m_xAsianLanguageLB->set_active_id(LANGUAGE_NONE);
1760 else
1761 m_xAsianLanguageLB->set_active_id(eCurLangCJK);
1763 if(LANGUAGE_NONE == eCurLangCTL || LANGUAGE_DONTKNOW == eCurLangCTL)
1764 m_xComplexLanguageLB->set_active_id(LANGUAGE_NONE);
1765 else
1766 m_xComplexLanguageLB->set_active_id(eCurLangCTL);
1768 m_xWesternLanguageLB->save_active_id();
1769 m_xAsianLanguageLB->save_active_id();
1770 m_xComplexLanguageLB->save_active_id();
1771 m_xIgnoreLanguageChangeCB->save_state();
1772 m_xCurrentDocCB->save_state();
1774 bool bEnable = !pLangConfig->aLinguConfig.IsReadOnly( u"DefaultLocale" );
1775 m_xWesternLanguageFT->set_sensitive( bEnable );
1776 m_xWesternLanguageLB->set_sensitive( bEnable );
1777 m_xWesternLanguageImg->set_visible( !bEnable );
1779 // check the box "For the current document only"
1780 // set the focus to the Western Language box
1781 const SfxBoolItem* pLang = rSet->GetItemIfSet(SID_SET_DOCUMENT_LANGUAGE, false );
1782 if ( pLang && pLang->GetValue() )
1784 m_xWesternLanguageLB->grab_focus();
1785 m_xCurrentDocCB->set_sensitive(true);
1786 m_xCurrentDocCB->set_active(true);
1790 IMPL_LINK(OfaLanguagesTabPage, SupportHdl, weld::Toggleable&, rBox, void)
1792 bool bCheck = rBox.get_active();
1793 if ( m_xAsianSupportCB.get() == &rBox )
1795 bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly(u"DefaultLocale_CJK");
1796 bCheck = ( bCheck && !bReadonly );
1797 m_xAsianLanguageLB->set_sensitive( bCheck );
1798 if (rBox.get_sensitive())
1799 m_bOldAsian = bCheck;
1801 else if ( m_xCTLSupportCB.get() == &rBox )
1803 bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly(u"DefaultLocale_CTL");
1804 bCheck = ( bCheck && !bReadonly );
1805 m_xComplexLanguageLB->set_sensitive( bCheck );
1806 if (rBox.get_sensitive())
1807 m_bOldCtl = bCheck;
1809 else
1810 SAL_WARN( "cui.options", "OfaLanguagesTabPage::SupportHdl(): wrong rBox" );
1813 namespace
1815 void lcl_checkLanguageCheckBox(weld::CheckButton& _rCB, bool _bNewValue, bool _bOldValue)
1817 if ( _bNewValue )
1818 _rCB.set_active(true);
1819 else
1820 _rCB.set_active( _bOldValue );
1821 // #i15082# do not call save_state() in running dialog...
1822 // _rCB.save_state();
1823 _rCB.set_sensitive( !_bNewValue );
1827 IMPL_LINK_NOARG(OfaLanguagesTabPage, LocaleSettingHdl, weld::ComboBox&, void)
1829 LanguageType eLang = m_xLocaleSettingLB->get_active_id();
1830 SvtScriptType nType = SvtLanguageOptions::GetScriptTypeOfLanguage(eLang);
1831 // first check if CTL must be enabled
1832 // #103299# - if CTL font setting is not readonly
1833 if(!pLangConfig->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::E_CTLFONT))
1835 bool bIsCTLFixed = bool(nType & SvtScriptType::COMPLEX);
1836 lcl_checkLanguageCheckBox(*m_xCTLSupportCB, bIsCTLFixed, m_bOldCtl);
1837 SupportHdl(*m_xCTLSupportCB);
1839 // second check if CJK must be enabled
1840 // #103299# - if CJK support is not readonly
1841 if(!SvtCJKOptions::IsAnyReadOnly())
1843 bool bIsCJKFixed = bool(nType & SvtScriptType::ASIAN);
1844 lcl_checkLanguageCheckBox(*m_xAsianSupportCB, bIsCJKFixed, m_bOldAsian);
1845 SupportHdl(*m_xAsianSupportCB);
1848 const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry(
1849 (eLang == LANGUAGE_USER_SYSTEM_CONFIG) ? MsLangId::getConfiguredSystemLanguage() : eLang);
1850 static constexpr OUString aDefaultID = u"default"_ustr;
1851 // Update the "Default ..." currency.
1852 m_xCurrencyLB->remove_id(aDefaultID);
1853 OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol();
1854 m_xCurrencyLB->insert(0, aDefaultCurr, &aDefaultID, nullptr, nullptr);
1855 assert(m_xCurrencyLB->find_id(aDefaultID) != -1);
1856 m_xCurrencyLB->set_active_text(aDefaultCurr);
1858 // obtain corresponding locale data
1859 LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang) ));
1861 // update the decimal separator key of the related CheckBox
1862 OUString sTempLabel(m_sDecimalSeparatorLabel);
1863 sTempLabel = sTempLabel.replaceFirst("%1", aLocaleWrapper.getNumDecimalSep() );
1864 m_xDecimalSeparatorCB->set_label(sTempLabel);
1866 // update the date acceptance patterns
1867 OUString aDatePatternsString = lcl_getDatePatternsConfigString( aLocaleWrapper);
1868 m_bDatePatternsValid = true;
1869 m_xDatePatternsED->set_text( aDatePatternsString);
1870 m_xDatePatternsED->set_message_type(weld::EntryMessageType::Normal);
1873 IMPL_LINK( OfaLanguagesTabPage, DatePatternsHdl, weld::Entry&, rEd, void )
1875 OUString aPatterns(rEd.get_text());
1876 bool bModified = false;
1877 const bool bValid = validateDatePatterns( bModified, aPatterns);
1878 if (bModified)
1880 // gtk3 keeps the cursor position on equal length set_text() but at
1881 // least the 'gen' backend does not and resets to 0.
1882 const int nCursorPos = rEd.get_position();
1883 rEd.set_text(aPatterns);
1884 rEd.set_position(nCursorPos);
1886 if (bValid)
1887 rEd.set_message_type(weld::EntryMessageType::Normal);
1888 else
1889 rEd.set_message_type(weld::EntryMessageType::Error);
1890 m_bDatePatternsValid = bValid;
1893 bool OfaLanguagesTabPage::validateDatePatterns( bool& rbModified, OUString& rPatterns )
1895 bool bValid = true;
1896 if (!rPatterns.isEmpty())
1898 OUStringBuffer aBuf( rPatterns);
1899 sal_Int32 nChar = 0;
1900 for (sal_Int32 nIndex=0; nIndex >= 0 && bValid; ++nChar)
1902 const OUString aPat( rPatterns.getToken( 0, ';', nIndex));
1903 if (aPat.isEmpty() && nIndex < 0)
1905 // Indicating failure when about to append a pattern is too
1906 // confusing. Empty patterns are ignored anyway when sequencing
1907 // to SvtSysLocale.
1908 continue; // for
1910 else if (aPat.getLength() < 2)
1911 bValid = false;
1912 else
1914 bool bY, bM, bD;
1915 bY = bM = bD = false;
1916 bool bSep = true;
1917 if (aPat.getLength() == 3)
1919 // Disallow a pattern that would match a numeric input with
1920 // decimal separator, like M.D
1921 const LanguageType eLang = m_xLocaleSettingLB->get_active_id();
1922 const LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang)));
1923 if ( aPat[1] == aLocaleWrapper.getNumDecimalSep().toChar()
1924 || aPat[1] == aLocaleWrapper.getNumDecimalSepAlt().toChar())
1926 bValid = false;
1929 for (sal_Int32 i = 0; i < aPat.getLength() && bValid; /*nop*/)
1931 const sal_Int32 j = i;
1932 const sal_uInt32 c = aPat.iterateCodePoints( &i);
1933 // Only one Y,M,D per pattern, separated by any character(s).
1934 switch (c)
1936 case 'y':
1937 case 'Y':
1938 if (bY || !bSep)
1939 bValid = false;
1940 else if (c == 'y')
1942 aBuf[nChar] = 'Y';
1943 rbModified = true;
1945 bY = true;
1946 bSep = false;
1947 break;
1948 case 'm':
1949 case 'M':
1950 if (bM || !bSep)
1951 bValid = false;
1952 else if (c == 'm')
1954 aBuf[nChar] = 'M';
1955 rbModified = true;
1957 bM = true;
1958 bSep = false;
1959 break;
1960 case 'd':
1961 case 'D':
1962 if (bD || !bSep)
1963 bValid = false;
1964 else if (c == 'd')
1966 aBuf[nChar] = 'D';
1967 rbModified = true;
1969 bD = true;
1970 bSep = false;
1971 break;
1972 default:
1973 // A pattern must not start with a separator (but
1974 // may end with).
1975 if (!(bY || bM || bD))
1976 bValid = false;
1977 bSep = true;
1979 nChar += i-j;
1981 // At least one of Y,M,D
1982 bValid &= (bY || bM || bD);
1985 if (rbModified)
1986 rPatterns = aBuf.makeStringAndClear();
1988 return bValid;
1991 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */