1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include "optaboutconfig.hxx"
11 #include <o3tl/safeint.hxx>
12 #include <o3tl/string_view.hxx>
14 #include <com/sun/star/beans/NamedValue.hpp>
15 #include <com/sun/star/beans/PropertyAttribute.hpp>
16 #include <com/sun/star/beans/UnknownPropertyException.hpp>
17 #include <com/sun/star/beans/XPropertySetInfo.hpp>
18 #include <com/sun/star/configuration/ReadWriteAccess.hpp>
19 #include <com/sun/star/configuration/XDocumentation.hpp>
20 #include <com/sun/star/configuration/theDefaultProvider.hpp>
21 #include <com/sun/star/container/XHierarchicalName.hpp>
22 #include <com/sun/star/container/XNameAccess.hpp>
23 #include <com/sun/star/container/XNameReplace.hpp>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <com/sun/star/uno/Reference.hxx>
26 #include <com/sun/star/uno/Type.hxx>
27 #include <com/sun/star/uno/TypeClass.hpp>
28 #include <com/sun/star/util/InvalidStateException.hpp>
29 #include <com/sun/star/util/SearchAlgorithms2.hpp>
30 #include <com/sun/star/util/SearchFlags.hpp>
31 #include <com/sun/star/util/XChangesBatch.hpp>
32 #include <comphelper/diagnose_ex.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/sequence.hxx>
35 #include <cppu/unotype.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <sal/log.hxx>
38 #include <unotools/textsearch.hxx>
40 #include <vcl/event.hxx>
42 #include <dialmgr.hxx>
43 #include <strings.hrc>
49 using namespace ::com::sun::star
;
50 using namespace com::sun::star::uno
;
51 using namespace com::sun::star::container
;
59 Prop_Impl(OUString sName
, OUString sProperty
, Any aValue
)
60 : Name(std::move(sName
))
61 , Property(std::move(sProperty
))
62 , Value(std::move(aValue
))
72 OUString sPropertyPath
;
76 Reference
<XNameAccess
> aXNameAccess
;
78 explicit UserData(OUString aPropertyPath
, Any aPropValue
, OUString aTooltip
, bool isReadOnly
,
80 : bIsPropertyPath(true)
81 , bIsReadOnly(isReadOnly
)
82 , bWasModified(wasModified
)
83 , sPropertyPath(std::move(aPropertyPath
))
84 , aPropertyValue(aPropValue
)
85 , sTooltip(std::move(aTooltip
))
90 explicit UserData(Reference
<XNameAccess
> const& rXNameAccess
, int rIndex
)
91 : bIsPropertyPath(false)
95 , aXNameAccess(rXNameAccess
)
100 CuiAboutConfigTabPage::CuiAboutConfigTabPage(weld::Window
* pParent
)
101 : GenericDialogController(pParent
, u
"cui/ui/aboutconfigdialog.ui"_ustr
, u
"AboutConfig"_ustr
)
102 , m_xResetBtn(m_xBuilder
->weld_button(u
"reset"_ustr
))
103 , m_xEditBtn(m_xBuilder
->weld_button(u
"edit"_ustr
))
104 , m_xSearchBtn(m_xBuilder
->weld_button(u
"searchButton"_ustr
))
105 , m_xModifiedCheckBtn(m_xBuilder
->weld_check_button(u
"modifiedButton"_ustr
))
106 , m_xSearchEdit(m_xBuilder
->weld_entry(u
"searchEntry"_ustr
))
107 , m_xPrefBox(m_xBuilder
->weld_tree_view(u
"preferences"_ustr
))
108 , m_xScratchIter(m_xPrefBox
->make_iterator())
111 m_xPrefBox
->set_size_request(m_xPrefBox
->get_approximate_digit_width() * 100,
112 m_xPrefBox
->get_height_rows(23));
113 m_xPrefBox
->connect_column_clicked(LINK(this, CuiAboutConfigTabPage
, HeaderBarClick
));
115 m_xEditBtn
->connect_clicked(LINK(this, CuiAboutConfigTabPage
, StandardHdl_Impl
));
116 m_xResetBtn
->connect_clicked(LINK(this, CuiAboutConfigTabPage
, ResetBtnHdl_Impl
));
117 m_xPrefBox
->connect_row_activated(LINK(this, CuiAboutConfigTabPage
, DoubleClickHdl_Impl
));
118 m_xPrefBox
->connect_expanding(LINK(this, CuiAboutConfigTabPage
, ExpandingHdl_Impl
));
119 m_xSearchBtn
->connect_clicked(LINK(this, CuiAboutConfigTabPage
, SearchHdl_Impl
));
120 m_xModifiedCheckBtn
->connect_toggled(LINK(this, CuiAboutConfigTabPage
, ModifiedHdl_Impl
));
122 m_options
.AlgorithmType2
= util::SearchAlgorithms2::ABSOLUTE
;
123 m_options
.transliterateFlags
|= TransliterationFlags::IGNORE_CASE
;
125 |= (util::SearchFlags::REG_NOT_BEGINOFLINE
| util::SearchFlags::REG_NOT_ENDOFLINE
);
127 float fWidth
= m_xPrefBox
->get_approximate_digit_width();
128 std::vector
<int> aWidths
{ o3tl::narrowing
<int>(fWidth
* 65), o3tl::narrowing
<int>(fWidth
* 20),
129 o3tl::narrowing
<int>(fWidth
* 8) };
130 m_xPrefBox
->set_column_fixed_widths(aWidths
);
132 m_xPrefBox
->connect_query_tooltip(LINK(this, CuiAboutConfigTabPage
, QueryTooltip
));
135 IMPL_LINK(CuiAboutConfigTabPage
, QueryTooltip
, const weld::TreeIter
&, rIter
, OUString
)
137 UserData
* pUserData
= weld::fromId
<UserData
*>(m_xPrefBox
->get_id(rIter
));
139 if (pUserData
&& pUserData
->bIsReadOnly
)
141 ret
.append(CuiResId(RID_CUISTR_OPT_READONLY
));
143 if (pUserData
&& !pUserData
->sTooltip
.isEmpty())
145 if (pUserData
->bIsReadOnly
)
147 ret
.append(pUserData
->sTooltip
);
150 return ret
.makeStringAndClear();
153 IMPL_LINK(CuiAboutConfigTabPage
, HeaderBarClick
, int, nColumn
, void)
157 m_xPrefBox
->make_sorted();
161 bool bSortAtoZ
= m_xPrefBox
->get_sort_order();
163 //set new arrow positions in headerbar
164 if (nColumn
== m_xPrefBox
->get_sort_column())
166 bSortAtoZ
= !bSortAtoZ
;
167 m_xPrefBox
->set_sort_order(bSortAtoZ
);
171 int nOldSortColumn
= m_xPrefBox
->get_sort_column();
172 if (nOldSortColumn
!= -1)
173 m_xPrefBox
->set_sort_indicator(TRISTATE_INDET
, nOldSortColumn
);
174 m_xPrefBox
->set_sort_column(nColumn
);
180 m_xPrefBox
->set_sort_indicator(bSortAtoZ
? TRISTATE_TRUE
: TRISTATE_FALSE
, nColumn
);
184 IMPL_STATIC_LINK_NOARG(CuiAboutConfigTabPage
, ValidNameHdl
, SvxNameDialog
&, bool)
190 CuiAboutConfigTabPage::~CuiAboutConfigTabPage() {}
192 void CuiAboutConfigTabPage::InsertEntry(const OUString
& rPropertyPath
, Any aPropertyValue
,
193 const OUString
& rProp
, const OUString
& rStatus
,
194 const OUString
& rType
, const OUString
& rValue
,
195 const OUString
& rTooltip
,
196 const weld::TreeIter
* pParentEntry
, bool bInsertToPrefBox
,
197 bool bIsReadOnly
, bool bWasModified
)
199 bool bOnlyModified
= m_xModifiedCheckBtn
->get_active();
200 if (bOnlyModified
&& !bWasModified
)
203 m_vectorUserData
.push_back(std::make_unique
<UserData
>(rPropertyPath
, aPropertyValue
, rTooltip
,
204 bIsReadOnly
, bWasModified
));
205 if (bInsertToPrefBox
)
207 OUString
sId(weld::toId(m_vectorUserData
.back().get()));
208 m_xPrefBox
->insert(pParentEntry
, -1, &rProp
, &sId
, nullptr, nullptr, false,
209 m_xScratchIter
.get());
210 m_xPrefBox
->set_text(*m_xScratchIter
, rStatus
, 1);
211 m_xPrefBox
->set_text(*m_xScratchIter
, rType
, 2);
212 m_xPrefBox
->set_text(*m_xScratchIter
, rValue
, 3);
213 m_xPrefBox
->set_text_emphasis(*m_xScratchIter
, bWasModified
, -1);
214 m_xPrefBox
->set_sensitive(*m_xScratchIter
, !bIsReadOnly
, -1);
218 m_prefBoxEntries
.push_back(
219 { rProp
, rStatus
, rType
, rValue
, m_vectorUserData
.back().get() });
223 void CuiAboutConfigTabPage::InputChanged()
225 weld::WaitObject
aWait(m_xDialog
.get());
229 m_xPrefBox
->freeze();
232 m_xPrefBox
->make_unsorted();
234 if (m_xSearchEdit
->get_text().isEmpty())
237 Reference
<XNameAccess
> xConfigAccess
= getConfigAccess(u
"/"_ustr
, false);
238 FillItems(xConfigAccess
);
242 m_options
.searchString
= m_xSearchEdit
->get_text();
243 utl::TextSearch
textSearch(m_options
);
244 for (auto const& it
: m_prefBoxEntries
)
246 sal_Int32 endPos
, startPos
= 0;
248 for (size_t i
= 0; i
< 5; ++i
)
253 scrTxt
= it
.pUserData
->sPropertyPath
;
263 endPos
= scrTxt
.getLength();
264 if (textSearch
.SearchForward(scrTxt
, &startPos
, &endPos
))
275 m_xPrefBox
->make_sorted();
277 m_xPrefBox
->all_foreach([this](weld::TreeIter
& rEntry
) {
278 m_xPrefBox
->expand_row(rEntry
);
284 void CuiAboutConfigTabPage::Reset()
286 weld::WaitObject
aWait(m_xDialog
.get());
289 m_vectorOfModified
.clear();
292 m_xPrefBox
->set_sort_indicator(TRISTATE_INDET
, m_xPrefBox
->get_sort_column());
293 m_xPrefBox
->make_unsorted();
296 m_prefBoxEntries
.clear();
297 m_modifiedPrefBoxEntries
.clear();
299 m_xPrefBox
->freeze();
300 Reference
<XNameAccess
> xConfigAccess
= getConfigAccess(u
"/"_ustr
, false);
301 //Load all XNameAccess to m_prefBoxEntries
302 FillItems(xConfigAccess
, nullptr, 0, true);
303 //Load xConfigAccess' children to m_prefBox
304 FillItems(xConfigAccess
);
308 void CuiAboutConfigTabPage::FillItemSet()
310 std::vector
<std::shared_ptr
<Prop_Impl
>>::iterator pIter
;
311 for (pIter
= m_vectorOfModified
.begin(); pIter
!= m_vectorOfModified
.end(); ++pIter
)
313 Reference
<XNameAccess
> xUpdateAccess
= getConfigAccess((*pIter
)->Name
, true);
314 Reference
<XNameReplace
> xNameReplace(xUpdateAccess
, UNO_QUERY_THROW
);
316 xNameReplace
->replaceByName((*pIter
)->Property
, (*pIter
)->Value
);
318 Reference
<util::XChangesBatch
> xChangesBatch(xUpdateAccess
, UNO_QUERY_THROW
);
319 xChangesBatch
->commitChanges();
325 OUString
lcl_StringListToString(const uno::Sequence
<OUString
>& seq
)
327 OUStringBuffer sBuffer
;
328 for (sal_Int32 i
= 0; i
!= seq
.getLength(); ++i
)
332 sBuffer
.append(seq
[i
]);
334 return sBuffer
.makeStringAndClear();
337 OUString
lcl_IntListToString(const uno::Sequence
<sal_Int16
>& seq
)
339 OUStringBuffer sBuffer
;
340 for (sal_Int32 i
= 0; i
!= seq
.getLength(); ++i
)
344 sBuffer
.append(OUString::number(seq
[i
]));
346 return sBuffer
.makeStringAndClear();
349 OUString
lcl_IntListToString(const uno::Sequence
<sal_Int32
>& seq
)
351 OUStringBuffer sBuffer
;
352 for (sal_Int32 i
= 0; i
!= seq
.getLength(); ++i
)
356 sBuffer
.append(OUString::number(seq
[i
]));
358 return sBuffer
.makeStringAndClear();
361 OUString
lcl_IntListToString(const uno::Sequence
<sal_Int64
>& seq
)
363 OUStringBuffer sBuffer
;
364 for (sal_Int32 i
= 0; i
!= seq
.getLength(); ++i
)
368 sBuffer
.append(OUString::number(seq
[i
]));
370 return sBuffer
.makeStringAndClear();
373 OUString
lcl_DoubleListToString(const uno::Sequence
<double>& seq
)
375 OUStringBuffer sBuffer
;
376 for (sal_Int32 i
= 0; i
!= seq
.getLength(); ++i
)
380 sBuffer
.append(OUString::number(seq
[i
]));
382 return sBuffer
.makeStringAndClear();
386 void CuiAboutConfigTabPage::FillItems(const Reference
<XNameAccess
>& xNameAccess
,
387 const weld::TreeIter
* pParentEntry
, int lineage
,
391 = Reference
<XHierarchicalName
>(xNameAccess
, uno::UNO_QUERY_THROW
)->getHierarchicalName();
392 const uno::Sequence
<OUString
> seqItems
= xNameAccess
->getElementNames();
393 for (const OUString
& item
: seqItems
)
395 Any aNode
= xNameAccess
->getByName(item
);
397 bool bNotLeaf
= false;
399 Reference
<XNameAccess
> xNextNameAccess
;
402 xNextNameAccess
.set(aNode
, uno::UNO_QUERY
);
403 bNotLeaf
= xNextNameAccess
.is();
405 catch (const RuntimeException
&)
407 TOOLS_WARN_EXCEPTION("cui.options", "CuiAboutConfigTabPage");
413 FillItems(xNextNameAccess
, nullptr, lineage
+ 1, true);
417 m_vectorUserData
.push_back(
418 std::make_unique
<UserData
>(xNextNameAccess
, lineage
+ 1));
419 OUString
sId(weld::toId(m_vectorUserData
.back().get()));
421 m_xPrefBox
->insert(pParentEntry
, -1, &item
, &sId
, nullptr, nullptr, true,
422 m_xScratchIter
.get());
423 // Necessary, without this the selection line will be truncated.
424 m_xPrefBox
->set_text(*m_xScratchIter
, u
""_ustr
, 1);
425 m_xPrefBox
->set_text(*m_xScratchIter
, u
""_ustr
, 2);
426 m_xPrefBox
->set_text(*m_xScratchIter
, u
""_ustr
, 3);
427 m_xPrefBox
->set_text_emphasis(*m_xScratchIter
, false, -1);
428 m_xPrefBox
->set_sensitive(*m_xScratchIter
, true);
434 OUString sPropertyName
= item
;
435 auto it
= std::find_if(m_modifiedPrefBoxEntries
.begin(), m_modifiedPrefBoxEntries
.end(),
436 [&sPath
, &sPropertyName
](const prefBoxEntry
& rEntry
) -> bool {
437 return rEntry
.pUserData
->sPropertyPath
== sPath
438 && rEntry
.sStatus
== sPropertyName
;
441 css::uno::Reference
<css::configuration::XReadWriteAccess
> m_xReadWriteAccess
;
442 m_xReadWriteAccess
= css::configuration::ReadWriteAccess::create(
443 ::comphelper::getProcessComponentContext(), u
"*"_ustr
);
444 beans::Property aProperty
;
445 bool bReadOnly
= false;
446 OUString
sFullPath(sPath
+ "/" + sPropertyName
);
449 aProperty
= m_xReadWriteAccess
->getPropertyByHierarchicalName(sFullPath
);
450 bReadOnly
= (aProperty
.Attributes
& beans::PropertyAttribute::READONLY
) != 0;
452 catch (css::beans::UnknownPropertyException
)
454 SAL_WARN("cui.options", "unknown property: " << sFullPath
);
459 bool bWasModified
= false;
460 css::uno::Type aType
= cppu::UnoType
<void>::get();
461 OUString sDynamicType
= aNode
.getValueTypeName();
464 Reference
<configuration::XDocumentation
> xDocumentation(xNameAccess
,
467 = xDocumentation
->getDescriptionByHierarchicalName(sPath
+ "/" + sPropertyName
);
468 aType
= xDocumentation
->getTypeByHierarchicalName(sFullPath
);
469 bWasModified
= xDocumentation
->getModifiedByHierarchicalName(sFullPath
);
471 catch (css::container::NoSuchElementException
)
474 catch (css::util::InvalidStateException
)
478 OUStringBuffer sValue
;
480 // Fall back to dynamic type when this is empty
481 if (aType
== cppu::UnoType
<void>::get() && sDynamicType
!= "void")
483 if (sDynamicType
== "boolean")
484 aType
= cppu::UnoType
<sal_Bool
>::get();
485 else if (sDynamicType
== "short")
486 aType
= cppu::UnoType
<sal_Int16
>::get();
487 else if (sDynamicType
== "long")
488 aType
= cppu::UnoType
<sal_Int32
>::get();
489 else if (sDynamicType
== "hyper")
490 aType
= cppu::UnoType
<sal_Int64
>::get();
491 else if (sDynamicType
== "double")
492 aType
= cppu::UnoType
<double>::get();
493 else if (sDynamicType
== "string")
494 aType
= cppu::UnoType
<OUString
>::get();
495 else if (sDynamicType
== "[]byte")
496 aType
= cppu::UnoType
<css::uno::Sequence
<sal_Int8
>>::get();
497 else if (sDynamicType
== "[]boolean")
498 aType
= cppu::UnoType
<css::uno::Sequence
<sal_Bool
>>::get();
499 else if (sDynamicType
== "[]short")
500 aType
= cppu::UnoType
<css::uno::Sequence
<sal_Int16
>>::get();
501 else if (sDynamicType
== "[]long")
502 aType
= cppu::UnoType
<css::uno::Sequence
<sal_Int32
>>::get();
503 else if (sDynamicType
== "[]hyper")
504 aType
= cppu::UnoType
<css::uno::Sequence
<sal_Int64
>>::get();
505 else if (sDynamicType
== "[]double")
506 aType
= cppu::UnoType
<css::uno::Sequence
<double>>::get();
507 else if (sDynamicType
== "[]string")
508 aType
= cppu::UnoType
<css::uno::Sequence
<OUString
>>::get();
509 else if (sDynamicType
== "[][]byte")
510 aType
= cppu::UnoType
<css::uno::Sequence
<css::uno::Sequence
<sal_Int8
>>>::get();
513 if (it
!= m_modifiedPrefBoxEntries
.end())
517 bool bHasValue
= sDynamicType
!= "void";
518 if (aType
== cppu::UnoType
<sal_Bool
>::get())
521 sValue
= OUString::boolean(aNode
.get
<bool>());
524 else if (aType
== cppu::UnoType
<sal_Int16
>::get())
527 sValue
= OUString::number(aNode
.get
<sal_Int16
>());
530 else if (aType
== cppu::UnoType
<sal_Int32
>::get())
533 sValue
= OUString::number(aNode
.get
<sal_Int32
>());
536 else if (aType
== cppu::UnoType
<sal_Int64
>::get())
539 sValue
= OUString::number(aNode
.get
<sal_Int64
>());
542 else if (aType
== cppu::UnoType
<double>::get())
545 sValue
= OUString::number(aNode
.get
<double>());
548 else if (aType
== cppu::UnoType
<OUString
>::get())
551 sValue
= aNode
.get
<OUString
>();
554 else if (aType
== cppu::UnoType
<css::uno::Sequence
<sal_Int8
>>::get())
558 const uno::Sequence
<sal_Int8
> seq
= aNode
.get
<uno::Sequence
<sal_Int8
>>();
559 for (sal_Int8 j
: seq
)
561 OUString s
= OUString::number(static_cast<sal_uInt8
>(j
), 16);
562 if (s
.getLength() == 1)
566 sValue
.append(s
.toAsciiUpperCase());
571 else if (aType
== cppu::UnoType
<css::uno::Sequence
<sal_Bool
>>::get())
575 uno::Sequence
<sal_Bool
> seq
= aNode
.get
<uno::Sequence
<sal_Bool
>>();
576 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
582 sValue
.append(OUString::boolean(seq
[j
]));
585 sType
= "boolean-list";
587 else if (aType
== cppu::UnoType
<css::uno::Sequence
<sal_Int16
>>::get())
591 uno::Sequence
<sal_Int16
> seq
= aNode
.get
<uno::Sequence
<sal_Int16
>>();
592 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
598 sValue
.append(static_cast<sal_Int32
>(seq
[j
]));
601 sType
= "short-list";
603 else if (aType
== cppu::UnoType
<css::uno::Sequence
<sal_Int32
>>::get())
607 uno::Sequence
<sal_Int32
> seq
= aNode
.get
<uno::Sequence
<sal_Int32
>>();
608 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
614 sValue
.append(seq
[j
]);
619 else if (aType
== cppu::UnoType
<css::uno::Sequence
<sal_Int64
>>::get())
623 uno::Sequence
<sal_Int64
> seq
= aNode
.get
<uno::Sequence
<sal_Int64
>>();
624 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
630 sValue
.append(seq
[j
]);
635 else if (aType
== cppu::UnoType
<css::uno::Sequence
<double>>::get())
639 uno::Sequence
<double> seq
= aNode
.get
<uno::Sequence
<double>>();
640 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
646 sValue
.append(seq
[j
]);
649 sType
= "double-list";
651 else if (aType
== cppu::UnoType
<css::uno::Sequence
<OUString
>>::get())
654 sValue
= lcl_StringListToString(aNode
.get
<uno::Sequence
<OUString
>>());
655 sType
= "string-list";
658 == cppu::UnoType
<css::uno::Sequence
<css::uno::Sequence
<sal_Int8
>>>::get())
662 const uno::Sequence
<uno::Sequence
<sal_Int8
>> seq
663 = aNode
.get
<uno::Sequence
<uno::Sequence
<sal_Int8
>>>();
664 for (sal_Int32 j
= 0; j
!= seq
.getLength(); ++j
)
670 for (sal_Int8 k
: seq
[j
])
672 OUString s
= OUString::number(static_cast<sal_uInt8
>(k
), 16);
673 if (s
.getLength() == 1)
677 sValue
.append(s
.toAsciiUpperCase());
681 sType
= "hexBinary-list";
685 SAL_INFO("cui.options", "path \"" << sPath
<< "\" member " << item
686 << " of unsupported type " << sType
);
693 for (int j
= 1; j
< lineage
; ++j
)
694 index
= sPath
.indexOf("/", index
+ 1);
696 InsertEntry(sPath
, aNode
, sPath
.copy(index
+ 1), item
, sType
,
697 sValue
.makeStringAndClear(), sTooltip
, pParentEntry
, !bLoadAll
, bReadOnly
,
703 Reference
<XNameAccess
> CuiAboutConfigTabPage::getConfigAccess(const OUString
& sNodePath
,
706 const uno::Reference
<uno::XComponentContext
>& xContext(
707 ::comphelper::getProcessComponentContext());
709 uno::Reference
<lang::XMultiServiceFactory
> xConfigProvider(
710 css::configuration::theDefaultProvider::get(xContext
));
712 beans::NamedValue aProperty
;
713 aProperty
.Name
= "nodepath";
714 aProperty
.Value
<<= sNodePath
;
716 uno::Sequence
<uno::Any
> aArgumentList
{ uno::Any(aProperty
) };
718 OUString sAccessString
;
721 sAccessString
= "com.sun.star.configuration.ConfigurationUpdateAccess";
723 sAccessString
= "com.sun.star.configuration.ConfigurationAccess";
725 uno::Reference
<container::XNameAccess
> xNameAccess(
726 xConfigProvider
->createInstanceWithArguments(sAccessString
, aArgumentList
),
727 uno::UNO_QUERY_THROW
);
732 void CuiAboutConfigTabPage::AddToModifiedVector(const std::shared_ptr
<Prop_Impl
>& rProp
)
734 bool isModifiedBefore
= false;
735 //Check if value modified before
736 for (std::shared_ptr
<Prop_Impl
>& nInd
: m_vectorOfModified
)
738 if (rProp
->Name
== nInd
->Name
&& rProp
->Property
== nInd
->Property
)
740 //property modified before. Assign reference to the modified value
741 //do your changes on this object. They will be saved later.
743 isModifiedBefore
= true;
748 if (!isModifiedBefore
)
749 m_vectorOfModified
.push_back(rProp
);
750 //property is not modified before
753 std::vector
<OUString
>
754 CuiAboutConfigTabPage::commaStringToSequence(std::u16string_view rCommaSepString
)
756 std::vector
<OUString
> tempVector
;
761 OUString
word(o3tl::getToken(rCommaSepString
, 0, u
',', index
));
764 tempVector
.push_back(word
);
765 } while (index
>= 0);
769 IMPL_LINK_NOARG(CuiAboutConfigTabPage
, ResetBtnHdl_Impl
, weld::Button
&, void) { Reset(); }
771 IMPL_LINK_NOARG(CuiAboutConfigTabPage
, DoubleClickHdl_Impl
, weld::TreeView
&, bool)
773 StandardHdl_Impl(*m_xEditBtn
);
777 IMPL_LINK_NOARG(CuiAboutConfigTabPage
, StandardHdl_Impl
, weld::Button
&, void)
779 if (!m_xPrefBox
->get_selected(m_xScratchIter
.get()))
782 UserData
* pUserData
= weld::fromId
<UserData
*>(m_xPrefBox
->get_id(*m_xScratchIter
));
783 if (!pUserData
|| !pUserData
->bIsPropertyPath
|| pUserData
->bIsReadOnly
)
786 //if selection is a node
787 OUString sPropertyName
= m_xPrefBox
->get_text(*m_xScratchIter
, 1);
788 OUString sPropertyType
= m_xPrefBox
->get_text(*m_xScratchIter
, 2);
789 OUString sPropertyValue
= m_xPrefBox
->get_text(*m_xScratchIter
, 3);
792 = std::make_shared
<Prop_Impl
>(pUserData
->sPropertyPath
, sPropertyName
, Any(sPropertyValue
));
793 bool bSaveChanges
= false;
795 bool bOpenDialog
= true;
796 OUString sDialogValue
;
798 if (sPropertyType
== "boolean")
801 if (sPropertyValue
== "true")
803 sDialogValue
= "false";
808 sDialogValue
= "true";
812 pProperty
->Value
<<= bValue
;
818 sDialogValue
= sPropertyValue
;
826 if (sPropertyType
== "short" || sPropertyType
== "int" || sPropertyType
== "long")
828 sal_Int64 nMin
= sPropertyType
== "short"
830 : sPropertyType
== "int" ? SAL_MIN_INT32
: SAL_MIN_INT64
;
831 sal_Int64 nMax
= sPropertyType
== "short"
833 : sPropertyType
== "int" ? SAL_MAX_INT32
: SAL_MAX_INT64
;
834 SvxNumberDialog
aNumberDialog(m_xDialog
.get(), sPropertyName
,
835 sDialogValue
.toInt64(), nMin
, nMax
);
836 if (aNumberDialog
.run() == RET_OK
)
838 sal_Int64 nNewValue
= aNumberDialog
.GetNumber();
839 if (sPropertyType
== "short")
841 pProperty
->Value
<<= static_cast<sal_Int16
>(nNewValue
);
843 else if (sPropertyType
== "int")
845 pProperty
->Value
<<= static_cast<sal_Int32
>(nNewValue
);
847 else if (sPropertyType
== "long")
849 pProperty
->Value
<<= nNewValue
;
852 sDialogValue
= OUString::number(nNewValue
);
855 else if (sPropertyType
== "double")
857 SvxDecimalNumberDialog
aNumberDialog(m_xDialog
.get(), sPropertyName
,
858 sDialogValue
.toDouble());
859 if (aNumberDialog
.run() == RET_OK
)
861 double fNewValue
= aNumberDialog
.GetNumber();
862 pProperty
->Value
<<= fNewValue
;
864 sDialogValue
= OUString::number(fNewValue
);
867 else if (sPropertyType
== "string")
869 SvxNameDialog
aNameDialog(m_xDialog
.get(), sDialogValue
, sPropertyName
);
870 aNameDialog
.SetCheckNameHdl(LINK(this, CuiAboutConfigTabPage
, ValidNameHdl
));
871 if (aNameDialog
.run() == RET_OK
)
873 sDialogValue
= aNameDialog
.GetName();
874 pProperty
->Value
<<= sDialogValue
;
878 else if (sPropertyType
== "short-list")
880 SvxListDialog
aListDialog(m_xDialog
.get());
881 aListDialog
.SetEntries(commaStringToSequence(sDialogValue
));
882 aListDialog
.SetMode(ListMode::Int16
);
883 if (aListDialog
.run() == RET_OK
)
885 std::vector
<OUString
> seqStr
= aListDialog
.GetEntries();
886 uno::Sequence
<sal_Int16
> seqShort(seqStr
.size());
888 seqStr
.begin(), seqStr
.end(), seqShort
.getArray(),
889 [](const auto& str
) { return static_cast<sal_Int16
>(str
.toInt32()); });
890 pProperty
->Value
<<= seqShort
;
891 sDialogValue
= lcl_IntListToString(seqShort
);
895 else if (sPropertyType
== "int-list")
897 SvxListDialog
aListDialog(m_xDialog
.get());
898 aListDialog
.SetEntries(commaStringToSequence(sDialogValue
));
899 aListDialog
.SetMode(ListMode::Int32
);
900 if (aListDialog
.run() == RET_OK
)
902 std::vector
<OUString
> seqStr
= aListDialog
.GetEntries();
903 uno::Sequence
<sal_Int32
> seq(seqStr
.size());
905 seqStr
.begin(), seqStr
.end(), seq
.getArray(),
906 [](const auto& str
) { return static_cast<sal_Int32
>(str
.toInt32()); });
907 pProperty
->Value
<<= seq
;
908 sDialogValue
= lcl_IntListToString(seq
);
912 else if (sPropertyType
== "long-list")
914 SvxListDialog
aListDialog(m_xDialog
.get());
915 aListDialog
.SetEntries(commaStringToSequence(sDialogValue
));
916 aListDialog
.SetMode(ListMode::Int64
);
917 if (aListDialog
.run() == RET_OK
)
919 std::vector
<OUString
> seqStr
= aListDialog
.GetEntries();
920 uno::Sequence
<sal_Int64
> seq(seqStr
.size());
922 seqStr
.begin(), seqStr
.end(), seq
.getArray(),
923 [](const auto& str
) { return static_cast<sal_Int64
>(str
.toInt32()); });
924 pProperty
->Value
<<= seq
;
925 sDialogValue
= lcl_IntListToString(seq
);
929 else if (sPropertyType
== "double-list")
931 SvxListDialog
aListDialog(m_xDialog
.get());
932 aListDialog
.SetEntries(commaStringToSequence(sDialogValue
));
933 aListDialog
.SetMode(ListMode::Double
);
934 if (aListDialog
.run() == RET_OK
)
936 std::vector
<OUString
> seqStr
= aListDialog
.GetEntries();
937 uno::Sequence
<double> seq(seqStr
.size());
939 seqStr
.begin(), seqStr
.end(), seq
.getArray(),
940 [](const auto& str
) { return static_cast<double>(str
.toDouble()); });
941 pProperty
->Value
<<= seq
;
942 sDialogValue
= lcl_DoubleListToString(seq
);
946 else if (sPropertyType
== "string-list")
948 SvxListDialog
aListDialog(m_xDialog
.get());
949 uno::Sequence
<OUString
> aList
950 = pUserData
->aPropertyValue
.get
<uno::Sequence
<OUString
>>();
951 aListDialog
.SetEntries(
952 comphelper::sequenceToContainer
<std::vector
<OUString
>>(aList
));
953 aListDialog
.SetMode(ListMode::String
);
954 if (aListDialog
.run() == RET_OK
)
956 auto seq
= comphelper::containerToSequence(aListDialog
.GetEntries());
957 sDialogValue
= lcl_StringListToString(seq
);
958 pProperty
->Value
<<= seq
;
963 throw uno::Exception("unknown property type " + sPropertyType
, nullptr);
968 AddToModifiedVector(pProperty
);
969 pUserData
->aPropertyValue
= pProperty
->Value
;
971 //update listbox value.
972 m_xPrefBox
->set_text(*m_xScratchIter
, sPropertyType
, 2);
973 m_xPrefBox
->set_text(*m_xScratchIter
, sDialogValue
, 3);
974 m_xPrefBox
->set_text_emphasis(*m_xScratchIter
, true, -1);
975 //update m_prefBoxEntries
976 auto it
= std::find_if(
977 m_prefBoxEntries
.begin(), m_prefBoxEntries
.end(),
978 [&pUserData
, &sPropertyName
](const prefBoxEntry
& rEntry
) -> bool {
979 return rEntry
.pUserData
->sPropertyPath
== pUserData
->sPropertyPath
980 && rEntry
.sStatus
== sPropertyName
;
982 if (it
!= m_prefBoxEntries
.end())
984 it
->sValue
= sDialogValue
;
985 it
->pUserData
->bWasModified
= true;
987 auto modifiedIt
= std::find_if(
988 m_modifiedPrefBoxEntries
.begin(), m_modifiedPrefBoxEntries
.end(),
989 [&pUserData
, &sPropertyName
](const prefBoxEntry
& rEntry
) -> bool {
990 return rEntry
.pUserData
->sPropertyPath
== pUserData
->sPropertyPath
991 && rEntry
.sStatus
== sPropertyName
;
994 if (modifiedIt
!= m_modifiedPrefBoxEntries
.end())
996 modifiedIt
->sValue
= sDialogValue
;
997 modifiedIt
->pUserData
->bWasModified
= true;
1001 m_modifiedPrefBoxEntries
.push_back(*it
);
1006 catch (uno::Exception
&)
1011 IMPL_LINK_NOARG(CuiAboutConfigTabPage
, SearchHdl_Impl
, weld::Button
&, void) { InputChanged(); }
1013 IMPL_LINK_NOARG(CuiAboutConfigTabPage
, ModifiedHdl_Impl
, weld::Toggleable
&, void)
1018 void CuiAboutConfigTabPage::InsertEntry(const prefBoxEntry
& rEntry
)
1020 bool bOnlyModified
= m_xModifiedCheckBtn
->get_active();
1021 if (bOnlyModified
&& !rEntry
.pUserData
->bWasModified
)
1024 OUString sPathWithProperty
= rEntry
.pUserData
->sPropertyPath
;
1025 sal_Int32 index
= sPathWithProperty
.lastIndexOf(rEntry
.sProp
);
1026 OUString sPath
= sPathWithProperty
.copy(0, index
);
1028 std::unique_ptr
<weld::TreeIter
> xParentEntry(m_xPrefBox
->make_iterator());
1029 std::unique_ptr
<weld::TreeIter
> xGrandParentEntry
;
1033 int prevIndex
= index
;
1034 index
= sPath
.indexOf("/", index
+ 1);
1035 // deal with no parent case (tdf#107811)
1038 OUString
sId(weld::toId(rEntry
.pUserData
));
1039 m_xPrefBox
->insert(nullptr, -1, &rEntry
.sProp
, &sId
, nullptr, nullptr, false,
1040 m_xScratchIter
.get());
1041 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sStatus
, 1);
1042 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sType
, 2);
1043 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sValue
, 3);
1044 m_xPrefBox
->set_text_emphasis(*m_xScratchIter
, rEntry
.pUserData
->bWasModified
, -1);
1045 m_xPrefBox
->set_sensitive(*m_xScratchIter
, !rEntry
.pUserData
->bIsReadOnly
);
1048 OUString sParentName
= sPath
.copy(prevIndex
+ 1, index
- prevIndex
- 1);
1050 bool hasEntry
= false;
1053 if (!xGrandParentEntry
)
1054 bStartOk
= m_xPrefBox
->get_iter_first(*xParentEntry
);
1057 m_xPrefBox
->copy_iterator(*xGrandParentEntry
, *xParentEntry
);
1058 bStartOk
= m_xPrefBox
->iter_children(*xParentEntry
);
1065 if (m_xPrefBox
->get_text(*xParentEntry
, 0) == sParentName
)
1070 } while (m_xPrefBox
->iter_next_sibling(*xParentEntry
));
1075 m_xPrefBox
->insert(xGrandParentEntry
.get(), -1, &sParentName
, nullptr, nullptr, nullptr,
1076 false, xParentEntry
.get());
1077 //It is needed, without this the selection line will be truncated.
1078 m_xPrefBox
->set_text(*xParentEntry
, u
""_ustr
, 1);
1079 m_xPrefBox
->set_text(*xParentEntry
, u
""_ustr
, 2);
1080 m_xPrefBox
->set_text(*xParentEntry
, u
""_ustr
, 3);
1081 m_xPrefBox
->set_text_emphasis(*xParentEntry
, false, -1);
1082 m_xPrefBox
->set_sensitive(*xParentEntry
, true);
1085 xGrandParentEntry
= m_xPrefBox
->make_iterator(xParentEntry
.get());
1086 } while (index
< sPath
.getLength() - 1);
1088 OUString
sId(weld::toId(rEntry
.pUserData
));
1089 m_xPrefBox
->insert(xParentEntry
.get(), -1, &rEntry
.sProp
, &sId
, nullptr, nullptr, false,
1090 m_xScratchIter
.get());
1091 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sStatus
, 1);
1092 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sType
, 2);
1093 m_xPrefBox
->set_text(*m_xScratchIter
, rEntry
.sValue
, 3);
1094 m_xPrefBox
->set_text_emphasis(*m_xScratchIter
, rEntry
.pUserData
->bWasModified
, -1);
1095 m_xPrefBox
->set_sensitive(*m_xScratchIter
, !rEntry
.pUserData
->bIsReadOnly
);
1098 IMPL_LINK(CuiAboutConfigTabPage
, ExpandingHdl_Impl
, const weld::TreeIter
&, rEntry
, bool)
1100 if (m_xPrefBox
->iter_has_child(rEntry
))
1102 UserData
* pUserData
= weld::fromId
<UserData
*>(m_xPrefBox
->get_id(rEntry
));
1103 if (pUserData
&& !pUserData
->bIsPropertyPath
)
1105 assert(pUserData
->aXNameAccess
.is());
1106 FillItems(pUserData
->aXNameAccess
, &rEntry
, pUserData
->aLineage
);
1111 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */