1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <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 <unotools/syslocaleoptions.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <comphelper/propertysequence.hxx>
40 #include <svtools/langtab.hxx>
41 #include <editeng/unolingu.hxx>
42 #include <editeng/langitem.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <comphelper/string.hxx>
45 #include <rtl/ustrbuf.hxx>
46 #include <editeng/editids.hrc>
47 #include <svx/svxids.hrc>
48 #include <svl/intitem.hxx>
49 #include <svl/voiditem.hxx>
50 #include <GraphicsTestsDialog.hxx>
51 #include <unotools/searchopt.hxx>
52 #include <sal/log.hxx>
53 #include <officecfg/Office/Canvas.hxx>
54 #include <officecfg/Office/Common.hxx>
55 #include <officecfg/Setup.hxx>
56 #include <comphelper/configuration.hxx>
57 #include <comphelper/diagnose_ex.hxx>
58 #if HAVE_FEATURE_BREAKPAD
59 #include <desktop/crashreport.hxx>
60 #endif
61
62 #include <com/sun/star/configuration/theDefaultProvider.hpp>
63 #include <com/sun/star/container/XNameAccess.hpp>
64 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
65 #include <com/sun/star/beans/NamedValue.hpp>
66 #include <com/sun/star/beans/XPropertySet.hpp>
67 #include <com/sun/star/util/XChangesBatch.hpp>
68 #include <com/sun/star/uno/Any.hxx>
69 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
70 #include <com/sun/star/container/XSet.hpp>
71 #include <com/sun/star/i18n/ScriptType.hpp>
72 #include <com/sun/star/office/Quickstart.hpp>
73 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
74
75 #include <vcl/vclenum.hxx>
76 #include <vcl/svapp.hxx>
77 #include <vcl/settings.hxx>
78 #include <vcl/window.hxx>
79 #include <vcl/skia/SkiaHelper.hxx>
80 #include <bitmaps.hlst>
81
82 #include "optgdlg.hxx"
83 #include <svtools/apearcfg.hxx>
84 #include <svtools/optionsdrawinglayer.hxx>
85 #include <svtools/restartdialog.hxx>
86 #include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
87 #include <vcl/unohelp2.hxx>
88
89 #if defined(_WIN32)
90 #include <systools/win32/winstoreutil.hxx>
91 #include <vcl/fileregistration.hxx>
92 #endif
93 using namespace ::com::sun::star::uno;
94 using namespace ::com::sun::star::lang;
95 using namespace ::com::sun::star::beans;
96 using namespace ::com::sun::star::container;
97 using namespace ::com::sun::star::util;
98 using namespace ::utl;
99
100 // class OfaMiscTabPage --------------------------------------------------
101
DeactivatePage(SfxItemSet * pSet_)102 DeactivateRC OfaMiscTabPage::DeactivatePage( SfxItemSet* pSet_ )
103 {
104 if ( pSet_ )
105 FillItemSet( pSet_ );
106 return DeactivateRC::LeavePage;
107 }
108
109 namespace
110 {
impl_SystemFileOpenServiceName()111 const OUString & impl_SystemFileOpenServiceName()
112 {
113 #if defined(_WIN32)
114 static constexpr OUString gPicker = u"com.sun.star.ui.dialogs.SystemFilePicker"_ustr;
115 return gPicker;
116 #elif defined MACOSX
117 static constexpr OUString gPicker = u"com.sun.star.ui.dialogs.AquaFilePicker"_ustr;
118 return gPicker;
119 #else
120 return EMPTY_OUSTRING;
121 #endif
122 }
123
lcl_HasSystemFilePicker()124 bool lcl_HasSystemFilePicker()
125 {
126 if( Application::hasNativeFileSelection() )
127 return true;
128
129 // Otherwise fall-back on querying services
130 bool bRet = false;
131 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
132
133 Reference< XContentEnumerationAccess > xEnumAccess( xFactory, UNO_QUERY );
134 Reference< XSet > xSet( xFactory, UNO_QUERY );
135
136 if ( ! xEnumAccess.is() || ! xSet.is() )
137 return bRet;
138
139 try
140 {
141 const OUString& aFileService = impl_SystemFileOpenServiceName();
142 Reference< XEnumeration > xEnum = xEnumAccess->createContentEnumeration( aFileService );
143 if ( xEnum.is() && xEnum->hasMoreElements() )
144 bRet = true;
145 }
146 catch (const IllegalArgumentException&)
147 {
148 }
149 catch (const ElementExistException&)
150 {
151 }
152 return bRet;
153 }
154 }
155
OfaMiscTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)156 OfaMiscTabPage::OfaMiscTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
157 : SfxTabPage(pPage, pController, u"cui/ui/optgeneralpage.ui"_ustr, u"OptGeneralPage"_ustr, &rSet)
158 , m_xExtHelpCB(m_xBuilder->weld_check_button(u"exthelp"_ustr))
159 , m_xExtHelpImg(m_xBuilder->weld_widget(u"lockexthelp"_ustr))
160 , m_xPopUpNoHelpCB(m_xBuilder->weld_check_button(u"popupnohelp"_ustr))
161 , m_xPopUpNoHelpImg(m_xBuilder->weld_widget(u"lockpopupnohelp"_ustr))
162 , m_xShowTipOfTheDay(m_xBuilder->weld_check_button(u"cbShowTipOfTheDay"_ustr))
163 , m_xShowTipOfTheDayImg(m_xBuilder->weld_widget(u"lockcbShowTipOfTheDay"_ustr))
164 , m_xFileDlgFrame(m_xBuilder->weld_widget(u"filedlgframe"_ustr))
165 , m_xFileDlgROImage(m_xBuilder->weld_widget(u"lockimage"_ustr))
166 , m_xFileDlgCB(m_xBuilder->weld_check_button(u"filedlg"_ustr))
167 , m_xDocStatusCB(m_xBuilder->weld_check_button(u"docstatus"_ustr))
168 , m_xDocStatusImg(m_xBuilder->weld_widget(u"lockdocstatus"_ustr))
169 , m_xYearFrame(m_xBuilder->weld_widget(u"yearframe"_ustr))
170 , m_xYearLabel(m_xBuilder->weld_label(u"yearslabel"_ustr))
171 , m_xYearValueField(m_xBuilder->weld_spin_button(u"year"_ustr))
172 , m_xToYearFT(m_xBuilder->weld_label(u"toyear"_ustr))
173 , m_xYearFrameImg(m_xBuilder->weld_widget(u"lockyears"_ustr))
174 #if HAVE_FEATURE_BREAKPAD
175 , m_xPrivacyFrame(m_xBuilder->weld_widget("privacyframe"))
176 , m_xCrashReport(m_xBuilder->weld_check_button("crashreport"))
177 , m_xCrashReportImg(m_xBuilder->weld_widget("lockcrashreport"))
178 #endif
179 #if defined(_WIN32)
180 , m_xQuickStarterFrame(m_xBuilder->weld_widget("quickstarter"))
181 , m_xQuickLaunchCB(m_xBuilder->weld_check_button("quicklaunch"))
182 , m_xQuickLaunchImg(m_xBuilder->weld_widget("lockquicklaunch"))
183 , m_xFileAssocFrame(m_xBuilder->weld_widget("fileassoc"))
184 , m_xFileAssocBtn(m_xBuilder->weld_button("assocfiles"))
185 , m_xPerformFileExtCheck(m_xBuilder->weld_check_button("cbPerformFileExtCheck"))
186 , m_xPerformFileExtImg(m_xBuilder->weld_widget("lockcbPerformFileExtCheck"))
187 #endif
188 {
189 #if HAVE_FEATURE_BREAKPAD
190 m_xPrivacyFrame->show();
191 #endif
192
193 #if defined(_WIN32)
194 // Store-packaged apps (located under the protected Program Files\WindowsApps) can't use normal
195 // shell shortcuts to their exe. TODO: show a button to open "Startup Apps" system applet?
196 if (!sal::systools::IsStorePackagedApp())
197 m_xQuickStarterFrame->show();
198
199 m_xFileAssocFrame->show();
200 m_xFileAssocBtn->connect_clicked(LINK(this, OfaMiscTabPage, FileAssocClick));
201 #endif
202
203 m_aStrDateInfo = m_xToYearFT->get_label();
204 m_xYearValueField->connect_value_changed( LINK( this, OfaMiscTabPage, TwoFigureHdl ) );
205
206 SetExchangeSupport();
207 }
208
~OfaMiscTabPage()209 OfaMiscTabPage::~OfaMiscTabPage()
210 {
211 }
212
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)213 std::unique_ptr<SfxTabPage> OfaMiscTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
214 {
215 return std::make_unique<OfaMiscTabPage>( pPage, pController, *rAttrSet );
216 }
217
GetAllStrings()218 OUString OfaMiscTabPage::GetAllStrings()
219 {
220 OUString sAllStrings;
221 OUString labels[] = { u"label1"_ustr, u"label2"_ustr, u"label4"_ustr, u"label5"_ustr, u"yearslabel"_ustr,
222 u"toyear"_ustr, u"label8"_ustr, u"label9"_ustr };
223
224 for (const auto& label : labels)
225 {
226 if (const auto pString = m_xBuilder->weld_label(label))
227 sAllStrings += pString->get_label() + " ";
228 }
229
230 OUString checkButton[]
231 = { u"exthelp"_ustr, u"popupnohelp"_ustr, u"cbShowTipOfTheDay"_ustr, u"filedlg"_ustr,
232 u"docstatus"_ustr, u"crashreport"_ustr, u"quicklaunch"_ustr, u"cbPerformFileExtCheck"_ustr };
233
234 for (const auto& check : checkButton)
235 {
236 if (const auto pString = m_xBuilder->weld_check_button(check))
237 sAllStrings += pString->get_label() + " ";
238 }
239
240 if (const auto pString = m_xBuilder->weld_button(u"assocfiles"_ustr))
241 sAllStrings += pString->get_label() + " ";
242
243 return sAllStrings.replaceAll("_", "");
244 }
245
FillItemSet(SfxItemSet * rSet)246 bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet )
247 {
248 bool bModified = false;
249 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
250
251 if ( m_xPopUpNoHelpCB->get_state_changed_from_saved() )
252 officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::set(m_xPopUpNoHelpCB->get_active(), batch);
253
254 if ( m_xExtHelpCB->get_state_changed_from_saved() )
255 officecfg::Office::Common::Help::ExtendedTip::set(m_xExtHelpCB->get_active(), batch);
256
257 if ( m_xShowTipOfTheDay->get_state_changed_from_saved() )
258 {
259 officecfg::Office::Common::Misc::ShowTipOfTheDay::set(m_xShowTipOfTheDay->get_active(), batch);
260 bModified = true;
261 }
262
263 if ( m_xFileDlgCB->get_state_changed_from_saved() )
264 {
265 officecfg::Office::Common::Misc::UseSystemFileDialog::set( !m_xFileDlgCB->get_active(), batch );
266 bModified = true;
267 }
268
269 if (m_xDocStatusCB->get_state_changed_from_saved())
270 {
271 officecfg::Office::Common::Print::PrintingModifiesDocument::set(m_xDocStatusCB->get_active(), batch);
272 bModified = true;
273 }
274
275 const SfxUInt16Item* pUInt16Item = GetOldItem( *rSet, SID_ATTR_YEAR2000 );
276 sal_uInt16 nNum = static_cast<sal_uInt16>(m_xYearValueField->get_text().toInt32());
277 if ( pUInt16Item && pUInt16Item->GetValue() != nNum )
278 {
279 bModified = true;
280 rSet->Put( SfxUInt16Item( SID_ATTR_YEAR2000, nNum ) );
281 }
282
283 #if HAVE_FEATURE_BREAKPAD
284 if (m_xCrashReport->get_state_changed_from_saved())
285 {
286 officecfg::Office::Common::Misc::CrashReport::set(m_xCrashReport->get_active(), batch);
287 bModified = true;
288 }
289 #endif
290
291 #if defined(_WIN32)
292 if (m_xPerformFileExtCheck->get_state_changed_from_saved())
293 {
294 officecfg::Office::Common::Misc::PerformFileExtCheck::set(
295 m_xPerformFileExtCheck->get_active(), batch);
296 bModified = true;
297 }
298
299 if( m_xQuickLaunchCB->get_state_changed_from_saved())
300 {
301 rSet->Put(SfxBoolItem(SID_ATTR_QUICKLAUNCHER, m_xQuickLaunchCB->get_active()));
302 bModified = true;
303 }
304 #endif
305
306 batch->commit();
307
308 return bModified;
309 }
310
Reset(const SfxItemSet * rSet)311 void OfaMiscTabPage::Reset( const SfxItemSet* rSet )
312 {
313 bool bEnable = !officecfg::Office::Common::Help::ExtendedTip::isReadOnly();
314 m_xExtHelpCB->set_active( officecfg::Office::Common::Help::Tip::get() &&
315 officecfg::Office::Common::Help::ExtendedTip::get() );
316 m_xExtHelpCB->set_sensitive(bEnable);
317 m_xExtHelpImg->set_visible(!bEnable);
318 m_xExtHelpCB->save_state();
319
320 bEnable = !officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::isReadOnly();
321 m_xPopUpNoHelpCB->set_active( officecfg::Office::Common::Help::BuiltInHelpNotInstalledPopUp::get() );
322 m_xPopUpNoHelpCB->set_sensitive(bEnable);
323 m_xPopUpNoHelpImg->set_visible(!bEnable);
324 m_xPopUpNoHelpCB->save_state();
325
326 bEnable = !officecfg::Office::Common::Misc::ShowTipOfTheDay::isReadOnly();
327 m_xShowTipOfTheDay->set_active( officecfg::Office::Common::Misc::ShowTipOfTheDay::get() );
328 m_xShowTipOfTheDay->set_sensitive(bEnable);
329 m_xShowTipOfTheDayImg->set_visible(!bEnable);
330 m_xShowTipOfTheDay->save_state();
331
332 if (!lcl_HasSystemFilePicker())
333 m_xFileDlgFrame->hide();
334 else
335 {
336 bEnable = !officecfg::Office::Common::Misc::UseSystemFileDialog::isReadOnly();
337 m_xFileDlgCB->set_sensitive(bEnable);
338 m_xFileDlgROImage->set_visible(!bEnable);
339 }
340 m_xFileDlgCB->set_active(!officecfg::Office::Common::Misc::UseSystemFileDialog::get());
341 m_xFileDlgCB->save_state();
342
343 bEnable = !officecfg::Office::Common::Print::PrintingModifiesDocument::isReadOnly();
344 m_xDocStatusCB->set_active(officecfg::Office::Common::Print::PrintingModifiesDocument::get());
345 m_xDocStatusCB->set_sensitive(bEnable);
346 m_xDocStatusImg->set_visible(!bEnable);
347 m_xDocStatusCB->save_state();
348
349 bEnable = !officecfg::Office::Common::DateFormat::TwoDigitYear::isReadOnly();
350 m_xYearLabel->set_sensitive(bEnable);
351 m_xYearValueField->set_sensitive(bEnable);
352 m_xToYearFT->set_sensitive(bEnable);
353 m_xYearFrameImg->set_visible(!bEnable);
354
355 if ( const SfxUInt16Item* pYearItem = rSet->GetItemIfSet( SID_ATTR_YEAR2000, false ) )
356 {
357 m_xYearValueField->set_value( pYearItem->GetValue() );
358 TwoFigureHdl(*m_xYearValueField);
359 }
360 else
361 m_xYearFrame->set_sensitive(false);
362
363 #if HAVE_FEATURE_BREAKPAD
364 m_xCrashReport->set_active(officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::IsDumpEnable());
365 m_xCrashReport->set_sensitive(!officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable());
366 m_xCrashReportImg->set_visible(officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable());
367 m_xCrashReport->save_state();
368 #endif
369
370 #if defined(_WIN32)
371 if (const SfxBoolItem* pItem = rSet->GetItemIfSet( SID_ATTR_QUICKLAUNCHER, false ))
372 {
373 m_xQuickLaunchCB->set_active( pItem->GetValue() );
374 }
375 else
376 {
377 // quickstart not installed
378 m_xQuickStarterFrame->hide();
379 }
380
381 m_xQuickLaunchCB->save_state();
382
383 m_xPerformFileExtCheck->set_active(
384 officecfg::Office::Common::Misc::PerformFileExtCheck::get());
385 m_xPerformFileExtCheck->save_state();
386 m_xPerformFileExtCheck->set_sensitive(!officecfg::Office::Common::Misc::PerformFileExtCheck::isReadOnly());
387 m_xPerformFileExtImg->set_visible(officecfg::Office::Common::Misc::PerformFileExtCheck::isReadOnly());
388 #endif
389 }
390
IMPL_LINK_NOARG(OfaMiscTabPage,TwoFigureHdl,weld::SpinButton &,void)391 IMPL_LINK_NOARG( OfaMiscTabPage, TwoFigureHdl, weld::SpinButton&, void )
392 {
393 OUString aOutput( m_aStrDateInfo );
394 OUString aStr( m_xYearValueField->get_text() );
395 sal_Int32 nNum = aStr.toInt32();
396 if ( aStr.getLength() != 4 || nNum < m_xYearValueField->get_min() || nNum > m_xYearValueField->get_max() )
397 aOutput += "????";
398 else
399 {
400 nNum += 99;
401 aOutput += OUString::number( nNum );
402 }
403 m_xToYearFT->set_label( aOutput );
404 }
405
406 #if defined(_WIN32)
IMPL_STATIC_LINK_NOARG(OfaMiscTabPage,FileAssocClick,weld::Button &,void)407 IMPL_STATIC_LINK_NOARG(OfaMiscTabPage, FileAssocClick, weld::Button&, void)
408 {
409 vcl::fileregistration::LaunchRegistrationUI();
410 }
411 #endif
412
413 class CanvasSettings
414 {
415 public:
416 CanvasSettings();
417
418 bool IsHardwareAccelerationAvailable() const;
419
420 private:
421 typedef std::vector< std::pair<OUString,Sequence<OUString> > > ServiceVector;
422
423 Reference<XNameAccess> mxForceFlagNameAccess;
424 ServiceVector maAvailableImplementations;
425 mutable bool mbHWAccelAvailable;
426 mutable bool mbHWAccelChecked;
427 };
428
CanvasSettings()429 CanvasSettings::CanvasSettings() :
430 mbHWAccelAvailable(false),
431 mbHWAccelChecked(false)
432 {
433 try
434 {
435 Reference<XMultiServiceFactory> xConfigProvider(
436 css::configuration::theDefaultProvider::get(
437 comphelper::getProcessComponentContext()));
438
439 Sequence<Any> aArgs1(comphelper::InitAnyPropertySequence(
440 {
441 {"nodepath", Any(u"/org.openoffice.Office.Canvas"_ustr)}
442 }));
443 mxForceFlagNameAccess.set(
444 xConfigProvider->createInstanceWithArguments(
445 u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr,
446 aArgs1 ),
447 UNO_QUERY_THROW );
448
449 Sequence<Any> aArgs2(comphelper::InitAnyPropertySequence(
450 {
451 {"nodepath", Any(u"/org.openoffice.Office.Canvas/CanvasServiceList"_ustr)}
452 }));
453 Reference<XNameAccess> xNameAccess(
454 xConfigProvider->createInstanceWithArguments(
455 u"com.sun.star.configuration.ConfigurationAccess"_ustr,
456 aArgs2 ), UNO_QUERY_THROW );
457 Reference<XHierarchicalNameAccess> xHierarchicalNameAccess(
458 xNameAccess, UNO_QUERY_THROW);
459
460 for (auto& serviceName : xNameAccess->getElementNames())
461 {
462 Reference<XNameAccess> xEntryNameAccess(
463 xHierarchicalNameAccess->getByHierarchicalName(serviceName),
464 UNO_QUERY );
465
466 if( xEntryNameAccess.is() )
467 {
468 Sequence<OUString> preferredImplementations;
469 if( xEntryNameAccess->getByName(u"PreferredImplementations"_ustr) >>= preferredImplementations )
470 maAvailableImplementations.emplace_back(serviceName, preferredImplementations);
471 }
472 }
473 }
474 catch (const Exception&)
475 {
476 }
477 }
478
IsHardwareAccelerationAvailable() const479 bool CanvasSettings::IsHardwareAccelerationAvailable() const
480 {
481 if( !mbHWAccelChecked )
482 {
483 mbHWAccelChecked = true;
484
485 Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
486
487 // check whether any of the service lists has an
488 // implementation that presents the "HardwareAcceleration" property
489 for (auto const& availableImpl : maAvailableImplementations)
490 {
491 for (auto& currImpl : availableImpl.second)
492 {
493 try
494 {
495 Reference<XPropertySet> xPropSet( xFactory->createInstance(
496 currImpl.trim() ),
497 UNO_QUERY_THROW );
498 bool bHasAccel(false);
499 if( xPropSet->getPropertyValue(u"HardwareAcceleration"_ustr) >>= bHasAccel )
500 if( bHasAccel )
501 {
502 mbHWAccelAvailable = true;
503 return mbHWAccelAvailable;
504 }
505 }
506 catch (const Exception&)
507 {
508 }
509 }
510 }
511 }
512
513 return mbHWAccelAvailable;
514 }
515
516 // class OfaViewTabPage --------------------------------------------------
517
OfaViewTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)518 OfaViewTabPage::OfaViewTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
519 : SfxTabPage(pPage, pController, u"cui/ui/optviewpage.ui"_ustr, u"OptViewPage"_ustr, &rSet)
520 , pCanvasSettings(new CanvasSettings)
521 , m_xFontAntiAliasing(m_xBuilder->weld_check_button(u"aafont"_ustr))
522 , m_xFontAntiAliasingImg(m_xBuilder->weld_widget(u"lockaafont"_ustr))
523 , m_xAAPointLimitLabel(m_xBuilder->weld_label(u"aafrom"_ustr))
524 , m_xAAPointLimitLabelImg(m_xBuilder->weld_widget(u"lockaafrom"_ustr))
525 , m_xAAPointLimit(m_xBuilder->weld_metric_spin_button(u"aanf"_ustr, FieldUnit::PIXEL))
526 , m_xFontShowCB(m_xBuilder->weld_check_button(u"showfontpreview"_ustr))
527 , m_xFontShowImg(m_xBuilder->weld_widget(u"lockshowfontpreview"_ustr))
528 , m_xUseHardwareAccell(m_xBuilder->weld_check_button(u"useaccel"_ustr))
529 , m_xUseHardwareAccellImg(m_xBuilder->weld_widget(u"lockuseaccel"_ustr))
530 , m_xUseAntiAliase(m_xBuilder->weld_check_button(u"useaa"_ustr))
531 , m_xUseAntiAliaseImg(m_xBuilder->weld_widget(u"lockuseaa"_ustr))
532 , m_xUseSkia(m_xBuilder->weld_check_button(u"useskia"_ustr))
533 , m_xUseSkiaImg(m_xBuilder->weld_widget(u"lockuseskia"_ustr))
534 , m_xForceSkiaRaster(m_xBuilder->weld_check_button(u"forceskiaraster"_ustr))
535 , m_xForceSkiaRasterImg(m_xBuilder->weld_widget(u"lockforceskiaraster"_ustr))
536 , m_xSkiaStatusEnabled(m_xBuilder->weld_label(u"skiaenabled"_ustr))
537 , m_xSkiaStatusDisabled(m_xBuilder->weld_label(u"skiadisabled"_ustr))
538 , m_xSkiaLog(m_xBuilder->weld_button(u"btnSkialog"_ustr))
539 , m_xMouseMiddleLabel(m_xBuilder->weld_label(u"label12"_ustr))
540 , m_xMouseMiddleLB(m_xBuilder->weld_combo_box(u"mousemiddle"_ustr))
541 , m_xMouseMiddleImg(m_xBuilder->weld_widget(u"lockmousemiddle"_ustr))
542 , m_xRunGPTests(m_xBuilder->weld_button(u"btn_rungptest"_ustr))
543 {
544 m_xFontAntiAliasing->connect_toggled( LINK( this, OfaViewTabPage, OnAntialiasingToggled ) );
545
546 m_xUseSkia->connect_toggled(LINK(this, OfaViewTabPage, OnUseSkiaToggled));
547 m_xSkiaLog->connect_clicked(LINK(this, OfaViewTabPage, OnCopySkiaLog));
548
549 m_xRunGPTests->connect_clicked(LINK(this, OfaViewTabPage, OnRunGPTestClick));
550
551 // Hide "Run Graphics Test" button if Experimental Mode is off
552 if (!officecfg::Office::Common::Misc::ExperimentalMode::get())
553 m_xRunGPTests->hide();
554 }
555
~OfaViewTabPage()556 OfaViewTabPage::~OfaViewTabPage()
557 {
558 }
559
IMPL_LINK_NOARG(OfaViewTabPage,OnRunGPTestClick,weld::Button &,void)560 IMPL_LINK_NOARG(OfaViewTabPage, OnRunGPTestClick, weld::Button&, void)
561 {
562 GraphicsTestsDialog m_xGraphicsTestDialog(m_xContainer.get());
563 m_xGraphicsTestDialog.run();
564 }
565
IMPL_LINK_NOARG(OfaViewTabPage,OnAntialiasingToggled,weld::Toggleable &,void)566 IMPL_LINK_NOARG( OfaViewTabPage, OnAntialiasingToggled, weld::Toggleable&, void )
567 {
568 bool bAAEnabled = m_xFontAntiAliasing->get_active() && !officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::isReadOnly();
569
570 m_xAAPointLimitLabel->set_sensitive(bAAEnabled);
571 m_xAAPointLimit->set_sensitive(bAAEnabled);
572 }
573
IMPL_LINK_NOARG(OfaViewTabPage,OnUseSkiaToggled,weld::Toggleable &,void)574 IMPL_LINK_NOARG(OfaViewTabPage, OnUseSkiaToggled, weld::Toggleable&, void)
575 {
576 UpdateSkiaStatus();
577 }
578
IMPL_LINK_NOARG(OfaViewTabPage,OnCopySkiaLog,weld::Button &,void)579 IMPL_LINK_NOARG(OfaViewTabPage, OnCopySkiaLog, weld::Button&, void)
580 {
581 #if HAVE_FEATURE_SKIA
582 css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard =
583 css::datatransfer::clipboard::SystemClipboard::create(
584 comphelper::getProcessComponentContext());
585 OUString sInfo = SkiaHelper::readLog();
586 vcl::unohelper::TextDataObject::CopyStringTo(sInfo, xClipboard);
587 m_xSkiaLog->set_from_icon_name(RID_SVXBMP_COPY);
588 #endif
589 }
590
HideSkiaWidgets()591 void OfaViewTabPage::HideSkiaWidgets()
592 {
593 m_xUseSkia->hide();
594 m_xForceSkiaRaster->hide();
595 m_xSkiaStatusEnabled->hide();
596 m_xSkiaStatusDisabled->hide();
597 m_xSkiaLog->hide();
598 }
599
UpdateSkiaStatus()600 void OfaViewTabPage::UpdateSkiaStatus()
601 {
602 #if HAVE_FEATURE_SKIA
603 bool skiaHidden = true;
604
605 // For now Skia is used mainly on Windows, enable the controls there.
606 if (Application::GetToolkitName() == "win")
607 skiaHidden = false;
608 // It can also be used on Linux, but only with the rarely used 'gen' backend.
609 if (Application::GetToolkitName() == "x11")
610 skiaHidden = false;
611 // OSX backend has Skia support too.
612 if (Application::GetToolkitName() == "osx")
613 skiaHidden = false;
614
615 if (skiaHidden)
616 {
617 HideSkiaWidgets();
618 return;
619 }
620
621 // Easier than a custom translation string.
622 bool bEnabled = SkiaHelper::isVCLSkiaEnabled();
623 m_xSkiaStatusEnabled->set_visible(bEnabled);
624 m_xSkiaStatusDisabled->set_visible(!bEnabled);
625
626 #if defined(MACOSX) || defined(_WIN32)
627 m_xUseSkia->set_sensitive(false); // macOS/win can __only__ render via skia
628 #else
629 m_xUseSkia->set_sensitive(!officecfg::Office::Common::VCL::UseSkia::isReadOnly());
630 #endif
631 m_xUseSkiaImg->set_visible(officecfg::Office::Common::VCL::UseSkia::isReadOnly());
632 m_xForceSkiaRaster->set_sensitive(m_xUseSkia->get_active() && !officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly());
633 m_xForceSkiaRasterImg->set_visible(officecfg::Office::Common::VCL::ForceSkiaRaster::isReadOnly());
634 m_xSkiaLog->set_sensitive(bEnabled);
635
636 // Technically the 'use hardware acceleration' option could be used to mean !forceSkiaRaster, but the implementation
637 // of the option is so tied to the implementation of the canvas module that it's simpler to ignore it.
638 UpdateHardwareAccelStatus();
639 #else
640 HideSkiaWidgets();
641 #endif
642 }
643
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)644 std::unique_ptr<SfxTabPage> OfaViewTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
645 {
646 return std::make_unique<OfaViewTabPage>(pPage, pController, *rAttrSet);
647 }
648
GetAllStrings()649 OUString OfaViewTabPage::GetAllStrings()
650 {
651 OUString sAllStrings;
652 OUString labels[] = { u"label16"_ustr, u"label1"_ustr, u"label6"_ustr, u"label15"_ustr,
653 u"label14"_ustr, u"label8"_ustr, u"label9"_ustr, u"label4"_ustr, u"label12"_ustr,
654 u"label2"_ustr, u"skiaenabled"_ustr, u"skiadisabled"_ustr, u"label5"_ustr, u"aafrom"_ustr };
655
656 for (const auto& label : labels)
657 {
658 if (const auto pString = m_xBuilder->weld_label(label))
659 sAllStrings += pString->get_label() + " ";
660 }
661
662 OUString checkButton[]
663 = { u"useaccel"_ustr, u"useaa"_ustr, u"useskia"_ustr, u"forceskiaraster"_ustr, u"showfontpreview"_ustr, u"aafont"_ustr };
664
665 for (const auto& check : checkButton)
666 {
667 if (const auto pString = m_xBuilder->weld_check_button(check))
668 sAllStrings += pString->get_label() + " ";
669 }
670
671 sAllStrings += m_xSkiaLog->get_label() + " " + m_xRunGPTests->get_label() + " ";
672
673 return sAllStrings.replaceAll("_", "");
674 }
675
FillItemSet(SfxItemSet *)676 bool OfaViewTabPage::FillItemSet( SfxItemSet* )
677 {
678 bool bModified = false;
679 bool bRepaintWindows(false);
680
681 bool bAppearanceChanged = false;
682 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
683
684 // Middle Mouse Button
685 MouseMiddleButtonAction eOldMiddleMouse = static_cast<MouseMiddleButtonAction>(officecfg::Office::Common::View::Dialog::MiddleMouseButton::get());
686 short eNewMiddleMouse = m_xMouseMiddleLB->get_active();
687 if(eNewMiddleMouse > 2)
688 eNewMiddleMouse = 2;
689
690 if ( eNewMiddleMouse != static_cast<short>(eOldMiddleMouse) )
691 {
692 officecfg::Office::Common::View::Dialog::MiddleMouseButton::set(eNewMiddleMouse, batch);
693 bAppearanceChanged = true;
694 }
695
696 if (m_xFontAntiAliasing->get_state_changed_from_saved())
697 {
698 bool b = m_xFontAntiAliasing->get_active();
699 officecfg::Office::Common::View::FontAntiAliasing::Enabled::set(b, batch);
700 bAppearanceChanged = true;
701 }
702
703 if (m_xAAPointLimit->get_value_changed_from_saved())
704 {
705 sal_Int64 i = m_xAAPointLimit->get_value(FieldUnit::PIXEL);
706 officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::set(i, batch);
707 bAppearanceChanged = true;
708 }
709
710 std::shared_ptr<comphelper::ConfigurationChanges> xChanges(comphelper::ConfigurationChanges::create());
711
712 if (m_xFontShowCB->get_state_changed_from_saved())
713 {
714 officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::set(m_xFontShowCB->get_active(), xChanges);
715 bModified = true;
716 }
717
718 // #i95644# if disabled, do not use value, see in ::Reset()
719 if (m_xUseHardwareAccell->get_sensitive())
720 {
721 if(m_xUseHardwareAccell->get_state_changed_from_saved())
722 {
723 officecfg::Office::Canvas::ForceSafeServiceImpl::set(m_xUseHardwareAccell->get_active(), xChanges);
724 bModified = true;
725 }
726 }
727
728 // #i95644# if disabled, do not use value, see in ::Reset()
729 if (m_xUseAntiAliase->get_sensitive())
730 {
731 if (m_xUseAntiAliase->get_active() != SvtOptionsDrawinglayer::IsAntiAliasing())
732 {
733 SvtOptionsDrawinglayer::SetAntiAliasing(m_xUseAntiAliase->get_active(), /*bTemporary*/false);
734 bModified = true;
735 bRepaintWindows = true;
736 }
737 }
738
739 if (m_xUseSkia->get_state_changed_from_saved() ||
740 m_xForceSkiaRaster->get_state_changed_from_saved())
741 {
742 officecfg::Office::Common::VCL::UseSkia::set(m_xUseSkia->get_active(), xChanges);
743 officecfg::Office::Common::VCL::ForceSkiaRaster::set(m_xForceSkiaRaster->get_active(), xChanges);
744 bModified = true;
745 }
746
747 xChanges->commit();
748
749 if ( bAppearanceChanged )
750 {
751 batch->commit();
752 SvtTabAppearanceCfg::SetApplicationDefaults ( GetpApp() );
753 }
754
755 if(bRepaintWindows)
756 {
757 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow();
758
759 while(pAppWindow)
760 {
761 pAppWindow->Invalidate();
762 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow);
763 }
764 }
765
766 if (m_xUseSkia->get_state_changed_from_saved() ||
767 m_xForceSkiaRaster->get_state_changed_from_saved())
768 {
769 SolarMutexGuard aGuard;
770 if( svtools::executeRestartDialog(
771 comphelper::getProcessComponentContext(), nullptr,
772 svtools::RESTART_REASON_SKIA))
773 GetDialogController()->response(RET_OK);
774 }
775
776 return bModified;
777 }
778
Reset(const SfxItemSet *)779 void OfaViewTabPage::Reset( const SfxItemSet* )
780 {
781 bool bEnable = true;
782
783 // Middle Mouse Button
784 bEnable = !officecfg::Office::Common::View::Dialog::MiddleMouseButton::isReadOnly();
785 sal_Int16 nMiddleMouseButton = officecfg::Office::Common::View::Dialog::MiddleMouseButton::get();
786 m_xMouseMiddleLB->set_active(static_cast<short>(nMiddleMouseButton));
787 m_xMouseMiddleLabel->set_sensitive(bEnable);
788 m_xMouseMiddleLB->set_sensitive(bEnable);
789 m_xMouseMiddleImg->set_visible(!bEnable);
790 m_xMouseMiddleLB->save_value();
791
792 bEnable = !officecfg::Office::Common::View::FontAntiAliasing::Enabled::isReadOnly();
793 bool bFontAntiAliasing = officecfg::Office::Common::View::FontAntiAliasing::Enabled::get();
794 m_xFontAntiAliasing->set_active( bFontAntiAliasing );
795 m_xFontAntiAliasing->set_sensitive(bEnable);
796 m_xFontAntiAliasingImg->set_visible(!bEnable);
797
798 bEnable = !officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::isReadOnly();
799 sal_Int16 nFontAntiAliasingMinPixelHeight = officecfg::Office::Common::View::FontAntiAliasing::MinPixelHeight::get();
800 m_xAAPointLimit->set_value(nFontAntiAliasingMinPixelHeight, FieldUnit::PIXEL);
801 m_xAAPointLimit->set_sensitive(bEnable);
802 m_xAAPointLimitLabelImg->set_visible(!bEnable);
803
804 // WorkingSet
805 bEnable = !officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::isReadOnly();
806 m_xFontShowCB->set_active(officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::get());
807 m_xFontShowCB->set_sensitive(bEnable);
808 m_xFontShowImg->set_visible(!bEnable);
809
810 UpdateHardwareAccelStatus();
811 m_xUseHardwareAccell->save_state();
812
813 { // #i95644# AntiAliasing
814 m_xUseAntiAliase->set_active(SvtOptionsDrawinglayer::IsAntiAliasing());
815 bEnable = !officecfg::Office::Common::Drawinglayer::AntiAliasing::isReadOnly();
816 m_xUseAntiAliase->set_sensitive(bEnable);
817 m_xUseAntiAliaseImg->set_visible(!bEnable);
818 m_xUseAntiAliase->save_state();
819 }
820
821 #if defined(MACOSX) || defined(_WIN32)
822 m_xUseSkia->set_active(true); // macOS/win can __only__ render via skia
823 #else
824 m_xUseSkia->set_active(officecfg::Office::Common::VCL::UseSkia::get());
825 #endif
826 m_xForceSkiaRaster->set_active(officecfg::Office::Common::VCL::ForceSkiaRaster::get());
827 m_xUseSkia->save_state();
828 m_xForceSkiaRaster->save_state();
829
830 m_xFontAntiAliasing->save_state();
831 m_xAAPointLimit->save_value();
832 m_xFontShowCB->save_state();
833
834 OnAntialiasingToggled(*m_xFontAntiAliasing);
835 UpdateSkiaStatus();
836 }
837
UpdateHardwareAccelStatus()838 void OfaViewTabPage::UpdateHardwareAccelStatus()
839 {
840 // #i95644# HW accel (unified to disable mechanism)
841 bool bHardwareAccRO = officecfg::Office::Canvas::ForceSafeServiceImpl::isReadOnly();
842 if(pCanvasSettings->IsHardwareAccelerationAvailable())
843 {
844 m_xUseHardwareAccell->set_active(officecfg::Office::Canvas::ForceSafeServiceImpl::get());
845 m_xUseHardwareAccell->set_sensitive(!bHardwareAccRO);
846 m_xUseHardwareAccellImg->set_visible(bHardwareAccRO);
847 }
848 else
849 {
850 m_xUseHardwareAccell->set_active(false);
851 m_xUseHardwareAccell->set_sensitive(false);
852 m_xUseHardwareAccellImg->set_visible(true);
853 }
854 #if HAVE_FEATURE_SKIA
855 m_xUseHardwareAccell->set_sensitive(!bHardwareAccRO && !m_xUseSkia->get_active());
856 #endif
857 }
858
859 struct LanguageConfig_Impl
860 {
861 SvtCTLOptions aCTLLanguageOptions;
862 SvtSysLocaleOptions aSysLocaleOptions;
863 SvtLinguConfig aLinguConfig;
864 };
865
866 static bool bLanguageCurrentDoc_Impl = false;
867
868 // some things we'll need...
869 constexpr OUString sAccessSrvc = u"com.sun.star.configuration.ConfigurationAccess"_ustr;
870 constexpr OUStringLiteral sAccessUpdSrvc = u"com.sun.star.configuration.ConfigurationUpdateAccess";
871 constexpr OUString sInstalledLocalesPath = u"org.openoffice.Setup/Office/InstalledLocales"_ustr;
872 constexpr OUString sUserLocalePath = u"org.openoffice.Office.Linguistic/General"_ustr;
873 constexpr OUString sUserLocaleKey = u"UILocale"_ustr;
874 static Sequence< OUString > seqInstalledLanguages;
875
lcl_getDatePatternsConfigString(const LocaleDataWrapper & rLocaleWrapper)876 static OUString lcl_getDatePatternsConfigString( const LocaleDataWrapper& rLocaleWrapper )
877 {
878 const Sequence< OUString >& aDateAcceptancePatterns = rLocaleWrapper.getDateAcceptancePatterns();
879 sal_Int32 nPatterns = aDateAcceptancePatterns.getLength();
880 OUStringBuffer aBuf( nPatterns * 6 ); // 6 := length of Y-M-D;
881 SAL_WARN_IF( !nPatterns, "cui.options", "No date acceptance pattern");
882 if (nPatterns)
883 {
884 aBuf.append(aDateAcceptancePatterns[0]);
885 for (sal_Int32 i=1; i < nPatterns; ++i)
886 aBuf.append(";" + aDateAcceptancePatterns[i]);
887 }
888 return aBuf.makeStringAndClear();
889 }
890
891 namespace
892 {
893 //what ui language will be selected by default if the user override of General::UILocale is unset ?
GetInstalledLocaleForSystemUILanguage()894 LanguageTag GetInstalledLocaleForSystemUILanguage()
895 {
896 css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames());
897 return LanguageTag(getInstalledLocaleForSystemUILanguage(inst, false)).makeFallback();
898 }
899 }
900
OfaLanguagesTabPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rSet)901 OfaLanguagesTabPage::OfaLanguagesTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet)
902 : SfxTabPage(pPage, pController, u"cui/ui/optlanguagespage.ui"_ustr, u"OptLanguagesPage"_ustr, &rSet)
903 , pLangConfig(new LanguageConfig_Impl)
904 , m_bDatePatternsValid(false)
905 , m_xUserInterfaceLB(m_xBuilder->weld_combo_box(u"userinterface"_ustr))
906 , m_xLocaleSettingFT(m_xBuilder->weld_label(u"localesettingFT"_ustr))
907 , m_xLocaleSettingLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"localesetting"_ustr)))
908 , m_xLocaleSettingImg(m_xBuilder->weld_widget(u"locklocalesetting"_ustr))
909 , m_xDecimalSeparatorFT(m_xBuilder->weld_label(u"label6"_ustr))
910 , m_xDecimalSeparatorCB(m_xBuilder->weld_check_button(u"decimalseparator"_ustr))
911 , m_xDecimalSeparatorImg(m_xBuilder->weld_widget(u"lockdecimalseparator"_ustr))
912 , m_xCurrencyFT(m_xBuilder->weld_label(u"defaultcurrency"_ustr))
913 , m_xCurrencyLB(m_xBuilder->weld_combo_box(u"currencylb"_ustr))
914 , m_xCurrencyImg(m_xBuilder->weld_widget(u"lockcurrencylb"_ustr))
915 , m_xDatePatternsFT(m_xBuilder->weld_label(u"dataaccpatterns"_ustr))
916 , m_xDatePatternsED(m_xBuilder->weld_entry(u"datepatterns"_ustr))
917 , m_xDatePatternsImg(m_xBuilder->weld_widget(u"lockdatepatterns"_ustr))
918 , m_xWesternLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"westernlanguage"_ustr)))
919 , m_xWesternLanguageFT(m_xBuilder->weld_label(u"western"_ustr))
920 , m_xWesternLanguageImg(m_xBuilder->weld_widget(u"lockwesternlanguage"_ustr))
921 , m_xAsianLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"asianlanguage"_ustr)))
922 , m_xComplexLanguageLB(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"complexlanguage"_ustr)))
923 , m_xCurrentDocCB(m_xBuilder->weld_check_button(u"currentdoc"_ustr))
924 , m_xAsianSupportCB(m_xBuilder->weld_check_button(u"asiansupport"_ustr))
925 , m_xAsianSupportImg(m_xBuilder->weld_widget(u"lockasiansupport"_ustr))
926 , m_xCTLSupportCB(m_xBuilder->weld_check_button(u"ctlsupport"_ustr))
927 , m_xCTLSupportImg(m_xBuilder->weld_widget(u"lockctlsupport"_ustr))
928 , m_xIgnoreLanguageChangeCB(m_xBuilder->weld_check_button(u"ignorelanguagechange"_ustr))
929 , m_xIgnoreLanguageChangeImg(m_xBuilder->weld_widget(u"lockignorelanguagechange"_ustr))
930 {
931 // tdf#125483 save original default label
932 m_sDecimalSeparatorLabel = m_xDecimalSeparatorCB->get_label();
933
934 // initialize user interface language selection
935 m_sSystemDefaultString = SvtLanguageTable::GetLanguageString( LANGUAGE_SYSTEM );
936
937 OUString aUILang = m_sSystemDefaultString +
938 " - " +
939 SvtLanguageTable::GetLanguageString(GetInstalledLocaleForSystemUILanguage().getLanguageType());
940
941 m_xUserInterfaceLB->append(u"0"_ustr, aUILang);
942 m_xUserInterfaceLB->append_separator(u""_ustr);
943 try
944 {
945 Reference< XMultiServiceFactory > theConfigProvider(
946 css::configuration::theDefaultProvider::get(
947 comphelper::getProcessComponentContext()));
948 // find out which locales are currently installed and add them to the listbox
949 Sequence< Any > theArgs{ Any(NamedValue(u"nodepath"_ustr, Any(sInstalledLocalesPath))) };
950 Reference< XNameAccess > theNameAccess(
951 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs ), UNO_QUERY_THROW );
952 seqInstalledLanguages = theNameAccess->getElementNames();
953 LanguageType aLang = LANGUAGE_DONTKNOW;
954 std::vector< std::pair<sal_Int32, OUString> > aUILanguages;
955 for (sal_Int32 i=0; i<seqInstalledLanguages.getLength(); i++)
956 {
957 aLang = LanguageTag::convertToLanguageTypeWithFallback(seqInstalledLanguages[i]);
958 if (aLang != LANGUAGE_DONTKNOW)
959 {
960 OUString aLangStr( SvtLanguageTable::GetLanguageString( aLang ) );
961 aUILanguages.emplace_back(i+1, aLangStr);
962 }
963 }
964
965 std::sort(aUILanguages.begin(), aUILanguages.end(), [](const auto& l1, const auto& l2) {
966 static const auto aSorter = comphelper::string::NaturalStringSorter(
967 comphelper::getProcessComponentContext(),
968 Application::GetSettings().GetUILanguageTag().getLocale());
969 return aSorter.compare(l1.second, l2.second) < 0;
970 });
971
972 // tdf#114694: append the sorted list after the default entry and separator.
973 for (const auto & [ nGroupID, sGroupName ] : aUILanguages)
974 {
975 m_xUserInterfaceLB->append(OUString::number(nGroupID), sGroupName);
976 }
977
978 m_xUserInterfaceLB->set_active(0);
979
980 // find out whether the user has a specific locale specified
981 Sequence< Any > theArgs2{ Any(NamedValue(u"nodepath"_ustr, Any(sUserLocalePath))) };
982 theNameAccess.set(
983 theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs2 ), UNO_QUERY_THROW );
984 if (theNameAccess->hasByName(sUserLocaleKey))
985 theNameAccess->getByName(sUserLocaleKey) >>= m_sUserLocaleValue;
986 // select the user specified locale in the listbox
987 if (!m_sUserLocaleValue.isEmpty())
988 {
989 for (sal_Int32 i = 0, nEntryCount = m_xUserInterfaceLB->get_count(); i < nEntryCount; ++i)
990 {
991 sal_Int32 d = m_xUserInterfaceLB->get_id(i).toInt32();
992 if ( d > 0 && seqInstalledLanguages.getLength() > d-1 && seqInstalledLanguages[d-1] == m_sUserLocaleValue)
993 m_xUserInterfaceLB->set_active(i);
994 }
995 }
996
997 }
998 catch (const Exception &)
999 {
1000 // we'll just leave the box in its default setting and won't
1001 // even give it event handler...
1002 TOOLS_WARN_EXCEPTION("cui.options", "ignoring" );
1003 }
1004
1005 m_xWesternLanguageLB->SetLanguageList(
1006 SvxLanguageListFlags::WESTERN | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1007 LANGUAGE_SYSTEM, css::i18n::ScriptType::LATIN);
1008
1009 m_xAsianLanguageLB->SetLanguageList(
1010 SvxLanguageListFlags::CJK | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1011 LANGUAGE_SYSTEM, css::i18n::ScriptType::ASIAN);
1012
1013 m_xComplexLanguageLB->SetLanguageList(
1014 SvxLanguageListFlags::CTL | SvxLanguageListFlags::ONLY_KNOWN, true, false, true, true,
1015 LANGUAGE_SYSTEM, css::i18n::ScriptType::COMPLEX);
1016
1017 m_xLocaleSettingLB->SetLanguageList(
1018 SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN, false, false, false, true,
1019 LANGUAGE_USER_SYSTEM_CONFIG, css::i18n::ScriptType::WEAK);
1020
1021 const NfCurrencyTable& rCurrTab = SvNumberFormatter::GetTheCurrencyTable();
1022 const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry( LANGUAGE_SYSTEM );
1023 // insert SYSTEM entry
1024 OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol();
1025 m_xCurrencyLB->append(u"default"_ustr, aDefaultCurr);
1026 m_xCurrencyLB->append_separator(u""_ustr);
1027
1028 assert(m_xCurrencyLB->find_id(u"default"_ustr) != -1);
1029 // all currencies
1030 OUString aTwoSpace( u" "_ustr );
1031 sal_uInt16 nCurrCount = rCurrTab.size();
1032 std::vector< const NfCurrencyEntry* > aCurrencies;
1033 // first entry is SYSTEM, skip it
1034 for ( sal_uInt16 j=1; j < nCurrCount; ++j )
1035 {
1036 aCurrencies.push_back(&rCurrTab[j]);
1037 }
1038 std::sort(aCurrencies.begin(), aCurrencies.end(),
1039 [](const NfCurrencyEntry* c1, const NfCurrencyEntry* c2) {
1040 return c1->GetBankSymbol().compareTo(c2->GetBankSymbol()) < 0;
1041 });
1042
1043 for (auto &v : aCurrencies)
1044 {
1045 OUString aStr_ = v->GetBankSymbol() +
1046 aTwoSpace +
1047 v->GetSymbol();
1048 aStr_ = ApplyLreOrRleEmbedding( aStr_ ) +
1049 aTwoSpace +
1050 ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( v->GetLanguage() ) );
1051 m_xCurrencyLB->append(weld::toId(v), aStr_);
1052 }
1053
1054 m_xCurrencyLB->set_active(0);
1055
1056 m_xLocaleSettingLB->connect_changed( LINK( this, OfaLanguagesTabPage, LocaleSettingHdl ) );
1057 m_xDatePatternsED->connect_changed( LINK( this, OfaLanguagesTabPage, DatePatternsHdl ) );
1058
1059 Link<weld::Toggleable&,void> aLink( LINK( this, OfaLanguagesTabPage, SupportHdl ) );
1060 m_xAsianSupportCB->connect_toggled( aLink );
1061 m_xCTLSupportCB->connect_toggled( aLink );
1062
1063 m_bOldAsian = SvtCJKOptions::IsAnyEnabled();
1064 m_xAsianSupportCB->set_active(m_bOldAsian);
1065 m_xAsianSupportCB->save_state();
1066 bool bReadonly = SvtCJKOptions::IsAnyReadOnly();
1067 m_xAsianSupportCB->set_sensitive(!bReadonly);
1068 m_xAsianSupportImg->set_visible(bReadonly);
1069 SupportHdl(*m_xAsianSupportCB);
1070
1071 m_bOldCtl = SvtCTLOptions::IsCTLFontEnabled();
1072 m_xCTLSupportCB->set_active(m_bOldCtl);
1073 m_xCTLSupportCB->save_state();
1074 bReadonly = pLangConfig->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::E_CTLFONT);
1075 m_xCTLSupportCB->set_sensitive(!bReadonly);
1076 m_xCTLSupportImg->set_visible(bReadonly);
1077 SupportHdl(*m_xCTLSupportCB);
1078
1079 m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange() );
1080 }
1081
~OfaLanguagesTabPage()1082 OfaLanguagesTabPage::~OfaLanguagesTabPage()
1083 {
1084 }
1085
Create(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet * rAttrSet)1086 std::unique_ptr<SfxTabPage> OfaLanguagesTabPage::Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet )
1087 {
1088 return std::make_unique<OfaLanguagesTabPage>(pPage, pController, *rAttrSet);
1089 }
1090
lcl_Update(std::unique_ptr<SfxVoidItem> pInvalidItems[],std::unique_ptr<SfxBoolItem> pBoolItems[],sal_uInt16 nCount)1091 static void lcl_Update(std::unique_ptr<SfxVoidItem> pInvalidItems[], std::unique_ptr<SfxBoolItem> pBoolItems[], sal_uInt16 nCount)
1092 {
1093 SfxViewFrame* pCurrentFrm = SfxViewFrame::Current();
1094 SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst();
1095 while(pViewFrm)
1096 {
1097 SfxBindings& rBind = pViewFrm->GetBindings();
1098 for(sal_uInt16 i = 0; i < nCount; i++)
1099 {
1100 if(pCurrentFrm == pViewFrm)
1101 rBind.InvalidateAll(false);
1102 rBind.SetState( *pInvalidItems[i] );
1103 rBind.SetState( *pBoolItems[i] );
1104 }
1105 pViewFrm = SfxViewFrame::GetNext(*pViewFrm);
1106 }
1107 }
1108
GetAllStrings()1109 OUString OfaLanguagesTabPage::GetAllStrings()
1110 {
1111 OUString sAllStrings;
1112 OUString labels[]
1113 = { u"label1"_ustr, u"label4"_ustr, u"label7"_ustr, u"localesettingFT"_ustr, u"defaultcurrency"_ustr,
1114 u"label6"_ustr, u"dataaccpatterns"_ustr, u"label2"_ustr, u"western"_ustr, u"label3"_ustr };
1115
1116 for (const auto& label : labels)
1117 {
1118 if (const auto pString = m_xBuilder->weld_label(label))
1119 sAllStrings += pString->get_label() + " ";
1120 }
1121
1122 OUString checkButton[] = { u"decimalseparator"_ustr, u"asiansupport"_ustr, u"ctlsupport"_ustr, u"currentdoc"_ustr,
1123 u"ignorelanguagechange"_ustr };
1124
1125 for (const auto& check : checkButton)
1126 {
1127 if (const auto pString = m_xBuilder->weld_check_button(check))
1128 sAllStrings += pString->get_label() + " ";
1129 }
1130
1131 return sAllStrings.replaceAll("_", "");
1132 }
1133
FillItemSet(SfxItemSet * rSet)1134 bool OfaLanguagesTabPage::FillItemSet( SfxItemSet* rSet )
1135 {
1136 // lock configuration broadcasters so that we can coordinate the notifications
1137 pLangConfig->aSysLocaleOptions.BlockBroadcasts( true );
1138 pLangConfig->aCTLLanguageOptions.BlockBroadcasts( true );
1139 pLangConfig->aLinguConfig.BlockBroadcasts( true );
1140
1141 /*
1142 * Sequence checking only matters when CTL support is enabled.
1143 *
1144 * So we only need to check for sequence checking if
1145 * a) previously it was unchecked and is now checked or
1146 * b) it was already checked but the CTL language has changed
1147 */
1148 if (
1149 m_xCTLSupportCB->get_active() &&
1150 (m_xCTLSupportCB->get_saved_state() != TRISTATE_TRUE ||
1151 m_xComplexLanguageLB->get_active_id_changed_from_saved())
1152 )
1153 {
1154 //sequence checking has to be switched on depending on the selected CTL language
1155 LanguageType eCTLLang = m_xComplexLanguageLB->get_active_id();
1156 bool bOn = MsLangId::needsSequenceChecking( eCTLLang);
1157 pLangConfig->aCTLLanguageOptions.SetCTLSequenceCheckingRestricted(bOn);
1158 pLangConfig->aCTLLanguageOptions.SetCTLSequenceChecking(bOn);
1159 pLangConfig->aCTLLanguageOptions.SetCTLSequenceCheckingTypeAndReplace(bOn);
1160 }
1161 try
1162 {
1163 // handle settings for UI Language
1164 // a change of setting needs to bring up a warning message
1165 OUString aLangString;
1166 sal_Int32 d = m_xUserInterfaceLB->get_active_id().toInt32();
1167 if( d > 0 && seqInstalledLanguages.getLength() > d-1)
1168 aLangString = seqInstalledLanguages[d-1];
1169
1170 /*
1171 if( m_xUserInterfaceLB->GetSelectedEntryPos() > 0)
1172 aLangString = ConvertLanguageToIsoString(m_xUserInterfaceLB->get_active_id());
1173 */
1174 Reference< XMultiServiceFactory > theConfigProvider(
1175 css::configuration::theDefaultProvider::get(
1176 comphelper::getProcessComponentContext()));
1177 Sequence< Any > theArgs{ Any(NamedValue(u"nodepath"_ustr, Any(sUserLocalePath))) };
1178 Reference< XPropertySet >xProp(
1179 theConfigProvider->createInstanceWithArguments(sAccessUpdSrvc, theArgs ), UNO_QUERY_THROW );
1180 if ( m_sUserLocaleValue != aLangString)
1181 {
1182 // OSL_FAIL("UserInterface language was changed, restart.");
1183 // write new value
1184 xProp->setPropertyValue(sUserLocaleKey, Any(aLangString));
1185 Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges();
1186 // display info
1187 SolarMutexGuard aGuard;
1188 if (svtools::executeRestartDialog(
1189 comphelper::getProcessComponentContext(), GetFrameWeld(),
1190 svtools::RESTART_REASON_LANGUAGE_CHANGE))
1191 GetDialogController()->response(RET_OK);
1192
1193 // tell quickstarter to stop being a veto listener
1194
1195 const Reference< XComponentContext >& xContext(
1196 comphelper::getProcessComponentContext());
1197 css::office::Quickstart::createAndSetVeto(xContext, false, false, false/*DisableVeto*/);
1198 }
1199 }
1200 catch (const Exception&)
1201 {
1202 // we'll just leave the box in its default setting and won't
1203 // even give it event handler...
1204 TOOLS_WARN_EXCEPTION("cui.options", "ignoring");
1205 }
1206
1207 LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag());
1208 LanguageType eOldLocale = (aLanguageTag.isSystemLocale() ? LANGUAGE_SYSTEM :
1209 aLanguageTag.makeFallback().getLanguageType());
1210 LanguageType eNewLocale = m_xLocaleSettingLB->get_active_id();
1211
1212 // If the "Default ..." entry was selected that means SYSTEM, the actual
1213 // eNewLocale value is temporary for the dialog only, do not resolve to
1214 // what system currently is.
1215 if (eNewLocale == LANGUAGE_USER_SYSTEM_CONFIG)
1216 eNewLocale = LANGUAGE_SYSTEM;
1217
1218 if ( eOldLocale != eNewLocale )
1219 {
1220 // an empty string denotes SYSTEM locale
1221 OUString sNewLang;
1222 if ( eNewLocale != LANGUAGE_SYSTEM )
1223 sNewLang = LanguageTag::convertToBcp47( eNewLocale);
1224
1225 // locale nowadays get to AppSettings via notification
1226 // this will happen after releasing the lock on the ConfigurationBroadcaster at
1227 // the end of this method
1228 pLangConfig->aSysLocaleOptions.SetLocaleConfigString( sNewLang );
1229 rSet->Put( SfxBoolItem( SID_OPT_LOCALE_CHANGED, true ) );
1230
1231 SvtScriptType nNewType = SvtLanguageOptions::GetScriptTypeOfLanguage( eNewLocale );
1232 bool bNewCJK = bool( nNewType & SvtScriptType::ASIAN );
1233 auto batch = comphelper::ConfigurationChanges::create();
1234 SvtCompatibilityDefault aCompatOpts(batch);
1235 aCompatOpts.set(u"ExpandWordSpace"_ustr, !bNewCJK);
1236 batch->commit();
1237 }
1238
1239 if(m_xDecimalSeparatorCB->get_state_changed_from_saved())
1240 pLangConfig->aSysLocaleOptions.SetDecimalSeparatorAsLocale(m_xDecimalSeparatorCB->get_active());
1241
1242 if(m_xIgnoreLanguageChangeCB->get_state_changed_from_saved())
1243 pLangConfig->aSysLocaleOptions.SetIgnoreLanguageChange(m_xIgnoreLanguageChangeCB->get_active());
1244
1245 // Configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default.
1246 OUString sOldCurr = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString();
1247 OUString sId = m_xCurrencyLB->get_active_id();
1248 const NfCurrencyEntry* pCurr = sId == "default" ? nullptr : weld::fromId<const NfCurrencyEntry*>(sId);
1249 OUString sNewCurr;
1250 if ( pCurr )
1251 sNewCurr = SvtSysLocaleOptions::CreateCurrencyConfigString(
1252 pCurr->GetBankSymbol(), pCurr->GetLanguage() );
1253 if ( sOldCurr != sNewCurr )
1254 pLangConfig->aSysLocaleOptions.SetCurrencyConfigString( sNewCurr );
1255
1256 // Configured date acceptance patterns, for example Y-M-D;M-D or empty for
1257 // locale default.
1258 if (m_bDatePatternsValid && m_xDatePatternsED->get_value_changed_from_saved())
1259 pLangConfig->aSysLocaleOptions.SetDatePatternsConfigString( m_xDatePatternsED->get_text());
1260
1261 SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current();
1262 Reference< css::linguistic2::XLinguProperties > xLinguProp = LinguMgr::GetLinguPropertySet();
1263 bool bCurrentDocCBChecked = m_xCurrentDocCB->get_active();
1264 if (m_xCurrentDocCB->get_sensitive())
1265 bLanguageCurrentDoc_Impl = bCurrentDocCBChecked;
1266 bool bCurrentDocCBChanged = m_xCurrentDocCB->get_state_changed_from_saved();
1267
1268 bool bValChanged = m_xWesternLanguageLB->get_active_id_changed_from_saved();
1269 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1270 {
1271 LanguageType eSelectLang = m_xWesternLanguageLB->get_active_id();
1272 if(!bCurrentDocCBChecked)
1273 {
1274 Any aValue;
1275 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1276 aValue <<= aLocale;
1277 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale", aValue );
1278 if (xLinguProp.is())
1279 xLinguProp->setDefaultLocale( aLocale );
1280 }
1281 if(pCurrentDocShell)
1282 {
1283 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::LATIN),
1284 SID_ATTR_LANGUAGE));
1285 }
1286 }
1287 bValChanged = m_xAsianLanguageLB->get_active_id_changed_from_saved();
1288 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1289 {
1290 LanguageType eSelectLang = m_xAsianLanguageLB->get_active_id();
1291 if(!bCurrentDocCBChecked)
1292 {
1293 Any aValue;
1294 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1295 aValue <<= aLocale;
1296 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale_CJK", aValue );
1297 if (xLinguProp.is())
1298 xLinguProp->setDefaultLocale_CJK( aLocale );
1299 }
1300 if(pCurrentDocShell)
1301 {
1302 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::ASIAN),
1303 SID_ATTR_CHAR_CJK_LANGUAGE));
1304 }
1305 }
1306 bValChanged = m_xComplexLanguageLB->get_active_id_changed_from_saved();
1307 if( (bCurrentDocCBChanged && !bCurrentDocCBChecked) || bValChanged)
1308 {
1309 LanguageType eSelectLang = m_xComplexLanguageLB->get_active_id();
1310 if(!bCurrentDocCBChecked)
1311 {
1312 Any aValue;
1313 Locale aLocale = LanguageTag::convertToLocale( eSelectLang, false);
1314 aValue <<= aLocale;
1315 pLangConfig->aLinguConfig.SetProperty( u"DefaultLocale_CTL", aValue );
1316 if (xLinguProp.is())
1317 xLinguProp->setDefaultLocale_CTL( aLocale );
1318 }
1319 if(pCurrentDocShell)
1320 {
1321 rSet->Put(SvxLanguageItem(MsLangId::resolveSystemLanguageByScriptType(eSelectLang, css::i18n::ScriptType::COMPLEX),
1322 SID_ATTR_CHAR_CTL_LANGUAGE));
1323 }
1324
1325 // tdf#163228: Mongolian script supports vertical text
1326 pLangConfig->aCTLLanguageOptions.SetCTLVerticalText(
1327 MsLangId::getPrimaryLanguage(eSelectLang)
1328 == MsLangId::getPrimaryLanguage(LANGUAGE_MONGOLIAN_MONGOLIAN_MONGOLIA));
1329 }
1330
1331 if(m_xAsianSupportCB->get_state_changed_from_saved() )
1332 {
1333 bool bChecked = m_xAsianSupportCB->get_active();
1334 SvtCJKOptions::SetAll(bChecked);
1335
1336 //iterate over all bindings to invalidate vertical text direction
1337 const sal_uInt16 STATE_COUNT = 2;
1338
1339 std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT];
1340 pBoolItems[0].reset(new SfxBoolItem(SID_VERTICALTEXT_STATE, false));
1341 pBoolItems[1].reset(new SfxBoolItem(SID_TEXT_FITTOSIZE_VERTICAL, false));
1342
1343 std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT];
1344 pInvalidItems[0].reset(new SfxVoidItem(SID_VERTICALTEXT_STATE));
1345 pInvalidItems[1].reset(new SfxVoidItem(SID_TEXT_FITTOSIZE_VERTICAL));
1346
1347 lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT);
1348 }
1349
1350 if ( m_xCTLSupportCB->get_state_changed_from_saved() )
1351 {
1352 SvtSearchOptions aOpt;
1353 aOpt.SetIgnoreDiacritics_CTL(true);
1354 aOpt.SetIgnoreKashida_CTL(true);
1355 aOpt.Commit();
1356 pLangConfig->aCTLLanguageOptions.SetCTLFontEnabled( m_xCTLSupportCB->get_active() );
1357
1358 const sal_uInt16 STATE_COUNT = 1;
1359 std::unique_ptr<SfxBoolItem> pBoolItems[STATE_COUNT];
1360 pBoolItems[0].reset(new SfxBoolItem(SID_CTLFONT_STATE, false));
1361 std::unique_ptr<SfxVoidItem> pInvalidItems[STATE_COUNT];
1362 pInvalidItems[0].reset(new SfxVoidItem(SID_CTLFONT_STATE));
1363 lcl_Update(pInvalidItems, pBoolItems, STATE_COUNT);
1364 }
1365
1366 if ( pLangConfig->aSysLocaleOptions.IsModified() )
1367 pLangConfig->aSysLocaleOptions.Commit();
1368
1369 // first release the lock on the ConfigurationBroadcaster for Locale changes
1370 // it seems that our code relies on the fact that before other changes like e.g. currency
1371 // are broadcasted locale changes have been done
1372 pLangConfig->aSysLocaleOptions.BlockBroadcasts( false );
1373 pLangConfig->aCTLLanguageOptions.BlockBroadcasts( false );
1374 pLangConfig->aLinguConfig.BlockBroadcasts( false );
1375
1376 return false;
1377 }
1378
Reset(const SfxItemSet * rSet)1379 void OfaLanguagesTabPage::Reset( const SfxItemSet* rSet )
1380 {
1381 LanguageTag aLanguageTag( pLangConfig->aSysLocaleOptions.GetLanguageTag());
1382 if ( aLanguageTag.isSystemLocale() )
1383 m_xLocaleSettingLB->set_active_id( LANGUAGE_USER_SYSTEM_CONFIG );
1384 else
1385 m_xLocaleSettingLB->set_active_id( aLanguageTag.makeFallback().getLanguageType());
1386 bool bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Locale);
1387 m_xLocaleSettingLB->set_sensitive(!bReadonly);
1388 m_xLocaleSettingFT->set_sensitive(!bReadonly);
1389 m_xLocaleSettingImg->set_visible(bReadonly);
1390
1391
1392 m_xDecimalSeparatorCB->set_active( pLangConfig->aSysLocaleOptions.IsDecimalSeparatorAsLocale());
1393 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DecimalSeparator);
1394 m_xDecimalSeparatorCB->set_sensitive(!bReadonly);
1395 m_xDecimalSeparatorFT->set_sensitive(!bReadonly);
1396 m_xDecimalSeparatorImg->set_visible(bReadonly);
1397 m_xDecimalSeparatorCB->save_state();
1398
1399 m_xIgnoreLanguageChangeCB->set_active( pLangConfig->aSysLocaleOptions.IsIgnoreLanguageChange());
1400 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::IgnoreLanguageChange);
1401 m_xIgnoreLanguageChangeCB->set_sensitive(!bReadonly);
1402 m_xIgnoreLanguageChangeImg->set_visible(bReadonly);
1403 m_xIgnoreLanguageChangeCB->save_state();
1404
1405 // let LocaleSettingHdl enable/disable checkboxes for CJK/CTL support
1406 // #i15812# must be done *before* the configured currency is set
1407 // and update the decimal separator used for the given locale
1408 LocaleSettingHdl(*m_xLocaleSettingLB->get_widget());
1409
1410 // configured currency, for example, USD-en-US or EUR-de-DE, or empty for locale default
1411 const NfCurrencyEntry* pCurr = nullptr;
1412 OUString sCurrency = pLangConfig->aSysLocaleOptions.GetCurrencyConfigString();
1413 if ( !sCurrency.isEmpty() )
1414 {
1415 LanguageType eLang;
1416 OUString aAbbrev;
1417 SvtSysLocaleOptions::GetCurrencyAbbrevAndLanguage( aAbbrev, eLang, sCurrency );
1418 pCurr = SvNumberFormatter::GetCurrencyEntry( aAbbrev, eLang );
1419 }
1420 // if pCurr==nullptr the SYSTEM entry is selected
1421 OUString sId = !pCurr ? u"default"_ustr : weld::toId(pCurr);
1422 m_xCurrencyLB->set_active_id(sId);
1423 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::Currency);
1424 m_xCurrencyLB->set_sensitive(!bReadonly);
1425 m_xCurrencyFT->set_sensitive(!bReadonly);
1426 m_xCurrencyImg->set_visible(bReadonly);
1427
1428 // date acceptance patterns
1429 OUString aDatePatternsString = pLangConfig->aSysLocaleOptions.GetDatePatternsConfigString();
1430 if (aDatePatternsString.isEmpty())
1431 {
1432 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1433 aDatePatternsString = lcl_getDatePatternsConfigString( rLocaleWrapper);
1434 // Let's assume patterns are valid at this point.
1435 m_bDatePatternsValid = true;
1436 }
1437 else
1438 {
1439 bool bModified = false;
1440 m_bDatePatternsValid = validateDatePatterns( bModified, aDatePatternsString);
1441 }
1442 m_xDatePatternsED->set_text(aDatePatternsString);
1443 m_xDatePatternsED->set_message_type( m_bDatePatternsValid ?
1444 weld::EntryMessageType::Normal : weld::EntryMessageType::Error);
1445 bReadonly = pLangConfig->aSysLocaleOptions.IsReadOnly(SvtSysLocaleOptions::EOption::DatePatterns);
1446 m_xDatePatternsED->set_sensitive(!bReadonly);
1447 m_xDatePatternsFT->set_sensitive(!bReadonly);
1448 m_xDatePatternsImg->set_visible(bReadonly);
1449 m_xDatePatternsED->save_value();
1450
1451 //western/CJK/CLK language
1452 LanguageType eCurLang = LANGUAGE_NONE;
1453 LanguageType eCurLangCJK = LANGUAGE_NONE;
1454 LanguageType eCurLangCTL = LANGUAGE_NONE;
1455 SfxObjectShell* pCurrentDocShell = SfxObjectShell::Current();
1456 //collect the configuration values first
1457 m_xCurrentDocCB->set_sensitive(false);
1458
1459 Any aWestLang;
1460 Any aCJKLang;
1461 Any aCTLLang;
1462 try
1463 {
1464 aWestLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale");
1465 Locale aLocale;
1466 aWestLang >>= aLocale;
1467
1468 eCurLang = LanguageTag::convertToLanguageType( aLocale, false);
1469
1470 aCJKLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale_CJK");
1471 aLocale = Locale();
1472 aCJKLang >>= aLocale;
1473 eCurLangCJK = LanguageTag::convertToLanguageType( aLocale, false);
1474
1475 aCTLLang = pLangConfig->aLinguConfig.GetProperty(u"DefaultLocale_CTL");
1476 aLocale = Locale();
1477 aCTLLang >>= aLocale;
1478 eCurLangCTL = LanguageTag::convertToLanguageType( aLocale, false);
1479 }
1480 catch (const Exception&)
1481 {
1482 }
1483 //overwrite them by the values provided by the DocShell
1484 if(pCurrentDocShell)
1485 {
1486 m_xCurrentDocCB->set_sensitive(true);
1487 m_xCurrentDocCB->set_active(bLanguageCurrentDoc_Impl);
1488 if( const SvxLanguageItem* pLangItem = rSet->GetItemIfSet(SID_ATTR_LANGUAGE, false))
1489 {
1490 LanguageType eTempCurLang = pLangItem->GetValue();
1491 if (MsLangId::resolveSystemLanguageByScriptType(eCurLang, css::i18n::ScriptType::LATIN) != eTempCurLang)
1492 eCurLang = eTempCurLang;
1493 }
1494
1495 if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CJK_LANGUAGE, false))
1496 {
1497 LanguageType eTempCurLang = pLang->GetValue();
1498 if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCJK, css::i18n::ScriptType::ASIAN) != eTempCurLang)
1499 eCurLangCJK = eTempCurLang;
1500 }
1501
1502 if( const SvxLanguageItem* pLang = rSet->GetItemIfSet(SID_ATTR_CHAR_CTL_LANGUAGE, false))
1503 {
1504 LanguageType eTempCurLang = pLang->GetValue();
1505 if (MsLangId::resolveSystemLanguageByScriptType(eCurLangCTL, css::i18n::ScriptType::COMPLEX) != eTempCurLang)
1506 eCurLangCTL = eTempCurLang;
1507 }
1508 }
1509 if(LANGUAGE_NONE == eCurLang || LANGUAGE_DONTKNOW == eCurLang)
1510 m_xWesternLanguageLB->set_active_id(LANGUAGE_NONE);
1511 else
1512 m_xWesternLanguageLB->set_active_id(eCurLang);
1513
1514 if(LANGUAGE_NONE == eCurLangCJK || LANGUAGE_DONTKNOW == eCurLangCJK)
1515 m_xAsianLanguageLB->set_active_id(LANGUAGE_NONE);
1516 else
1517 m_xAsianLanguageLB->set_active_id(eCurLangCJK);
1518
1519 if(LANGUAGE_NONE == eCurLangCTL || LANGUAGE_DONTKNOW == eCurLangCTL)
1520 m_xComplexLanguageLB->set_active_id(LANGUAGE_NONE);
1521 else
1522 m_xComplexLanguageLB->set_active_id(eCurLangCTL);
1523
1524 m_xWesternLanguageLB->save_active_id();
1525 m_xAsianLanguageLB->save_active_id();
1526 m_xComplexLanguageLB->save_active_id();
1527 m_xIgnoreLanguageChangeCB->save_state();
1528 m_xCurrentDocCB->save_state();
1529
1530 bool bEnable = !pLangConfig->aLinguConfig.IsReadOnly( u"DefaultLocale" );
1531 m_xWesternLanguageFT->set_sensitive( bEnable );
1532 m_xWesternLanguageLB->set_sensitive( bEnable );
1533 m_xWesternLanguageImg->set_visible( !bEnable );
1534
1535 // check the box "For the current document only"
1536 // set the focus to the Western Language box
1537 const SfxBoolItem* pLang = rSet->GetItemIfSet(SID_SET_DOCUMENT_LANGUAGE, false );
1538 if ( pLang && pLang->GetValue() )
1539 {
1540 m_xWesternLanguageLB->grab_focus();
1541 m_xCurrentDocCB->set_sensitive(true);
1542 m_xCurrentDocCB->set_active(true);
1543 }
1544 }
1545
IMPL_LINK(OfaLanguagesTabPage,SupportHdl,weld::Toggleable &,rBox,void)1546 IMPL_LINK(OfaLanguagesTabPage, SupportHdl, weld::Toggleable&, rBox, void)
1547 {
1548 bool bCheck = rBox.get_active();
1549 if ( m_xAsianSupportCB.get() == &rBox )
1550 {
1551 bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly(u"DefaultLocale_CJK");
1552 bCheck = ( bCheck && !bReadonly );
1553 m_xAsianLanguageLB->set_sensitive( bCheck );
1554 if (rBox.get_sensitive())
1555 m_bOldAsian = bCheck;
1556 }
1557 else if ( m_xCTLSupportCB.get() == &rBox )
1558 {
1559 bool bReadonly = pLangConfig->aLinguConfig.IsReadOnly(u"DefaultLocale_CTL");
1560 bCheck = ( bCheck && !bReadonly );
1561 m_xComplexLanguageLB->set_sensitive( bCheck );
1562 if (rBox.get_sensitive())
1563 m_bOldCtl = bCheck;
1564 }
1565 else
1566 SAL_WARN( "cui.options", "OfaLanguagesTabPage::SupportHdl(): wrong rBox" );
1567 }
1568
1569 namespace
1570 {
lcl_checkLanguageCheckBox(weld::CheckButton & _rCB,bool _bNewValue,bool _bOldValue)1571 void lcl_checkLanguageCheckBox(weld::CheckButton& _rCB, bool _bNewValue, bool _bOldValue)
1572 {
1573 if ( _bNewValue )
1574 _rCB.set_active(true);
1575 else
1576 _rCB.set_active( _bOldValue );
1577 // #i15082# do not call save_state() in running dialog...
1578 // _rCB.save_state();
1579 _rCB.set_sensitive( !_bNewValue );
1580 }
1581 }
1582
IMPL_LINK_NOARG(OfaLanguagesTabPage,LocaleSettingHdl,weld::ComboBox &,void)1583 IMPL_LINK_NOARG(OfaLanguagesTabPage, LocaleSettingHdl, weld::ComboBox&, void)
1584 {
1585 LanguageType eLang = m_xLocaleSettingLB->get_active_id();
1586 SvtScriptType nType = SvtLanguageOptions::GetScriptTypeOfLanguage(eLang);
1587 // first check if CTL must be enabled
1588 // #103299# - if CTL font setting is not readonly
1589 if(!pLangConfig->aCTLLanguageOptions.IsReadOnly(SvtCTLOptions::E_CTLFONT))
1590 {
1591 bool bIsCTLFixed = bool(nType & SvtScriptType::COMPLEX);
1592 lcl_checkLanguageCheckBox(*m_xCTLSupportCB, bIsCTLFixed, m_bOldCtl);
1593 SupportHdl(*m_xCTLSupportCB);
1594 }
1595 // second check if CJK must be enabled
1596 // #103299# - if CJK support is not readonly
1597 if(!SvtCJKOptions::IsAnyReadOnly())
1598 {
1599 bool bIsCJKFixed = bool(nType & SvtScriptType::ASIAN);
1600 lcl_checkLanguageCheckBox(*m_xAsianSupportCB, bIsCJKFixed, m_bOldAsian);
1601 SupportHdl(*m_xAsianSupportCB);
1602 }
1603
1604 const NfCurrencyEntry& rCurr = SvNumberFormatter::GetCurrencyEntry(
1605 (eLang == LANGUAGE_USER_SYSTEM_CONFIG) ? MsLangId::getConfiguredSystemLanguage() : eLang);
1606 static constexpr OUString aDefaultID = u"default"_ustr;
1607 // Update the "Default ..." currency.
1608 m_xCurrencyLB->remove_id(aDefaultID);
1609 OUString aDefaultCurr = m_sSystemDefaultString + " - " + rCurr.GetBankSymbol();
1610 m_xCurrencyLB->insert(0, aDefaultCurr, &aDefaultID, nullptr, nullptr);
1611 assert(m_xCurrencyLB->find_id(aDefaultID) != -1);
1612 m_xCurrencyLB->set_active_text(aDefaultCurr);
1613
1614 // obtain corresponding locale data
1615 LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang) ));
1616
1617 // update the decimal separator key of the related CheckBox
1618 OUString sTempLabel(m_sDecimalSeparatorLabel);
1619 sTempLabel = sTempLabel.replaceFirst("%1", aLocaleWrapper.getNumDecimalSep() );
1620 m_xDecimalSeparatorCB->set_label(sTempLabel);
1621
1622 // update the date acceptance patterns
1623 OUString aDatePatternsString = lcl_getDatePatternsConfigString( aLocaleWrapper);
1624 m_bDatePatternsValid = true;
1625 m_xDatePatternsED->set_text( aDatePatternsString);
1626 m_xDatePatternsED->set_message_type(weld::EntryMessageType::Normal);
1627 }
1628
IMPL_LINK(OfaLanguagesTabPage,DatePatternsHdl,weld::Entry &,rEd,void)1629 IMPL_LINK( OfaLanguagesTabPage, DatePatternsHdl, weld::Entry&, rEd, void )
1630 {
1631 OUString aPatterns(rEd.get_text());
1632 bool bModified = false;
1633 const bool bValid = validateDatePatterns( bModified, aPatterns);
1634 if (bModified)
1635 {
1636 // gtk3 keeps the cursor position on equal length set_text() but at
1637 // least the 'gen' backend does not and resets to 0.
1638 const int nCursorPos = rEd.get_position();
1639 rEd.set_text(aPatterns);
1640 rEd.set_position(nCursorPos);
1641 }
1642 if (bValid)
1643 rEd.set_message_type(weld::EntryMessageType::Normal);
1644 else
1645 rEd.set_message_type(weld::EntryMessageType::Error);
1646 m_bDatePatternsValid = bValid;
1647 }
1648
validateDatePatterns(bool & rbModified,OUString & rPatterns)1649 bool OfaLanguagesTabPage::validateDatePatterns( bool& rbModified, OUString& rPatterns )
1650 {
1651 bool bValid = true;
1652 if (!rPatterns.isEmpty())
1653 {
1654 OUStringBuffer aBuf( rPatterns);
1655 sal_Int32 nChar = 0;
1656 for (sal_Int32 nIndex=0; nIndex >= 0 && bValid; ++nChar)
1657 {
1658 const OUString aPat( rPatterns.getToken( 0, ';', nIndex));
1659 if (aPat.isEmpty() && nIndex < 0)
1660 {
1661 // Indicating failure when about to append a pattern is too
1662 // confusing. Empty patterns are ignored anyway when sequencing
1663 // to SvtSysLocale.
1664 continue; // for
1665 }
1666 else if (aPat.getLength() < 2)
1667 bValid = false;
1668 else
1669 {
1670 bool bY, bM, bD;
1671 bY = bM = bD = false;
1672 bool bSep = true;
1673 if (aPat.getLength() == 3)
1674 {
1675 // Disallow a pattern that would match a numeric input with
1676 // decimal separator, like M.D
1677 const LanguageType eLang = m_xLocaleSettingLB->get_active_id();
1678 const LocaleDataWrapper aLocaleWrapper(( LanguageTag(eLang)));
1679 if ( aPat[1] == aLocaleWrapper.getNumDecimalSep().toChar()
1680 || aPat[1] == aLocaleWrapper.getNumDecimalSepAlt().toChar())
1681 {
1682 bValid = false;
1683 }
1684 }
1685 for (sal_Int32 i = 0; i < aPat.getLength() && bValid; /*nop*/)
1686 {
1687 const sal_Int32 j = i;
1688 const sal_uInt32 c = aPat.iterateCodePoints( &i);
1689 // Only one Y,M,D per pattern, separated by any character(s).
1690 switch (c)
1691 {
1692 case 'y':
1693 case 'Y':
1694 if (bY || !bSep)
1695 bValid = false;
1696 else if (c == 'y')
1697 {
1698 aBuf[nChar] = 'Y';
1699 rbModified = true;
1700 }
1701 bY = true;
1702 bSep = false;
1703 break;
1704 case 'm':
1705 case 'M':
1706 if (bM || !bSep)
1707 bValid = false;
1708 else if (c == 'm')
1709 {
1710 aBuf[nChar] = 'M';
1711 rbModified = true;
1712 }
1713 bM = true;
1714 bSep = false;
1715 break;
1716 case 'd':
1717 case 'D':
1718 if (bD || !bSep)
1719 bValid = false;
1720 else if (c == 'd')
1721 {
1722 aBuf[nChar] = 'D';
1723 rbModified = true;
1724 }
1725 bD = true;
1726 bSep = false;
1727 break;
1728 default:
1729 // A pattern must not start with a separator (but
1730 // may end with).
1731 if (!(bY || bM || bD))
1732 bValid = false;
1733 bSep = true;
1734 }
1735 nChar += i-j;
1736 }
1737 // At least one of Y,M,D
1738 bValid &= (bY || bM || bD);
1739 }
1740 }
1741 if (rbModified)
1742 rPatterns = aBuf.makeStringAndClear();
1743 }
1744 return bValid;
1745 }
1746
1747 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1748