include/vcl/weld.hxx | 2 sw/source/ui/misc/bookmark.cxx | 134 ++++++++++++++++++++----------- sw/source/uibase/inc/bookmark.hxx | 23 +++-- sw/uiconfig/swriter/ui/insertbookmark.ui | 5 + vcl/source/app/salvtables.cxx | 13 +++ vcl/unx/gtk3/gtk3gtkinst.cxx | 21 ++++ 6 files changed, 146 insertions(+), 52 deletions(-)
New commits: commit 46cd78756f784ce81f8051e211d542f53112d5a3 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Thu Jun 20 20:59:00 2019 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Jun 21 09:55:35 2019 +0200 Resolves: tdf#126005 make bookmark treeview sortable and use iterators into the tree Change-Id: I38eb24d71cc089bf61baa221324a983c1eb782c9 Reviewed-on: https://gerrit.libreoffice.org/74470 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 449190f7a92c..7393131fea14 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -877,6 +877,8 @@ public: virtual void set_selection_mode(SelectionMode eMode) = 0; virtual int count_selected_rows() const = 0; + // remove the selected nodes + virtual void remove_selection() = 0; void set_toggle_columns_as_radio(const std::vector<int>& rCols) { m_aRadioIndexes = rCols; } diff --git a/sw/source/ui/misc/bookmark.cxx b/sw/source/ui/misc/bookmark.cxx index 11144f55b703..089c34c9b68d 100644 --- a/sw/source/ui/misc/bookmark.cxx +++ b/sw/source/ui/misc/bookmark.cxx @@ -94,16 +94,12 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, DeleteHdl, weld::Button&, void) { if (!ValidateBookmarks()) return; - std::vector<int> aSelectedRows(m_xBookmarksBox->get_selected_rows()); - if (aSelectedRows.empty()) - return; - std::sort(aSelectedRows.begin(), aSelectedRows.end()); - for (size_t i = aSelectedRows.size(); i; --i) - { - int nRow = aSelectedRows[i-1]; + int nSelectedRows(0); + + m_xBookmarksBox->selected_foreach([this, &nSelectedRows](weld::TreeIter& rEntry){ // remove from model - sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(nRow).toInt64()); + sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(rEntry).toInt64()); OUString sRemoved = pBookmark->GetName(); IDocumentMarkAccess* const pMarkAccess = rSh.getIDocumentMarkAccess(); pMarkAccess->deleteMark(pMarkAccess->findMark(sRemoved)); @@ -112,11 +108,20 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, DeleteHdl, weld::Button&, void) aReq.Done(); aTableBookmarks.erase(std::remove(aTableBookmarks.begin(), aTableBookmarks.end(), std::make_pair(pBookmark, sRemoved)), aTableBookmarks.end()); - // remove from BookmarkTable - m_xBookmarksBox->remove(nRow); - } - m_xBookmarksBox->unselect_all(); - m_xEditBox->set_text(""); + + ++nSelectedRows; + + return false; + }); + + if (!nSelectedRows) + return; + + // remove from BookmarkTable + m_xBookmarksBox->remove_selection(); + + ValidateBookmarks(); + m_xDeleteBtn->set_sensitive(false); m_xGotoBtn->set_sensitive(false); m_xRenameBtn->set_sensitive(false); @@ -143,23 +148,21 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, SelectionChangedHdl, weld::TreeView&, void) return; OUStringBuffer sEditBoxText; - - std::vector<int> aSelectedRows(m_xBookmarksBox->get_selected_rows()); - std::sort(aSelectedRows.begin(), aSelectedRows.end()); - for (size_t i = aSelectedRows.size(); i; --i) - { - int nRow = aSelectedRows[i-1]; - sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(nRow).toInt64()); + int nSelectedRows = 0; + m_xBookmarksBox->selected_foreach([this, &sEditBoxText, &nSelectedRows](weld::TreeIter& rEntry){ + sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(rEntry).toInt64()); const OUString& sEntryName = pBookmark->GetName(); - sEditBoxText.append(sEntryName); - if (i > 1) + if (!sEditBoxText.isEmpty()) sEditBoxText.append(";"); - } - if (!aSelectedRows.empty()) + sEditBoxText.append(sEntryName); + ++nSelectedRows; + return false; + }); + if (nSelectedRows) { m_xInsertBtn->set_sensitive(false); - m_xGotoBtn->set_sensitive(aSelectedRows.size() == 1); - m_xRenameBtn->set_sensitive(aSelectedRows.size() == 1); + m_xGotoBtn->set_sensitive(nSelectedRows == 1); + m_xRenameBtn->set_sensitive(nSelectedRows == 1); m_xDeleteBtn->set_sensitive(true); m_xEditBox->set_text(sEditBoxText.makeStringAndClear()); } @@ -176,11 +179,11 @@ IMPL_LINK_NOARG(SwInsertBookmarkDlg, RenameHdl, weld::Button&, void) { if (!ValidateBookmarks()) return; - int nSelected = m_xBookmarksBox->get_selected_index(); - if (nSelected == -1) + auto xSelected = m_xBookmarksBox->get_selected(); + if (!xSelected) return; - sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(nSelected).toInt64()); + sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(*xSelected).toInt64()); uno::Reference<frame::XModel> xModel = rSh.GetView().GetDocShell()->GetBaseModel(); uno::Reference<text::XBookmarksSupplier> xBkms(xModel, uno::UNO_QUERY); uno::Reference<container::XNameAccess> xNameAccess = xBkms->getBookmarks(); @@ -228,11 +231,11 @@ void SwInsertBookmarkDlg::GotoSelectedBookmark() return; // if no entries selected we can't jump anywhere // shouldn't be needed as we disable GoTo button when jump is not possible - int nSelected = m_xBookmarksBox->get_selected_index(); - if (nSelected == -1) + auto xSelected = m_xBookmarksBox->get_selected(); + if (!xSelected) return; - sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(nSelected).toInt64()); + sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xBookmarksBox->get_id(*xSelected).toInt64()); rSh.EnterStdMode(); rSh.GotoMark(pBookmark); @@ -297,6 +300,7 @@ SwInsertBookmarkDlg::SwInsertBookmarkDlg(weld::Window* pParent, SwWrtShell& rS, , rSh(rS) , rReq(rRequest) , m_nLastBookmarksCount(0) + , m_bSorted(false) , m_xEditBox(m_xBuilder->weld_entry("name")) , m_xInsertBtn(m_xBuilder->weld_button("insert")) , m_xDeleteBtn(m_xBuilder->weld_button("delete")) @@ -309,6 +313,7 @@ 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_xEditBox->connect_changed(LINK(this, SwInsertBookmarkDlg, ModifyHdl)); m_xInsertBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, InsertHdl)); m_xDeleteBtn->connect_clicked(LINK(this, SwInsertBookmarkDlg, DeleteHdl)); @@ -328,6 +333,35 @@ SwInsertBookmarkDlg::SwInsertBookmarkDlg(weld::Window* pParent, SwWrtShell& rS, sRemoveWarning = SwResId(STR_REMOVE_WARNING); } +IMPL_LINK(SwInsertBookmarkDlg, HeaderBarClick, int, nColumn, void) +{ + if (!m_bSorted) + { + m_xBookmarksBox->make_sorted(); + m_bSorted = true; + } + + bool bSortAtoZ = m_xBookmarksBox->get_sort_order(); + + //set new arrow positions in headerbar + if (nColumn == m_xBookmarksBox->get_sort_column()) + { + bSortAtoZ = !bSortAtoZ; + m_xBookmarksBox->set_sort_order(bSortAtoZ); + } + else + { + m_xBookmarksBox->set_sort_indicator(TRISTATE_INDET, m_xBookmarksBox->get_sort_column()); + m_xBookmarksBox->set_sort_column(nColumn); + } + + if (nColumn != -1) + { + //sort lists + m_xBookmarksBox->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn); + } +} + SwInsertBookmarkDlg::~SwInsertBookmarkDlg() { } @@ -345,6 +379,14 @@ BookmarkTable::BookmarkTable(std::unique_ptr<weld::TreeView> xControl) m_xControl->set_selection_mode(SelectionMode::Multiple); } +std::unique_ptr<weld::TreeIter> BookmarkTable::get_selected() const +{ + std::unique_ptr<weld::TreeIter> xIter(m_xControl->make_iterator()); + if (!m_xControl->get_selected(xIter.get())) + xIter.reset(); + return xIter; +} + void BookmarkTable::InsertBookmark(sw::mark::IMark* pMark) { sw::mark::IBookmark* pBookmark = dynamic_cast<sw::mark::IBookmark*>(pMark); @@ -393,34 +435,36 @@ void BookmarkTable::InsertBookmark(sw::mark::IMark* pMark) m_xControl->set_text(nRow, sHideCondition, 4); } -int BookmarkTable::GetRowByBookmarkName(const OUString& sName) +std::unique_ptr<weld::TreeIter> BookmarkTable::GetRowByBookmarkName(const OUString& sName) { - for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i) - { - sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xControl->get_id(i).toInt64()); + std::unique_ptr<weld::TreeIter> xRet; + m_xControl->all_foreach([this, &sName, &xRet](weld::TreeIter& rEntry){ + sw::mark::IMark* pBookmark = reinterpret_cast<sw::mark::IMark*>(m_xControl->get_id(rEntry).toInt64()); if (pBookmark->GetName() == sName) { - return i; + xRet = m_xControl->make_iterator(&rEntry); + return true; } - } - return -1; + return false; + }); + return xRet; } sw::mark::IMark* BookmarkTable::GetBookmarkByName(const OUString& sName) { - int nEntry = GetRowByBookmarkName(sName); - if (nEntry == -1) + auto xEntry = GetRowByBookmarkName(sName); + if (!xEntry) return nullptr; - return reinterpret_cast<sw::mark::IMark*>(m_xControl->get_id(nEntry).toInt64()); + return reinterpret_cast<sw::mark::IMark*>(m_xControl->get_id(*xEntry).toInt64()); } void BookmarkTable::SelectByName(const OUString& sName) { - int nEntry = GetRowByBookmarkName(sName); - if (nEntry == -1) + auto xEntry = GetRowByBookmarkName(sName); + if (!xEntry) return; - select(nEntry); + select(*xEntry); } OUString BookmarkTable::GetNameProposal() diff --git a/sw/source/uibase/inc/bookmark.hxx b/sw/source/uibase/inc/bookmark.hxx index 8dcc15d53eda..8f51602dbfbb 100644 --- a/sw/source/uibase/inc/bookmark.hxx +++ b/sw/source/uibase/inc/bookmark.hxx @@ -32,7 +32,7 @@ class SfxRequest; class BookmarkTable { std::unique_ptr<weld::TreeView> m_xControl; - int GetRowByBookmarkName(const OUString& sName); + std::unique_ptr<weld::TreeIter> GetRowByBookmarkName(const OUString& sName); public: BookmarkTable(std::unique_ptr<weld::TreeView> xControl); void InsertBookmark(sw::mark::IMark* pMark); @@ -42,16 +42,23 @@ public: void unselect_all() { m_xControl->unselect_all(); } bool has_focus() const { return m_xControl->has_focus(); } - int n_children() const { return m_xControl->n_children(); } - int get_selected_index() const { return m_xControl->get_selected_index(); } - std::vector<int> get_selected_rows() const { return m_xControl->get_selected_rows(); } + std::unique_ptr<weld::TreeIter> get_selected() const; void clear() { m_xControl->clear(); } - void remove(int nRow) { m_xControl->remove(nRow); } - void select(int nRow) { m_xControl->select(nRow); } - OUString get_id(int nRow) const { return m_xControl->get_id(nRow); } + void remove(const weld::TreeIter& rIter) { m_xControl->remove(rIter); } + void select(const weld::TreeIter& rIter) { m_xControl->select(rIter); } + void remove_selection() { m_xControl->remove_selection(); } + 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); } void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xControl->connect_changed(rLink); } void connect_row_activated(const Link<weld::TreeView&, void>& rLink) { m_xControl->connect_row_activated(rLink); } + void connect_column_clicked(const Link<int, void>& rLink) { m_xControl->connect_column_clicked(rLink); } + 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); } + int get_sort_column() const { return m_xControl->get_sort_column(); } + void set_sort_column(int nColumn) { m_xControl->set_sort_column(nColumn); } static const OUString aForbiddenChars; static const char cSeparator; @@ -64,6 +71,7 @@ class SwInsertBookmarkDlg : public SfxDialogController SfxRequest& rReq; std::vector<std::pair<sw::mark::IMark*, OUString>> aTableBookmarks; sal_Int32 m_nLastBookmarksCount; + bool m_bSorted; std::unique_ptr<weld::Entry> m_xEditBox; std::unique_ptr<weld::Button> m_xInsertBtn; @@ -82,6 +90,7 @@ class SwInsertBookmarkDlg : public SfxDialogController DECL_LINK(GotoHdl, weld::Button&, void); DECL_LINK(SelectionChangedHdl, weld::TreeView&, void); DECL_LINK(DoubleClickHdl, weld::TreeView&, void); + DECL_LINK(HeaderBarClick, int, void); DECL_LINK(ChangeHideHdl, weld::ToggleButton&, void); // Fill table with bookmarks diff --git a/sw/uiconfig/swriter/ui/insertbookmark.ui b/sw/uiconfig/swriter/ui/insertbookmark.ui index 0aa5af987570..bc9c3896f1d3 100644 --- a/sw/uiconfig/swriter/ui/insertbookmark.ui +++ b/sw/uiconfig/swriter/ui/insertbookmark.ui @@ -196,6 +196,7 @@ <property name="resizable">True</property> <property name="spacing">6</property> <property name="title" translatable="yes" context="insertbookmark|page">Page</property> + <property name="clickable">True</property> <child> <object class="GtkCellRendererText" id="cellrenderer0"/> <attributes> @@ -209,6 +210,7 @@ <property name="resizable">True</property> <property name="spacing">6</property> <property name="title" translatable="yes" context="insertbookmark|name">Name</property> + <property name="clickable">True</property> <child> <object class="GtkCellRendererText" id="cellrenderer1"/> <attributes> @@ -222,6 +224,7 @@ <property name="resizable">True</property> <property name="spacing">6</property> <property name="title" translatable="yes" context="insertbookmark|text">Text</property> + <property name="clickable">True</property> <child> <object class="GtkCellRendererText" id="cellrenderer2"/> <attributes> @@ -235,6 +238,7 @@ <property name="resizable">True</property> <property name="spacing">6</property> <property name="title" translatable="yes" context="insertbookmark|hidden">Hidden</property> + <property name="clickable">True</property> <child> <object class="GtkCellRendererText" id="cellrenderer3"/> <attributes> @@ -248,6 +252,7 @@ <property name="resizable">True</property> <property name="spacing">6</property> <property name="title" translatable="yes" context="insertbookmark|condition">Condition</property> + <property name="clickable">True</property> <child> <object class="GtkCellRendererText" id="cellrenderer4"/> <attributes> diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 33aea3fe1419..fadd5607c365 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -3590,6 +3590,19 @@ public: m_xTreeView->SetScrolledHdl(LINK(this, SalInstanceTreeView, VisibleRangeChangedHdl)); } + virtual void remove_selection() override + { + disable_notify_events(); + SvTreeListEntry* pSelected = m_xTreeView->FirstSelected(); + while (pSelected) + { + SvTreeListEntry* pNextSelected = m_xTreeView->NextSelected(pSelected); + m_xTreeView->RemoveEntry(pSelected); + pSelected = pNextSelected; + } + enable_notify_events(); + } + virtual bool is_selected(const weld::TreeIter& rIter) const override { const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index bc8f69c9d05d..06f49b7aefc1 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -7704,6 +7704,27 @@ public: enable_notify_events(); } + virtual void remove_selection() override + { + disable_notify_events(); + + std::vector<GtkTreeIter> aIters; + GtkTreeModel* pModel; + GList* pList = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(m_pTreeView), &pModel); + for (GList* pItem = g_list_first(pList); pItem; pItem = g_list_next(pItem)) + { + GtkTreePath* path = static_cast<GtkTreePath*>(pItem->data); + aIters.emplace_back(); + gtk_tree_model_get_iter(pModel, &aIters.back(), path); + } + g_list_free_full(pList, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free)); + + for (auto& iter : aIters) + gtk_tree_store_remove(m_pTreeStore, &iter); + + enable_notify_events(); + } + virtual void select(const weld::TreeIter& rIter) override { assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen"); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits