sw/source/ui/misc/bookmark.cxx           |   99 +++++++++++++++++++++++--------
 sw/source/uibase/inc/bookmark.hxx        |   11 +++
 sw/uiconfig/swriter/ui/insertbookmark.ui |   20 +++++-
 3 files changed, 102 insertions(+), 28 deletions(-)

New commits:
commit aa6ec3f79607478213272283b7eb17ec2116173c
Author:     Michael Stahl <[email protected]>
AuthorDate: Thu Jul 21 19:31:45 2022 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Jul 26 20:15:37 2022 +0200

    tdf#150017 sw: allow editing bookmark text in Insert->Bookmarks dialog
    
    Enable editing the text of the bookmark if it's "short" enough and
    doesn't span multiple paragraphs; Replace the text when finished.
    
    This will delete any footnotes or text fields in the bookmark text,
    which isn't ideal but there's Undo.
    
    Double-clicking the column via property "editable" only seems to work
    with native GTK widgets, so provide an additional "Edit Text" button to
    start the editing.  The button requires commit
    fe38553aef2121f358fb58e450ec69314aad851e to edit the correct column
    with VCL widgets, and it doesn't work yet with GTK widgets (but with GTK
    double-clicking works).
    
    Change-Id: If9e8a148b039889924e4870b2e9bbe977c977ce9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137355
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <[email protected]>

diff --git a/sw/source/ui/misc/bookmark.cxx b/sw/source/ui/misc/bookmark.cxx
index 473c6a99b49f..fe63d4c133ca 100644
--- a/sw/source/ui/misc/bookmark.cxx
+++ b/sw/source/ui/misc/bookmark.cxx
@@ -88,6 +88,7 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, ModifyHdl, weld::Entry&, 
void)
     // allow to delete only if all bookmarks are recognized
     m_xDeleteBtn->set_sensitive(nEntries > 0 && nSelectedEntries == nEntries 
&& !m_bAreProtected);
     m_xGotoBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 1);
+    m_xEditTextBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 1);
     m_xRenameBtn->set_sensitive(nEntries == 1 && nSelectedEntries == 1 && 
!m_bAreProtected);
 }
 
@@ -128,6 +129,7 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, DeleteHdl, 
weld::Button&, void)
 
     m_xDeleteBtn->set_sensitive(false);
     m_xGotoBtn->set_sensitive(false);
+    m_xEditTextBtn->set_sensitive(false);
     m_xRenameBtn->set_sensitive(false);
     m_xInsertBtn->set_sensitive(false);
 }
@@ -166,6 +168,7 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, SelectionChangedHdl, 
weld::TreeView&, void)
     {
         m_xInsertBtn->set_sensitive(false);
         m_xGotoBtn->set_sensitive(nSelectedRows == 1);
+        m_xEditTextBtn->set_sensitive(nSelectedRows == 1);
         m_xRenameBtn->set_sensitive(nSelectedRows == 1 && !m_bAreProtected);
         m_xDeleteBtn->set_sensitive(!m_bAreProtected);
         m_xEditBox->set_text(sEditBoxText.makeStringAndClear());
@@ -174,11 +177,23 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, SelectionChangedHdl, 
weld::TreeView&, void)
     {
         m_xInsertBtn->set_sensitive(!m_bAreProtected);
         m_xGotoBtn->set_sensitive(false);
+        m_xEditTextBtn->set_sensitive(false);
         m_xRenameBtn->set_sensitive(false);
         m_xDeleteBtn->set_sensitive(false);
     }
 }
 
+IMPL_LINK_NOARG(SwInsertBookmarkDlg, EditTextHdl, weld::Button&, void)
+{
+    if (!ValidateBookmarks())
+        return;
+    auto pSelected = m_xBookmarksBox->get_selected();
+    if (!pSelected)
+        return;
+
+    m_xBookmarksBox->start_editing(*pSelected);
+}
+
 IMPL_LINK_NOARG(SwInsertBookmarkDlg, RenameHdl, weld::Button&, void)
 {
     if (!ValidateBookmarks())
@@ -207,6 +222,7 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, RenameHdl, 
weld::Button&, void)
         ValidateBookmarks();
         m_xDeleteBtn->set_sensitive(false);
         m_xGotoBtn->set_sensitive(false);
+        m_xEditTextBtn->set_sensitive(false);
         m_xRenameBtn->set_sensitive(false);
         m_xInsertBtn->set_sensitive(false);
     }
@@ -229,6 +245,45 @@ IMPL_LINK(SwInsertBookmarkDlg, ChangeHideHdl, 
weld::Toggleable&, rBox, void)
     m_xConditionFT->set_sensitive(bHide);
 }
 
+IMPL_LINK(SwInsertBookmarkDlg, EditingHdl, weld::TreeIter const&, rIter, bool)
+{
+    sw::mark::IMark const* const pBookmark(
+        weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(rIter)));
+    assert(pBookmark);
+    return pBookmark->IsExpanded()
+           && pBookmark->GetMarkPos().nNode == 
pBookmark->GetOtherMarkPos().nNode
+           && !m_xBookmarksBox->get_text(rIter).endsWith(u"…");
+}
+
+IMPL_LINK(SwInsertBookmarkDlg, EditedHdl, weld::TreeView::iter_string const&, 
rIterString, bool)
+{
+    sw::mark::IMark const* const pBookmark(
+        
weld::fromId<sw::mark::IMark*>(m_xBookmarksBox->get_id(rIterString.first)));
+    assert(pBookmark);
+    bool bRet(false);
+    if (pBookmark->GetMarkPos() != pBookmark->GetOtherMarkPos())
+    {
+        if (pBookmark->GetMarkPos().nNode != 
pBookmark->GetOtherMarkPos().nNode)
+        {
+            return false; // don't allow editing if it spans multiple nodes
+        }
+        rSh.Push();
+        rSh.GotoMark(pBookmark);
+        // GetSelText only works for 1 paragraph, but it's checked above
+        if (rSh.GetSelText() != rIterString.second)
+        {
+            bRet = rSh.Replace(rIterString.second, false);
+        }
+        rSh.Pop(SwEditShell::PopMode::DeleteCurrent);
+    }
+    else if (pBookmark->IsExpanded() && !rIterString.second.isEmpty())
+    { // SwEditShell::Replace does nothing for empty selection
+        rSh.Insert(rIterString.second);
+        bRet = true;
+    }
+    return bRet;
+}
+
 void SwInsertBookmarkDlg::GotoSelectedBookmark()
 {
     if (!ValidateBookmarks())
@@ -293,7 +348,7 @@ void SwInsertBookmarkDlg::PopulateTable()
     {
         if (IDocumentMarkAccess::MarkType::BOOKMARK == 
IDocumentMarkAccess::GetType(**ppBookmark))
         {
-            m_xBookmarksBox->InsertBookmark(*ppBookmark);
+            m_xBookmarksBox->InsertBookmark(rSh, *ppBookmark);
             aTableBookmarks.emplace_back(*ppBookmark, 
(*ppBookmark)->GetName());
         }
     }
@@ -309,6 +364,7 @@ SwInsertBookmarkDlg::SwInsertBookmarkDlg(weld::Window* 
pParent, SwWrtShell& rS)
     , m_xInsertBtn(m_xBuilder->weld_button("insert"))
     , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
     , m_xGotoBtn(m_xBuilder->weld_button("goto"))
+    , m_xEditTextBtn(m_xBuilder->weld_button("edittext"))
     , m_xRenameBtn(m_xBuilder->weld_button("rename"))
     , m_xHideCB(m_xBuilder->weld_check_button("hide"))
     , m_xConditionFT(m_xBuilder->weld_label("condlabel"))
@@ -319,17 +375,24 @@ SwInsertBookmarkDlg::SwInsertBookmarkDlg(weld::Window* 
pParent, SwWrtShell& rS)
     m_xBookmarksBox->connect_changed(LINK(this, SwInsertBookmarkDlg, 
SelectionChangedHdl));
     m_xBookmarksBox->connect_row_activated(LINK(this, SwInsertBookmarkDlg, 
DoubleClickHdl));
     m_xBookmarksBox->connect_column_clicked(LINK(this, SwInsertBookmarkDlg, 
HeaderBarClick));
+    m_xBookmarksBox->connect_editing(LINK(this, SwInsertBookmarkDlg, 
EditingHdl),
+                                     LINK(this, SwInsertBookmarkDlg, 
EditedHdl));
     m_xEditBox->connect_changed(LINK(this, SwInsertBookmarkDlg, ModifyHdl));
     m_xInsertBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, InsertHdl));
     m_xDeleteBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, DeleteHdl));
     m_xGotoBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, GotoHdl));
+    m_xEditTextBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, 
EditTextHdl));
     m_xRenameBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, RenameHdl));
     m_xHideCB->connect_toggled(LINK(this, SwInsertBookmarkDlg, ChangeHideHdl));
 
     m_xDeleteBtn->set_sensitive(false);
     m_xGotoBtn->set_sensitive(false);
+    m_xEditTextBtn->set_sensitive(false);
     m_xRenameBtn->set_sensitive(false);
 
+    // select 3rd colum, otherwise it'll pick 1st one FIXME doesn't work with 
gtk?
+    m_xBookmarksBox->set_column_editables({ false, false, true, false, false 
});
+
     PopulateTable();
 
     m_xEditBox->set_text(m_xBookmarksBox->GetNameProposal());
@@ -413,41 +476,27 @@ std::unique_ptr<weld::TreeIter> 
BookmarkTable::get_selected() const
     return xIter;
 }
 
-void BookmarkTable::InsertBookmark(sw::mark::IMark* pMark)
+void BookmarkTable::InsertBookmark(SwWrtShell& rSh, sw::mark::IMark* const 
pMark)
 {
     sw::mark::IBookmark* pBookmark = dynamic_cast<sw::mark::IBookmark*>(pMark);
     assert(pBookmark);
 
-    OUString sBookmarkNodeText = 
pBookmark->GetMarkStart().nNode.GetNode().GetTextNode()->GetText();
-    sal_Int32 nBookmarkNodeTextPos = 
pBookmark->GetMarkStart().nContent.GetIndex();
-    sal_Int32 nBookmarkTextLen = 0;
-    bool bPulledAll = false;
-    bool bPulling = false;
+    OUString sBookmarkNodeText;
     static const sal_Int32 nMaxTextLen = 50;
 
     if (pBookmark->IsExpanded())
     {
-        nBookmarkTextLen = pBookmark->GetMarkEnd().nContent.GetIndex() - 
nBookmarkNodeTextPos;
+        rSh.Push();
+        rSh.GotoMark(pBookmark);
+        rSh.GetSelectedText(sBookmarkNodeText, ParaBreakType::ToBlank);
+        rSh.Pop(SwEditShell::PopMode::DeleteCurrent);
     }
-    else
+    if (nMaxTextLen < sBookmarkNodeText.getLength())
     {
-        if (nBookmarkNodeTextPos == sBookmarkNodeText.getLength()) // no text 
after bookmark
-        {
-            nBookmarkNodeTextPos = std::max<sal_Int32>(0, nBookmarkNodeTextPos 
- nMaxTextLen);
-            bPulling = true;
-            if (nBookmarkNodeTextPos == 0)
-                bPulledAll = true;
-        }
-        nBookmarkTextLen = sBookmarkNodeText.getLength() - 
nBookmarkNodeTextPos;
+        sBookmarkNodeText = sBookmarkNodeText.subView(0, nMaxTextLen);
+        ;
+        sBookmarkNodeText += u"…";
     }
-    bool bExceedsLength = nBookmarkTextLen > nMaxTextLen;
-    nBookmarkTextLen = std::min<sal_Int32>(nMaxTextLen, nBookmarkTextLen);
-    sBookmarkNodeText
-        = o3tl::trim(sBookmarkNodeText.subView(nBookmarkNodeTextPos, 
nBookmarkTextLen));
-    if (bExceedsLength)
-        sBookmarkNodeText += "...";
-    else if (bPulling && !bPulledAll)
-        sBookmarkNodeText = "..." + sBookmarkNodeText;
 
     const OUString& sHideCondition = pBookmark->GetHideCondition();
     OUString sHidden = SwResId(STR_BOOKMARK_NO);
diff --git a/sw/source/uibase/inc/bookmark.hxx 
b/sw/source/uibase/inc/bookmark.hxx
index 6441a5f16f63..36f83f3a86e9 100644
--- a/sw/source/uibase/inc/bookmark.hxx
+++ b/sw/source/uibase/inc/bookmark.hxx
@@ -32,7 +32,7 @@ class BookmarkTable
     std::unique_ptr<weld::TreeIter> GetRowByBookmarkName(const OUString& 
sName);
 public:
     BookmarkTable(std::unique_ptr<weld::TreeView> xControl);
-    void                InsertBookmark(sw::mark::IMark* pMark);
+    void                InsertBookmark(SwWrtShell & rSh, sw::mark::IMark* 
pMark);
     void                SelectByName(const OUString& sName);
     sw::mark::IMark*    GetBookmarkByName(const OUString& sName);
     OUString            GetNameProposal() const;
@@ -43,6 +43,7 @@ public:
     void                clear() { m_xControl->clear(); }
     void                select(const weld::TreeIter& rIter) { 
m_xControl->select(rIter); }
     void                remove_selection() { m_xControl->remove_selection(); }
+    OUString            get_text(const weld::TreeIter& rIter) const { return 
m_xControl->get_text(rIter, 2); }
     OUString            get_id(const weld::TreeIter& rIter) const { return 
m_xControl->get_id(rIter); }
     void set_sort_indicator(TriState eState, int nColumn = -1) { 
m_xControl->set_sort_indicator(eState, nColumn); }
     void selected_foreach(const std::function<bool(weld::TreeIter&)>& func) { 
m_xControl->selected_foreach(func); }
@@ -50,6 +51,10 @@ public:
     void connect_changed(const Link<weld::TreeView&, void>& rLink) { 
m_xControl->connect_changed(rLink); }
     void connect_row_activated(const Link<weld::TreeView&, bool>& rLink) { 
m_xControl->connect_row_activated(rLink); }
     void connect_column_clicked(const Link<int, void>& rLink) { 
m_xControl->connect_column_clicked(rLink); }
+    void connect_editing(const Link<const weld::TreeIter&, bool>& rStartLink,
+         const Link<const weld::TreeView::iter_string&, bool>& rEndLink) { 
m_xControl->connect_editing(rStartLink, rEndLink); }
+    void set_column_editables(::std::vector<bool> const& rEditables) { 
m_xControl->set_column_editables(rEditables); }
+    void start_editing(weld::TreeIter const& rIter) { 
m_xControl->start_editing(rIter); }
     void make_sorted() { m_xControl->make_sorted(); }
     bool get_sort_order() const { return m_xControl->get_sort_order(); }
     void set_sort_order(bool bAscending) { 
m_xControl->set_sort_order(bAscending); }
@@ -72,6 +77,7 @@ class SwInsertBookmarkDlg final : public SfxDialogController
     std::unique_ptr<weld::Button> m_xInsertBtn;
     std::unique_ptr<weld::Button> m_xDeleteBtn;
     std::unique_ptr<weld::Button> m_xGotoBtn;
+    std::unique_ptr<weld::Button> m_xEditTextBtn;
     std::unique_ptr<weld::Button> m_xRenameBtn;
     std::unique_ptr<weld::CheckButton> m_xHideCB;
     std::unique_ptr<weld::Label> m_xConditionFT;
@@ -82,12 +88,15 @@ class SwInsertBookmarkDlg final : public SfxDialogController
     DECL_LINK(ModifyHdl, weld::Entry&, void);
     DECL_LINK(InsertHdl, weld::Button&, void);
     DECL_LINK(DeleteHdl, weld::Button&, void);
+    DECL_LINK(EditTextHdl, weld::Button&, void);
     DECL_LINK(RenameHdl, weld::Button&, void);
     DECL_LINK(GotoHdl, weld::Button&, void);
     DECL_LINK(SelectionChangedHdl, weld::TreeView&, void);
     DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
     DECL_LINK(HeaderBarClick, int, void);
     DECL_LINK(ChangeHideHdl, weld::Toggleable&, void);
+    DECL_LINK(EditingHdl, weld::TreeIter const&, bool);
+    DECL_LINK(EditedHdl, weld::TreeView::iter_string const&, bool);
 
     // Fill table with bookmarks
     void PopulateTable();
diff --git a/sw/uiconfig/swriter/ui/insertbookmark.ui 
b/sw/uiconfig/swriter/ui/insertbookmark.ui
index 0cd5225733f0..0a183c4e1f51 100644
--- a/sw/uiconfig/swriter/ui/insertbookmark.ui
+++ b/sw/uiconfig/swriter/ui/insertbookmark.ui
@@ -267,7 +267,9 @@
                         <property name="title" translatable="yes" 
context="insertbookmark|text">Text</property>
                         <property name="clickable">True</property>
                         <child>
-                          <object class="GtkCellRendererText" 
id="cellrenderer2"/>
+                          <object class="GtkCellRendererText" 
id="cellrenderer2">
+                            <property name="editable">True</property>
+                          </object>
                           <attributes>
                             <attribute name="text">2</attribute>
                           </attributes>
@@ -363,6 +365,20 @@
                 <property name="position">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkButton" id="edittext">
+                <property name="label" translatable="yes" 
context="insertbookmark|edittext">Edit Text</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="pack-type">end</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
             <child>
               <object class="GtkButton" id="rename">
                 <property name="label" translatable="yes" 
context="insertbookmark|rename">Rename</property>
@@ -374,7 +390,7 @@
                 <property name="expand">False</property>
                 <property name="fill">False</property>
                 <property name="pack-type">end</property>
-                <property name="position">2</property>
+                <property name="position">3</property>
               </packing>
             </child>
           </object>

Reply via email to