/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "optaboutconfig.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::container; struct Prop_Impl { OUString Name; OUString Property; Any Value; Prop_Impl(OUString sName, OUString sProperty, Any aValue) : Name(std::move(sName)) , Property(std::move(sProperty)) , Value(std::move(aValue)) { } }; struct UserData { bool bIsPropertyPath; bool bIsReadOnly; bool bWasModified; OUString sPropertyPath; Any aPropertyValue; OUString sTooltip; int aLineage; Reference aXNameAccess; explicit UserData(OUString aPropertyPath, Any aPropValue, OUString aTooltip, bool isReadOnly, bool wasModified) : bIsPropertyPath(true) , bIsReadOnly(isReadOnly) , bWasModified(wasModified) , sPropertyPath(std::move(aPropertyPath)) , aPropertyValue(aPropValue) , sTooltip(std::move(aTooltip)) , aLineage(0) { } explicit UserData(Reference const& rXNameAccess, int rIndex) : bIsPropertyPath(false) , bIsReadOnly(false) , bWasModified(false) , aLineage(rIndex) , aXNameAccess(rXNameAccess) { } }; CuiAboutConfigTabPage::CuiAboutConfigTabPage(weld::Window* pParent) : GenericDialogController(pParent, "cui/ui/aboutconfigdialog.ui", "AboutConfig") , m_xResetBtn(m_xBuilder->weld_button("reset")) , m_xEditBtn(m_xBuilder->weld_button("edit")) , m_xSearchBtn(m_xBuilder->weld_button("searchButton")) , m_xModifiedCheckBtn(m_xBuilder->weld_check_button("modifiedButton")) , m_xSearchEdit(m_xBuilder->weld_entry("searchEntry")) , m_xPrefBox(m_xBuilder->weld_tree_view("preferences")) , m_xScratchIter(m_xPrefBox->make_iterator()) , m_bSorted(false) , m_pParent(pParent) { m_xPrefBox->set_size_request(m_xPrefBox->get_approximate_digit_width() * 100, m_xPrefBox->get_height_rows(23)); m_xPrefBox->connect_column_clicked(LINK(this, CuiAboutConfigTabPage, HeaderBarClick)); m_xEditBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, StandardHdl_Impl)); m_xResetBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, ResetBtnHdl_Impl)); m_xPrefBox->connect_row_activated(LINK(this, CuiAboutConfigTabPage, DoubleClickHdl_Impl)); m_xPrefBox->connect_expanding(LINK(this, CuiAboutConfigTabPage, ExpandingHdl_Impl)); m_xSearchBtn->connect_clicked(LINK(this, CuiAboutConfigTabPage, SearchHdl_Impl)); m_xModifiedCheckBtn->connect_toggled(LINK(this, CuiAboutConfigTabPage, ModifiedHdl_Impl)); m_options.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE; m_options.transliterateFlags |= TransliterationFlags::IGNORE_CASE; m_options.searchFlag |= (util::SearchFlags::REG_NOT_BEGINOFLINE | util::SearchFlags::REG_NOT_ENDOFLINE); float fWidth = m_xPrefBox->get_approximate_digit_width(); std::vector aWidths{ o3tl::narrowing(fWidth * 65), o3tl::narrowing(fWidth * 20), o3tl::narrowing(fWidth * 8) }; m_xPrefBox->set_column_fixed_widths(aWidths); m_xPrefBox->connect_query_tooltip(LINK(this, CuiAboutConfigTabPage, QueryTooltip)); } IMPL_LINK(CuiAboutConfigTabPage, QueryTooltip, const weld::TreeIter&, rIter, OUString) { UserData* pUserData = weld::fromId(m_xPrefBox->get_id(rIter)); OUStringBuffer ret; if (pUserData && pUserData->bIsReadOnly) { ret.append(CuiResId(RID_CUISTR_OPT_READONLY)); } if (pUserData && !pUserData->sTooltip.isEmpty()) { if (pUserData->bIsReadOnly) ret.append("\n\n"); ret.append(pUserData->sTooltip); } return ret.makeStringAndClear(); } IMPL_LINK(CuiAboutConfigTabPage, HeaderBarClick, int, nColumn, void) { if (!m_bSorted) { m_xPrefBox->make_sorted(); m_bSorted = true; } bool bSortAtoZ = m_xPrefBox->get_sort_order(); //set new arrow positions in headerbar if (nColumn == m_xPrefBox->get_sort_column()) { bSortAtoZ = !bSortAtoZ; m_xPrefBox->set_sort_order(bSortAtoZ); } else { int nOldSortColumn = m_xPrefBox->get_sort_column(); if (nOldSortColumn != -1) m_xPrefBox->set_sort_indicator(TRISTATE_INDET, nOldSortColumn); m_xPrefBox->set_sort_column(nColumn); } if (nColumn != -1) { //sort lists m_xPrefBox->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn); } } IMPL_STATIC_LINK_NOARG(CuiAboutConfigTabPage, ValidNameHdl, SvxNameDialog&, bool) { // Allow empty value return true; } CuiAboutConfigTabPage::~CuiAboutConfigTabPage() {} void CuiAboutConfigTabPage::InsertEntry(const OUString& rPropertyPath, Any aPropertyValue, const OUString& rProp, const OUString& rStatus, const OUString& rType, const OUString& rValue, const OUString& rTooltip, const weld::TreeIter* pParentEntry, bool bInsertToPrefBox, bool bIsReadOnly, bool bWasModified) { bool bOnlyModified = m_xModifiedCheckBtn->get_active(); if (bOnlyModified && !bWasModified) return; m_vectorUserData.push_back(std::make_unique(rPropertyPath, aPropertyValue, rTooltip, bIsReadOnly, bWasModified)); if (bInsertToPrefBox) { OUString sId(weld::toId(m_vectorUserData.back().get())); m_xPrefBox->insert(pParentEntry, -1, &rProp, &sId, nullptr, nullptr, false, m_xScratchIter.get()); m_xPrefBox->set_text(*m_xScratchIter, rStatus, 1); m_xPrefBox->set_text(*m_xScratchIter, rType, 2); m_xPrefBox->set_text(*m_xScratchIter, rValue, 3); m_xPrefBox->set_text_emphasis(*m_xScratchIter, bWasModified, -1); m_xPrefBox->set_sensitive(*m_xScratchIter, !bIsReadOnly, -1); } else { m_prefBoxEntries.push_back( { rProp, rStatus, rType, rValue, m_vectorUserData.back().get() }); } } void CuiAboutConfigTabPage::InputChanged() { weld::WaitObject aWait(m_xDialog.get()); m_xPrefBox->hide(); m_xPrefBox->clear(); m_xPrefBox->freeze(); if (m_bSorted) m_xPrefBox->make_unsorted(); if (m_xSearchEdit->get_text().isEmpty()) { m_xPrefBox->clear(); Reference xConfigAccess = getConfigAccess("/", false); FillItems(xConfigAccess); } else { m_options.searchString = m_xSearchEdit->get_text(); utl::TextSearch textSearch(m_options); for (auto const& it : m_prefBoxEntries) { sal_Int32 endPos, startPos = 0; for (size_t i = 0; i < 5; ++i) { OUString scrTxt; if (i == 0) scrTxt = it.pUserData->sPropertyPath; else if (i == 1) scrTxt = it.sProp; else if (i == 2) scrTxt = it.sStatus; else if (i == 3) scrTxt = it.sType; else if (i == 4) scrTxt = it.sValue; endPos = scrTxt.getLength(); if (textSearch.SearchForward(scrTxt, &startPos, &endPos)) { InsertEntry(it); break; } } } } m_xPrefBox->thaw(); if (m_bSorted) m_xPrefBox->make_sorted(); m_xPrefBox->all_foreach([this](weld::TreeIter& rEntry) { m_xPrefBox->expand_row(rEntry); return false; }); m_xPrefBox->show(); } void CuiAboutConfigTabPage::Reset() { weld::WaitObject aWait(m_xDialog.get()); m_xPrefBox->clear(); m_vectorOfModified.clear(); if (m_bSorted) { m_xPrefBox->set_sort_indicator(TRISTATE_INDET, m_xPrefBox->get_sort_column()); m_xPrefBox->make_unsorted(); m_bSorted = false; } m_prefBoxEntries.clear(); m_modifiedPrefBoxEntries.clear(); m_xPrefBox->freeze(); Reference xConfigAccess = getConfigAccess("/", false); //Load all XNameAccess to m_prefBoxEntries FillItems(xConfigAccess, nullptr, 0, true); //Load xConfigAccess' children to m_prefBox FillItems(xConfigAccess); m_xPrefBox->thaw(); } void CuiAboutConfigTabPage::FillItemSet() { std::vector>::iterator pIter; for (pIter = m_vectorOfModified.begin(); pIter != m_vectorOfModified.end(); ++pIter) { Reference xUpdateAccess = getConfigAccess((*pIter)->Name, true); Reference xNameReplace(xUpdateAccess, UNO_QUERY_THROW); xNameReplace->replaceByName((*pIter)->Property, (*pIter)->Value); Reference xChangesBatch(xUpdateAccess, UNO_QUERY_THROW); xChangesBatch->commitChanges(); } } namespace { OUString lcl_StringListToString(const uno::Sequence& seq) { OUStringBuffer sBuffer; for (sal_Int32 i = 0; i != seq.getLength(); ++i) { if (i != 0) sBuffer.append(","); sBuffer.append(seq[i]); } return sBuffer.makeStringAndClear(); } OUString lcl_IntListToString(const uno::Sequence& seq) { OUStringBuffer sBuffer; for (sal_Int32 i = 0; i != seq.getLength(); ++i) { if (i != 0) sBuffer.append(","); sBuffer.append(OUString::number(seq[i])); } return sBuffer.makeStringAndClear(); } OUString lcl_IntListToString(const uno::Sequence& seq) { OUStringBuffer sBuffer; for (sal_Int32 i = 0; i != seq.getLength(); ++i) { if (i != 0) sBuffer.append(","); sBuffer.append(OUString::number(seq[i])); } return sBuffer.makeStringAndClear(); } OUString lcl_IntListToString(const uno::Sequence& seq) { OUStringBuffer sBuffer; for (sal_Int32 i = 0; i != seq.getLength(); ++i) { if (i != 0) sBuffer.append(","); sBuffer.append(OUString::number(seq[i])); } return sBuffer.makeStringAndClear(); } OUString lcl_DoubleListToString(const uno::Sequence& seq) { OUStringBuffer sBuffer; for (sal_Int32 i = 0; i != seq.getLength(); ++i) { if (i != 0) sBuffer.append(","); sBuffer.append(OUString::number(seq[i])); } return sBuffer.makeStringAndClear(); } } void CuiAboutConfigTabPage::FillItems(const Reference& xNameAccess, const weld::TreeIter* pParentEntry, int lineage, bool bLoadAll) { OUString sPath = Reference(xNameAccess, uno::UNO_QUERY_THROW)->getHierarchicalName(); const uno::Sequence seqItems = xNameAccess->getElementNames(); for (const OUString& item : seqItems) { Any aNode = xNameAccess->getByName(item); bool bNotLeaf = false; Reference xNextNameAccess; try { xNextNameAccess.set(aNode, uno::UNO_QUERY); bNotLeaf = xNextNameAccess.is(); } catch (const RuntimeException&) { TOOLS_WARN_EXCEPTION("cui.options", "CuiAboutConfigTabPage"); } if (bNotLeaf) { if (bLoadAll) FillItems(xNextNameAccess, nullptr, lineage + 1, true); else { // not leaf node m_vectorUserData.push_back( std::make_unique(xNextNameAccess, lineage + 1)); OUString sId(weld::toId(m_vectorUserData.back().get())); m_xPrefBox->insert(pParentEntry, -1, &item, &sId, nullptr, nullptr, true, m_xScratchIter.get()); // Necessary, without this the selection line will be truncated. m_xPrefBox->set_text(*m_xScratchIter, "", 1); m_xPrefBox->set_text(*m_xScratchIter, "", 2); m_xPrefBox->set_text(*m_xScratchIter, "", 3); m_xPrefBox->set_sensitive(*m_xScratchIter, true); } } else { // leaf node OUString sPropertyName = item; auto it = std::find_if(m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(), [&sPath, &sPropertyName](const prefBoxEntry& rEntry) -> bool { return rEntry.pUserData->sPropertyPath == sPath && rEntry.sStatus == sPropertyName; }); css::uno::Reference m_xReadWriteAccess; m_xReadWriteAccess = css::configuration::ReadWriteAccess::create( ::comphelper::getProcessComponentContext(), "*"); beans::Property aProperty; bool bReadOnly = false; OUString sFullPath(sPath + "/" + sPropertyName); try { aProperty = m_xReadWriteAccess->getPropertyByHierarchicalName(sFullPath); bReadOnly = (aProperty.Attributes & beans::PropertyAttribute::READONLY) != 0; } catch (css::beans::UnknownPropertyException) { SAL_WARN("cui.options", "unknown property: " << sFullPath); } OUString sTooltip; OUString sType; bool bWasModified = false; css::uno::Type aType = cppu::UnoType::get(); OUString sDynamicType = aNode.getValueTypeName(); try { Reference xDocumentation(xNameAccess, UNO_QUERY_THROW); sTooltip = xDocumentation->getDescriptionByHierarchicalName(sPath + "/" + sPropertyName); aType = xDocumentation->getTypeByHierarchicalName(sFullPath); bWasModified = xDocumentation->getModifiedByHierarchicalName(sFullPath); } catch (css::container::NoSuchElementException) { } catch (css::util::InvalidStateException) { } OUStringBuffer sValue; // Fall back to dynamic type when this is empty if (aType == cppu::UnoType::get() && sDynamicType != "void") { if (sDynamicType == "boolean") aType = cppu::UnoType::get(); else if (sDynamicType == "short") aType = cppu::UnoType::get(); else if (sDynamicType == "long") aType = cppu::UnoType::get(); else if (sDynamicType == "hyper") aType = cppu::UnoType::get(); else if (sDynamicType == "double") aType = cppu::UnoType::get(); else if (sDynamicType == "string") aType = cppu::UnoType::get(); else if (sDynamicType == "[]byte") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]boolean") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]short") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]long") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]hyper") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]double") aType = cppu::UnoType>::get(); else if (sDynamicType == "[]string") aType = cppu::UnoType>::get(); else if (sDynamicType == "[][]byte") aType = cppu::UnoType>>::get(); } if (it != m_modifiedPrefBoxEntries.end()) sValue = it->sValue; else { bool bHasValue = sDynamicType != "void"; if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = OUString::boolean(aNode.get()); sType = "boolean"; } else if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = OUString::number(aNode.get()); sType = "short"; } else if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = OUString::number(aNode.get()); sType = "int"; } else if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = OUString::number(aNode.get()); sType = "long"; } else if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = OUString::number(aNode.get()); sType = "double"; } else if (aType == cppu::UnoType::get()) { if (bHasValue) sValue = aNode.get(); sType = "string"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { const uno::Sequence seq = aNode.get>(); for (sal_Int8 j : seq) { OUString s = OUString::number(static_cast(j), 16); if (s.getLength() == 1) { sValue.append("0"); } sValue.append(s.toAsciiUpperCase()); } } sType = "hexBinary"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { uno::Sequence seq = aNode.get>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } sValue.append(OUString::boolean(seq[j])); } } sType = "boolean-list"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { uno::Sequence seq = aNode.get>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } sValue.append(static_cast(seq[j])); } } sType = "short-list"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { uno::Sequence seq = aNode.get>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } sValue.append(seq[j]); } } sType = "int-list"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { uno::Sequence seq = aNode.get>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } sValue.append(seq[j]); } } sType = "long-list"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) { uno::Sequence seq = aNode.get>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } sValue.append(seq[j]); } } sType = "double-list"; } else if (aType == cppu::UnoType>::get()) { if (bHasValue) sValue = lcl_StringListToString(aNode.get>()); sType = "string-list"; } else if (aType == cppu::UnoType>>::get()) { if (bHasValue) { const uno::Sequence> seq = aNode.get>>(); for (sal_Int32 j = 0; j != seq.getLength(); ++j) { if (j != 0) { sValue.append(","); } for (sal_Int8 k : seq[j]) { OUString s = OUString::number(static_cast(k), 16); if (s.getLength() == 1) { sValue.append("0"); } sValue.append(s.toAsciiUpperCase()); } } } sType = "hexBinary-list"; } else { SAL_INFO("cui.options", "path \"" << sPath << "\" member " << item << " of unsupported type " << sType); continue; } } //Short name int index = 0; for (int j = 1; j < lineage; ++j) index = sPath.indexOf("/", index + 1); InsertEntry(sPath, aNode, sPath.copy(index + 1), item, sType, sValue.makeStringAndClear(), sTooltip, pParentEntry, !bLoadAll, bReadOnly, bWasModified); } } } Reference CuiAboutConfigTabPage::getConfigAccess(const OUString& sNodePath, bool bUpdate) { uno::Reference xContext(::comphelper::getProcessComponentContext()); uno::Reference xConfigProvider( css::configuration::theDefaultProvider::get(xContext)); beans::NamedValue aProperty; aProperty.Name = "nodepath"; aProperty.Value <<= sNodePath; uno::Sequence aArgumentList{ uno::Any(aProperty) }; OUString sAccessString; if (bUpdate) sAccessString = "com.sun.star.configuration.ConfigurationUpdateAccess"; else sAccessString = "com.sun.star.configuration.ConfigurationAccess"; uno::Reference xNameAccess( xConfigProvider->createInstanceWithArguments(sAccessString, aArgumentList), uno::UNO_QUERY_THROW); return xNameAccess; } void CuiAboutConfigTabPage::AddToModifiedVector(const std::shared_ptr& rProp) { bool isModifiedBefore = false; //Check if value modified before for (std::shared_ptr& nInd : m_vectorOfModified) { if (rProp->Name == nInd->Name && rProp->Property == nInd->Property) { //property modified before. Assign reference to the modified value //do your changes on this object. They will be saved later. nInd = rProp; isModifiedBefore = true; break; } } if (!isModifiedBefore) m_vectorOfModified.push_back(rProp); //property is not modified before } std::vector CuiAboutConfigTabPage::commaStringToSequence(std::u16string_view rCommaSepString) { std::vector tempVector; sal_Int32 index = 0; do { OUString word(o3tl::getToken(rCommaSepString, 0, u',', index)); word = word.trim(); if (!word.isEmpty()) tempVector.push_back(word); } while (index >= 0); return tempVector; } IMPL_LINK_NOARG(CuiAboutConfigTabPage, ResetBtnHdl_Impl, weld::Button&, void) { Reset(); } IMPL_LINK_NOARG(CuiAboutConfigTabPage, DoubleClickHdl_Impl, weld::TreeView&, bool) { StandardHdl_Impl(*m_xEditBtn); return true; } IMPL_LINK_NOARG(CuiAboutConfigTabPage, StandardHdl_Impl, weld::Button&, void) { if (!m_xPrefBox->get_selected(m_xScratchIter.get())) return; UserData* pUserData = weld::fromId(m_xPrefBox->get_id(*m_xScratchIter)); if (!pUserData || !pUserData->bIsPropertyPath || pUserData->bIsReadOnly) return; //if selection is a node OUString sPropertyName = m_xPrefBox->get_text(*m_xScratchIter, 1); OUString sPropertyType = m_xPrefBox->get_text(*m_xScratchIter, 2); OUString sPropertyValue = m_xPrefBox->get_text(*m_xScratchIter, 3); auto pProperty = std::make_shared(pUserData->sPropertyPath, sPropertyName, Any(sPropertyValue)); bool bSaveChanges = false; bool bOpenDialog = true; OUString sDialogValue; if (sPropertyType == "boolean") { bool bValue; if (sPropertyValue == "true") { sDialogValue = "false"; bValue = false; } else { sDialogValue = "true"; bValue = true; } pProperty->Value <<= bValue; bOpenDialog = false; bSaveChanges = true; } else { sDialogValue = sPropertyValue; bOpenDialog = true; } try { if (bOpenDialog) { if (sPropertyType == "short" || sPropertyType == "int" || sPropertyType == "long") { sal_Int64 nMin = sPropertyType == "short" ? SAL_MIN_INT16 : sPropertyType == "int" ? SAL_MIN_INT32 : SAL_MIN_INT64; sal_Int64 nMax = sPropertyType == "short" ? SAL_MAX_INT16 : sPropertyType == "int" ? SAL_MAX_INT32 : SAL_MAX_INT64; SvxNumberDialog aNumberDialog(m_xDialog.get(), sPropertyName, sDialogValue.toInt64(), nMin, nMax); if (aNumberDialog.run() == RET_OK) { sal_Int64 nNewValue = aNumberDialog.GetNumber(); if (sPropertyType == "short") { pProperty->Value <<= static_cast(nNewValue); } else if (sPropertyType == "int") { pProperty->Value <<= static_cast(nNewValue); } else if (sPropertyType == "long") { pProperty->Value <<= nNewValue; } bSaveChanges = true; sDialogValue = OUString::number(nNewValue); } } else if (sPropertyType == "double") { SvxDecimalNumberDialog aNumberDialog(m_xDialog.get(), sPropertyName, sDialogValue.toDouble()); if (aNumberDialog.run() == RET_OK) { double fNewValue = aNumberDialog.GetNumber(); pProperty->Value <<= fNewValue; bSaveChanges = true; sDialogValue = OUString::number(fNewValue); } } else if (sPropertyType == "string") { SvxNameDialog aNameDialog(m_xDialog.get(), sDialogValue, sPropertyName); aNameDialog.SetCheckNameHdl(LINK(this, CuiAboutConfigTabPage, ValidNameHdl)); if (aNameDialog.run() == RET_OK) { sDialogValue = aNameDialog.GetName(); pProperty->Value <<= sDialogValue; bSaveChanges = true; } } else if (sPropertyType == "short-list") { SvxListDialog aListDialog(m_xDialog.get()); aListDialog.SetEntries(commaStringToSequence(sDialogValue)); aListDialog.SetMode(ListMode::Int16); if (aListDialog.run() == RET_OK) { std::vector seqStr = aListDialog.GetEntries(); uno::Sequence seqShort(seqStr.size()); std::transform( seqStr.begin(), seqStr.end(), seqShort.getArray(), [](const auto& str) { return static_cast(str.toInt32()); }); pProperty->Value <<= seqShort; sDialogValue = lcl_IntListToString(seqShort); bSaveChanges = true; } } else if (sPropertyType == "int-list") { SvxListDialog aListDialog(m_xDialog.get()); aListDialog.SetEntries(commaStringToSequence(sDialogValue)); aListDialog.SetMode(ListMode::Int32); if (aListDialog.run() == RET_OK) { std::vector seqStr = aListDialog.GetEntries(); uno::Sequence seq(seqStr.size()); std::transform( seqStr.begin(), seqStr.end(), seq.getArray(), [](const auto& str) { return static_cast(str.toInt32()); }); pProperty->Value <<= seq; sDialogValue = lcl_IntListToString(seq); bSaveChanges = true; } } else if (sPropertyType == "long-list") { SvxListDialog aListDialog(m_xDialog.get()); aListDialog.SetEntries(commaStringToSequence(sDialogValue)); aListDialog.SetMode(ListMode::Int64); if (aListDialog.run() == RET_OK) { std::vector seqStr = aListDialog.GetEntries(); uno::Sequence seq(seqStr.size()); std::transform( seqStr.begin(), seqStr.end(), seq.getArray(), [](const auto& str) { return static_cast(str.toInt32()); }); pProperty->Value <<= seq; sDialogValue = lcl_IntListToString(seq); bSaveChanges = true; } } else if (sPropertyType == "double-list") { SvxListDialog aListDialog(m_xDialog.get()); aListDialog.SetEntries(commaStringToSequence(sDialogValue)); aListDialog.SetMode(ListMode::Double); if (aListDialog.run() == RET_OK) { std::vector seqStr = aListDialog.GetEntries(); uno::Sequence seq(seqStr.size()); std::transform( seqStr.begin(), seqStr.end(), seq.getArray(), [](const auto& str) { return static_cast(str.toDouble()); }); pProperty->Value <<= seq; sDialogValue = lcl_DoubleListToString(seq); bSaveChanges = true; } } else if (sPropertyType == "string-list") { SvxListDialog aListDialog(m_xDialog.get()); uno::Sequence aList = pUserData->aPropertyValue.get>(); aListDialog.SetEntries( comphelper::sequenceToContainer>(aList)); aListDialog.SetMode(ListMode::String); if (aListDialog.run() == RET_OK) { auto seq = comphelper::containerToSequence(aListDialog.GetEntries()); sDialogValue = lcl_StringListToString(seq); pProperty->Value <<= seq; bSaveChanges = true; } } else //unknown throw uno::Exception("unknown property type " + sPropertyType, nullptr); } if (bSaveChanges) { AddToModifiedVector(pProperty); pUserData->aPropertyValue = pProperty->Value; //update listbox value. m_xPrefBox->set_text(*m_xScratchIter, sPropertyType, 2); m_xPrefBox->set_text(*m_xScratchIter, sDialogValue, 3); m_xPrefBox->set_text_emphasis(*m_xScratchIter, true, -1); //update m_prefBoxEntries auto it = std::find_if( m_prefBoxEntries.begin(), m_prefBoxEntries.end(), [&pUserData, &sPropertyName](const prefBoxEntry& rEntry) -> bool { return rEntry.pUserData->sPropertyPath == pUserData->sPropertyPath && rEntry.sStatus == sPropertyName; }); if (it != m_prefBoxEntries.end()) { it->sValue = sDialogValue; it->pUserData->bWasModified = true; auto modifiedIt = std::find_if( m_modifiedPrefBoxEntries.begin(), m_modifiedPrefBoxEntries.end(), [&pUserData, &sPropertyName](const prefBoxEntry& rEntry) -> bool { return rEntry.pUserData->sPropertyPath == pUserData->sPropertyPath && rEntry.sStatus == sPropertyName; }); if (modifiedIt != m_modifiedPrefBoxEntries.end()) { modifiedIt->sValue = sDialogValue; modifiedIt->pUserData->bWasModified = true; } else { m_modifiedPrefBoxEntries.push_back(*it); } } } } catch (uno::Exception&) { } } IMPL_LINK_NOARG(CuiAboutConfigTabPage, SearchHdl_Impl, weld::Button&, void) { InputChanged(); } IMPL_LINK_NOARG(CuiAboutConfigTabPage, ModifiedHdl_Impl, weld::Toggleable&, void) { InputChanged(); } void CuiAboutConfigTabPage::InsertEntry(const prefBoxEntry& rEntry) { bool bOnlyModified = m_xModifiedCheckBtn->get_active(); if (bOnlyModified && !rEntry.pUserData->bWasModified) return; OUString sPathWithProperty = rEntry.pUserData->sPropertyPath; sal_Int32 index = sPathWithProperty.lastIndexOf(rEntry.sProp); OUString sPath = sPathWithProperty.copy(0, index); index = 0; std::unique_ptr xParentEntry(m_xPrefBox->make_iterator()); std::unique_ptr xGrandParentEntry; do { int prevIndex = index; index = sPath.indexOf("/", index + 1); // deal with no parent case (tdf#107811) if (index < 0) { OUString sId(weld::toId(rEntry.pUserData)); m_xPrefBox->insert(nullptr, -1, &rEntry.sProp, &sId, nullptr, nullptr, false, m_xScratchIter.get()); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sStatus, 1); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sType, 2); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sValue, 3); m_xPrefBox->set_text_emphasis(*m_xScratchIter, rEntry.pUserData->bWasModified, -1); m_xPrefBox->set_sensitive(*m_xScratchIter, !rEntry.pUserData->bIsReadOnly); return; } OUString sParentName = sPath.copy(prevIndex + 1, index - prevIndex - 1); bool hasEntry = false; bool bStartOk; if (!xGrandParentEntry) bStartOk = m_xPrefBox->get_iter_first(*xParentEntry); else { m_xPrefBox->copy_iterator(*xGrandParentEntry, *xParentEntry); bStartOk = m_xPrefBox->iter_children(*xParentEntry); } if (bStartOk) { do { if (m_xPrefBox->get_text(*xParentEntry, 0) == sParentName) { hasEntry = true; break; } } while (m_xPrefBox->iter_next_sibling(*xParentEntry)); } if (!hasEntry) { m_xPrefBox->insert(xGrandParentEntry.get(), -1, &sParentName, nullptr, nullptr, nullptr, false, xParentEntry.get()); //It is needed, without this the selection line will be truncated. m_xPrefBox->set_text(*xParentEntry, "", 1); m_xPrefBox->set_text(*xParentEntry, "", 2); m_xPrefBox->set_text(*xParentEntry, "", 3); m_xPrefBox->set_sensitive(*xParentEntry, true); } xGrandParentEntry = m_xPrefBox->make_iterator(xParentEntry.get()); } while (index < sPath.getLength() - 1); OUString sId(weld::toId(rEntry.pUserData)); m_xPrefBox->insert(xParentEntry.get(), -1, &rEntry.sProp, &sId, nullptr, nullptr, false, m_xScratchIter.get()); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sStatus, 1); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sType, 2); m_xPrefBox->set_text(*m_xScratchIter, rEntry.sValue, 3); m_xPrefBox->set_text_emphasis(*m_xScratchIter, rEntry.pUserData->bWasModified, -1); m_xPrefBox->set_sensitive(*m_xScratchIter, !rEntry.pUserData->bIsReadOnly); } IMPL_LINK(CuiAboutConfigTabPage, ExpandingHdl_Impl, const weld::TreeIter&, rEntry, bool) { if (m_xPrefBox->iter_has_child(rEntry)) return true; UserData* pUserData = weld::fromId(m_xPrefBox->get_id(rEntry)); if (pUserData && !pUserData->bIsPropertyPath) { assert(pUserData->aXNameAccess.is()); FillItems(pUserData->aXNameAccess, &rEntry, pUserData->aLineage); } return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */