cui/UIConfig_cui.mk                   |    1 
 cui/source/dialogs/dlgname.cxx        |  109 ++++++++++++++++
 cui/source/options/optaboutconfig.cxx |   37 +++--
 cui/uiconfig/ui/listdialog.ui         |  231 ++++++++++++++++++++++++++++++++++
 include/cui/dlgname.hxx               |   26 +++
 5 files changed, 389 insertions(+), 15 deletions(-)

New commits:
commit 847db3fa1244c2707e1966d3e6579258bb6d8924
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Thu Nov 16 21:33:25 2023 +0100
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon Nov 20 08:24:51 2023 +0100

    tdf#157438 Make string lists editable in expert config
    
    Change-Id: Ia8b8553d547e760c18624c5c599951523b74ac82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159523
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>

diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk
index 97a4a56f3ecc..10acd83c8c39 100644
--- a/cui/UIConfig_cui.mk
+++ b/cui/UIConfig_cui.mk
@@ -113,6 +113,7 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\
        cui/uiconfig/ui/linetabpage \
        cui/uiconfig/ui/lineendstabpage \
        cui/uiconfig/ui/linestyletabpage \
+       cui/uiconfig/ui/listdialog \
        cui/uiconfig/ui/macroassigndialog \
        cui/uiconfig/ui/macroassignpage \
        cui/uiconfig/ui/macroselectordialog \
diff --git a/cui/source/dialogs/dlgname.cxx b/cui/source/dialogs/dlgname.cxx
index a96b59290bbd..a06833bb6ce6 100644
--- a/cui/source/dialogs/dlgname.cxx
+++ b/cui/source/dialogs/dlgname.cxx
@@ -19,6 +19,8 @@
 
 #include <cui/dlgname.hxx>
 
+#include <comphelper/string.hxx>
+
 /*************************************************************************
 |*
 |* Dialog for editing a name
@@ -144,4 +146,111 @@ IMPL_LINK_NOARG(SvxObjectTitleDescDialog, DecorativeHdl, 
weld::Toggleable&, void
     m_xDescriptionFT->set_sensitive(bEnable);
 }
 
+SvxListDialog::SvxListDialog(weld::Window* pParent)
+    : GenericDialogController(pParent, "cui/ui/listdialog.ui", "ListDialog")
+    , m_xList(m_xBuilder->weld_tree_view("assignlist"))
+    , m_xAddBtn(m_xBuilder->weld_button("addbtn"))
+    , m_xRemoveBtn(m_xBuilder->weld_button("removebtn"))
+    , m_xEditBtn(m_xBuilder->weld_button("editbtn"))
+{
+    m_xList->set_size_request(m_xList->get_approximate_digit_width() * 54,
+                              m_xList->get_height_rows(6));
+    m_xAddBtn->connect_clicked(LINK(this, SvxListDialog, AddHdl_Impl));
+    m_xRemoveBtn->connect_clicked(LINK(this, SvxListDialog, RemoveHdl_Impl));
+    m_xEditBtn->connect_clicked(LINK(this, SvxListDialog, EditHdl_Impl));
+    m_xList->connect_changed(LINK(this, SvxListDialog, SelectHdl_Impl));
+    m_xList->connect_row_activated(LINK(this, SvxListDialog, 
DblClickHdl_Impl));
+
+    SelectionChanged();
+}
+
+SvxListDialog::~SvxListDialog() {}
+
+IMPL_LINK_NOARG(SvxListDialog, AddHdl_Impl, weld::Button&, void)
+{
+    SvxNameDialog aNameDlg(m_xDialog.get(), "", "blabla");
+
+    if (!aNameDlg.run())
+        return;
+    OUString sNewText = comphelper::string::strip(aNameDlg.GetName(), ' ');
+    if (!sNewText.isEmpty())
+    {
+        m_xList->insert_text(-1, sNewText);
+        m_xList->select(-1);
+    }
+}
+
+IMPL_LINK_NOARG(SvxListDialog, EditHdl_Impl, weld::Button&, void) { 
EditEntry(); }
+
+IMPL_LINK_NOARG(SvxListDialog, SelectHdl_Impl, weld::TreeView&, void) { 
SelectionChanged(); }
+
+IMPL_LINK_NOARG(SvxListDialog, DblClickHdl_Impl, weld::TreeView&, bool)
+{
+    EditEntry();
+    return true;
+}
+
+IMPL_LINK_NOARG(SvxListDialog, RemoveHdl_Impl, weld::Button&, void)
+{
+    int nPos = m_xList->get_selected_index();
+    if (nPos == -1)
+        return;
+    m_xList->remove(nPos);
+    int nCount = m_xList->n_children();
+    if (nCount)
+    {
+        if (nPos >= nCount)
+            nPos = nCount - 1;
+        m_xList->select(nPos);
+    }
+    SelectionChanged();
+}
+
+void SvxListDialog::SelectionChanged()
+{
+    bool bEnable = m_xList->get_selected_index() != -1;
+    m_xRemoveBtn->set_sensitive(bEnable);
+    m_xEditBtn->set_sensitive(bEnable);
+}
+
+std::vector<OUString> SvxListDialog::GetEntries() const
+{
+    int nCount = m_xList->n_children();
+    std::vector<OUString> aList;
+    aList.reserve(nCount);
+    for (int i = 0; i < nCount; ++i)
+        aList.push_back(m_xList->get_text(i));
+    return aList;
+}
+
+void SvxListDialog::SetEntries(std::vector<OUString> const& rEntries)
+{
+    m_xList->clear();
+    for (auto const& sEntry : rEntries)
+    {
+        m_xList->append_text(sEntry);
+    }
+    SelectionChanged();
+}
+
+void SvxListDialog::EditEntry()
+{
+    int nPos = m_xList->get_selected_index();
+    if (nPos == -1)
+        return;
+
+    OUString sOldText(m_xList->get_selected_text());
+    SvxNameDialog aNameDlg(m_xDialog.get(), sOldText, "blabla");
+
+    if (!aNameDlg.run())
+        return;
+    OUString sNewText = comphelper::string::strip(aNameDlg.GetName(), ' ');
+    if (!sNewText.isEmpty() && sNewText != sOldText)
+    {
+        m_xList->remove(nPos);
+        m_xList->insert_text(nPos, sNewText);
+        m_xList->select(nPos);
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/options/optaboutconfig.cxx 
b/cui/source/options/optaboutconfig.cxx
index 362af44cfd7d..bb002d55d0d1 100644
--- a/cui/source/options/optaboutconfig.cxx
+++ b/cui/source/options/optaboutconfig.cxx
@@ -245,6 +245,21 @@ void CuiAboutConfigTabPage::FillItemSet()
     }
 }
 
+namespace
+{
+OUString lcl_StringListToString(const uno::Sequence<OUString>& seq)
+{
+    OUStringBuffer sBuffer;
+    for (sal_Int32 i = 0; i != seq.getLength(); ++i)
+    {
+        if (i != 0)
+            sBuffer.append(",");
+        sBuffer.append(seq[i]);
+    }
+    return sBuffer.makeStringAndClear();
+}
+}
+
 void CuiAboutConfigTabPage::FillItems(const Reference<XNameAccess>& 
xNameAccess,
                                       const weld::TreeIter* pParentEntry, int 
lineage,
                                       bool bLoadAll)
@@ -484,15 +499,7 @@ void CuiAboutConfigTabPage::FillItems(const 
Reference<XNameAccess>& xNameAccess,
                 }
                 else if (sType == "oor:string-list")
                 {
-                    uno::Sequence<OUString> seq = 
aNode.get<uno::Sequence<OUString>>();
-                    for (sal_Int32 j = 0; j != seq.getLength(); ++j)
-                    {
-                        if (j != 0)
-                        {
-                            sValue.append(",");
-                        }
-                        sValue.append(seq[j]);
-                    }
+                    sValue = 
lcl_StringListToString(aNode.get<uno::Sequence<OUString>>());
                     sType = "string-list";
                 }
                 else if (sType == "oor:hexBinary-list")
@@ -778,13 +785,13 @@ IMPL_LINK_NOARG(CuiAboutConfigTabPage, StandardHdl_Impl, 
weld::Button&, void)
             }
             else if (sPropertyType == "string-list")
             {
-                SvxNameDialog aNameDialog(m_pParent, sDialogValue, 
sPropertyName);
-                aNameDialog.SetCheckNameHdl(LINK(this, CuiAboutConfigTabPage, 
ValidNameHdl));
-                if (aNameDialog.run() == RET_OK)
+                SvxListDialog aListDialog(m_pParent);
+                aListDialog.SetEntries(commaStringToSequence(sDialogValue));
+                if (aListDialog.run() == RET_OK)
                 {
-                    sDialogValue = aNameDialog.GetName();
-                    pProperty->Value
-                        <<= 
comphelper::containerToSequence(commaStringToSequence(sDialogValue));
+                    auto seq = 
comphelper::containerToSequence(aListDialog.GetEntries());
+                    sDialogValue = lcl_StringListToString(seq);
+                    pProperty->Value <<= seq;
                     bSaveChanges = true;
                 }
             }
diff --git a/cui/uiconfig/ui/listdialog.ui b/cui/uiconfig/ui/listdialog.ui
new file mode 100644
index 000000000000..18fffa18640d
--- /dev/null
+++ b/cui/uiconfig/ui/listdialog.ui
@@ -0,0 +1,231 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkTreeStore" id="liststore1">
+    <columns>
+      <!-- column-name text -->
+      <column type="gchararray"/>
+      <!-- column-name id -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+  <object class="GtkDialog" id="ListDialog">
+    <property name="can-focus">False</property>
+    <property name="border-width">6</property>
+    <property name="title" translatable="yes" 
context="listdialog|ListDialog">Edit List</property>
+    <property name="modal">True</property>
+    <property name="default-width">0</property>
+    <property name="default-height">0</property>
+    <property name="type-hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can-focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can-focus">False</property>
+            <property name="layout-style">end</property>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label" translatable="yes" 
context="stock">_OK</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="can-default">True</property>
+                <property name="has-default">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes" 
context="stock">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="help">
+                <property name="label" translatable="yes" 
context="stock">_Help</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack-type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="box1">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <!-- n-columns=2 n-rows=2 -->
+              <object class="GtkGrid" id="grid1">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="row-spacing">6</property>
+                <property name="column-spacing">6</property>
+                <child>
+                  <object class="GtkScrolledWindow">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="shadow-type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="assignlist">
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="model">liststore1</property>
+                        <property name="headers-visible">False</property>
+                        <property name="headers-clickable">False</property>
+                        <property name="search-column">0</property>
+                        <property name="show-expanders">False</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
+                        <child>
+                          <object class="GtkTreeViewColumn" 
id="treeviewcolumn1">
+                            <child>
+                              <object class="GtkCellRendererText" 
id="cellrenderertext1"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="box2">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkButton" id="addbtn">
+                        <property name="label" translatable="yes" 
context="listdialog|addbtn">_Add</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="use-underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="editbtn">
+                        <property name="label" translatable="yes" 
context="listdialog|editbtn">_Edit</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="valign">start</property>
+                        <property name="use-underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="removebtn">
+                        <property name="label" translatable="yes" 
context="listdialog|removebtn">_Remove</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="valign">start</property>
+                        <property name="use-underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="description">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">assignlist</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                    <property name="width">2</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">ok</action-widget>
+      <action-widget response="-6">cancel</action-widget>
+      <action-widget response="-11">help</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/include/cui/dlgname.hxx b/include/cui/dlgname.hxx
index 45d7d541ccce..eb3ac6b3ec17 100644
--- a/include/cui/dlgname.hxx
+++ b/include/cui/dlgname.hxx
@@ -146,4 +146,30 @@ public:
     bool IsDecorative() const { return m_xDecorativeCB->get_active(); }
 };
 
+/** Generic dialog to edit lists */
+class SvxListDialog : public weld::GenericDialogController
+{
+private:
+    std::unique_ptr<weld::TreeView> m_xList;
+    std::unique_ptr<weld::Button> m_xAddBtn;
+    std::unique_ptr<weld::Button> m_xRemoveBtn;
+    std::unique_ptr<weld::Button> m_xEditBtn;
+
+    DECL_LINK(SelectHdl_Impl, weld::TreeView&, void);
+    DECL_LINK(DblClickHdl_Impl, weld::TreeView&, bool);
+    DECL_LINK(AddHdl_Impl, weld::Button&, void);
+    DECL_LINK(RemoveHdl_Impl, weld::Button&, void);
+    DECL_LINK(EditHdl_Impl, weld::Button&, void);
+
+    void SelectionChanged();
+
+public:
+    explicit SvxListDialog(weld::Window* pParent);
+    virtual ~SvxListDialog() override;
+
+    std::vector<OUString> GetEntries() const;
+    void SetEntries(std::vector<OUString> const& rParams);
+    void EditEntry();
+};
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to