include/o3tl/sorted_vector.hxx | 5 sc/qa/uitest/autofilter/autofilter.py | 2 sc/qa/uitest/autofilter/autofilterBugs.py | 2 sc/qa/uitest/autofilter/tdf97340.py | 9 sc/source/ui/cctrl/checklistmenu.cxx | 3 vcl/unx/gtk3/gtk3gtkinst.cxx | 690 +++++++++++++++++++----------- 6 files changed, 467 insertions(+), 244 deletions(-)
New commits: commit 7364cbbdea110d3c7b1656290b4c0a746a95cfe4 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Sep 18 20:52:16 2020 +0100 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Mon Nov 30 18:21:40 2020 +0100 tdf#136559 We can get a performance boost from using a ListStore instead of a TreeStore if we only need a list see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2693 Change-Id: I03d03f2364ccc75b87d3f7c31d21ac9993fb384b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103036 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106878 Tested-by: Szymon Kłos <szymon.k...@collabora.com> Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/include/o3tl/sorted_vector.hxx b/include/o3tl/sorted_vector.hxx index 088f5a2aa214..28ef75817fa7 100644 --- a/include/o3tl/sorted_vector.hxx +++ b/include/o3tl/sorted_vector.hxx @@ -198,6 +198,11 @@ public: return (ret.second) ? ret.first : m_vector.end(); } + size_type count(const Value& v) const + { + return find(v) != end() ? 1 : 0; + } + bool operator==(const sorted_vector & other) const { return m_vector == other.m_vector; diff --git a/sc/qa/uitest/autofilter/autofilter.py b/sc/qa/uitest/autofilter/autofilter.py index e1aea9c1e303..47b94a6807bc 100644 --- a/sc/qa/uitest/autofilter/autofilter.py +++ b/sc/qa/uitest/autofilter/autofilter.py @@ -33,7 +33,7 @@ class AutofilterTest(UITestCase): xFloatWindow = self.xUITest.getFloatWindow() xCheckListMenu = xFloatWindow.getChild("check_list_menu") - xTreeList = xCheckListMenu.getChild("check_list_box") + xTreeList = xCheckListMenu.getChild("check_tree_box") xFirstEntry = xTreeList.getChild("0") xFirstEntry.executeAction("CLICK", tuple()) diff --git a/sc/qa/uitest/autofilter/autofilterBugs.py b/sc/qa/uitest/autofilter/autofilterBugs.py index e216d7994d8c..460d4d86d19d 100644 --- a/sc/qa/uitest/autofilter/autofilterBugs.py +++ b/sc/qa/uitest/autofilter/autofilterBugs.py @@ -138,7 +138,7 @@ class autofilter(UITestCase): xGridWindow.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() - xTreeList = xFloatWindow.getChild("check_list_box") + xTreeList = xFloatWindow.getChild("check_tree_box") xFirstEntry = xTreeList.getChild("0") self.assertEqual(get_state_as_dict(xFirstEntry)["Text"], "2014") diff --git a/sc/qa/uitest/autofilter/tdf97340.py b/sc/qa/uitest/autofilter/tdf97340.py index 237ed71178ba..272883f1829d 100644 --- a/sc/qa/uitest/autofilter/tdf97340.py +++ b/sc/qa/uitest/autofilter/tdf97340.py @@ -30,9 +30,16 @@ class tdf97340(UITestCase): gridwin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) xFloatWindow = self.xUITest.getFloatWindow() + + xCheckListMenu = xFloatWindow.getChild("check_list_menu") + xTreeList = xCheckListMenu.getChild("check_tree_box") + self.assertEqual(2, len(xTreeList.getChildren())) + self.assertEqual("2016", get_state_as_dict(xTreeList.getChild('0'))['Text']) + self.assertEqual("2017", get_state_as_dict(xTreeList.getChild('1'))['Text']) + xsearchEdit = xFloatWindow.getChild("search_edit") xsearchEdit.executeAction("TYPE", mkPropertyValues({"TEXT":" "})) xsearchEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "BACKSPACE"})) self.ui_test.close_doc() -# vim: set shiftwidth=4 softtabstop=4 expandtab: \ No newline at end of file +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index 8c9317f9d5ab..b905d5a7bba1 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -416,7 +416,7 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v ScDocument* pDoc, bool bCanHaveSubMenu, bool bHasDates, int nWidth) : mxFrame(pParent) - , mxBuilder(Application::CreateInterimBuilder(pContainer, "modules/scalc/ui/filterdropdown.ui", false)) + , mxBuilder(Application::CreateInterimBuilder(pContainer, "modules/scalc/ui/filterdropdown.ui")) , mxContainer(mxBuilder->weld_container("FilterDropDown")) , mxMenu(mxBuilder->weld_tree_view("menu")) , mxScratchIter(mxMenu->make_iterator()) @@ -424,6 +424,7 @@ ScCheckListMenuControl::ScCheckListMenuControl(ScCheckListMenuWindow* pParent, v , mxBox(mxBuilder->weld_widget("box")) , mxListChecks(mxBuilder->weld_tree_view("check_list_box")) , mxTreeChecks(mxBuilder->weld_tree_view("check_tree_box")) + , mpChecks(mxTreeChecks.get()) , mxChkToggleAll(mxBuilder->weld_check_button("toggle_all")) , mxBtnSelectSingle(mxBuilder->weld_button("select_current")) , mxBtnUnselectSingle(mxBuilder->weld_button("unselect_current")) diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index be8f5289c614..c3e019b1d048 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -84,6 +84,7 @@ #include <strings.hrc> #include <window.h> #include <numeric> +#include <o3tl/sorted_vector.hxx> using namespace com::sun::star; using namespace com::sun::star::uno; @@ -7994,15 +7995,230 @@ struct GtkInstanceTreeIter : public weld::TreeIter GtkTreeIter iter; }; +namespace { + class GtkInstanceTreeView; static GtkInstanceTreeView* g_DragSource; +struct CompareGtkTreePath +{ + bool operator()(const GtkTreePath* lhs, const GtkTreePath* rhs) const + { + return gtk_tree_path_compare(lhs, rhs) < 0; + } +}; + +int get_height_row(GtkTreeView* pTreeView, GList* pColumns) +{ + gint nMaxRowHeight = 0; + for (GList* pEntry = g_list_first(pColumns); pEntry; pEntry = g_list_next(pEntry)) + { + GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data); + GList *pRenderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(pColumn)); + for (GList* pRenderer = g_list_first(pRenderers); pRenderer; pRenderer = g_list_next(pRenderer)) + { + GtkCellRenderer* pCellRenderer = GTK_CELL_RENDERER(pRenderer->data); + gint nRowHeight; + gtk_cell_renderer_get_preferred_height(pCellRenderer, GTK_WIDGET(pTreeView), nullptr, &nRowHeight); + nMaxRowHeight = std::max(nMaxRowHeight, nRowHeight); + } + g_list_free(pRenderers); + } + return nMaxRowHeight; +} + +int get_height_row_separator(GtkTreeView* pTreeView) +{ + gint nVerticalSeparator; + gtk_widget_style_get(GTK_WIDGET(pTreeView), "vertical-separator", &nVerticalSeparator, nullptr); + return nVerticalSeparator; +} + +int get_height_rows(GtkTreeView* pTreeView, GList* pColumns, int nRows) +{ + gint nMaxRowHeight = get_height_row(pTreeView, pColumns); + gint nVerticalSeparator = get_height_row_separator(pTreeView); + return (nMaxRowHeight * nRows) + (nVerticalSeparator * (nRows + 1)); +} + +int get_height_rows(int nRowHeight, int nSeparatorHeight, int nRows) +{ + return (nRowHeight * nRows) + (nSeparatorHeight * (nRows + 1)); +} + +tools::Rectangle get_row_area(GtkTreeView* pTreeView, GList* pColumns, GtkTreePath* pPath) +{ + tools::Rectangle aRet; + + GdkRectangle aRect; + for (GList* pEntry = g_list_last(pColumns); pEntry; pEntry = g_list_previous(pEntry)) + { + GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data); + gtk_tree_view_get_cell_area(pTreeView, pPath, pColumn, &aRect); + aRet.Union(tools::Rectangle(aRect.x, aRect.y, aRect.x + aRect.width, aRect.y + aRect.height)); + } + + return aRet; +} + +struct GtkTreeRowReferenceDeleter +{ + void operator()(GtkTreeRowReference* p) const + { + gtk_tree_row_reference_free(p); + } +}; + +bool separator_function(GtkTreePath* path, const std::vector<std::unique_ptr<GtkTreeRowReference, GtkTreeRowReferenceDeleter>>& rSeparatorRows) +{ + bool bFound = false; + for (auto& a : rSeparatorRows) + { + GtkTreePath* seppath = gtk_tree_row_reference_get_path(a.get()); + if (seppath) + { + bFound = gtk_tree_path_compare(path, seppath) == 0; + gtk_tree_path_free(seppath); + } + if (bFound) + break; + } + return bFound; +} + +void tree_store_set(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, ...) +{ + va_list args; + + va_start(args, pIter); + gtk_tree_store_set_valist(GTK_TREE_STORE(pTreeModel), pIter, args); + va_end(args); +} + +void list_store_set(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, ...) +{ + va_list args; + + va_start(args, pIter); + gtk_list_store_set_valist(GTK_LIST_STORE(pTreeModel), pIter, args); + va_end(args); +} + +void tree_store_insert_with_values(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent, gint nPos, + gint nTextCol, const gchar* pText, + gint nIdCol, const gchar* pId) +{ + gtk_tree_store_insert_with_values(GTK_TREE_STORE(pTreeModel), pIter, pParent, nPos, + nTextCol, pText, nIdCol, pId, -1); +} + +void list_store_insert_with_values(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent, gint nPos, + gint nTextCol, const gchar* pText, + gint nIdCol, const gchar* pId) +{ + assert(!pParent); (void)pParent; + gtk_list_store_insert_with_values(GTK_LIST_STORE(pTreeModel), pIter, nPos, + nTextCol, pText, nIdCol, pId, -1); +} + +void tree_store_prepend(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent) +{ + gtk_tree_store_prepend(GTK_TREE_STORE(pTreeModel), pIter, pParent); +} + +void list_store_prepend(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent) +{ + assert(!pParent); (void)pParent; + gtk_list_store_prepend(GTK_LIST_STORE(pTreeModel), pIter); +} + +void tree_store_insert(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent, gint nPosition) +{ + gtk_tree_store_insert(GTK_TREE_STORE(pTreeModel), pIter, pParent, nPosition); +} + +void list_store_insert(GtkTreeModel* pTreeModel, GtkTreeIter *pIter, GtkTreeIter *pParent, gint nPosition) +{ + assert(!pParent); (void)pParent; + gtk_list_store_insert(GTK_LIST_STORE(pTreeModel), pIter, nPosition); +} + +void tree_store_clear(GtkTreeModel* pTreeModel) +{ + gtk_tree_store_clear(GTK_TREE_STORE(pTreeModel)); +} + +void list_store_clear(GtkTreeModel* pTreeModel) +{ + gtk_list_store_clear(GTK_LIST_STORE(pTreeModel)); +} + +void tree_store_remove(GtkTreeModel* pTreeModel, GtkTreeIter *pIter) +{ + gtk_tree_store_remove(GTK_TREE_STORE(pTreeModel), pIter); +} + +void list_store_remove(GtkTreeModel* pTreeModel, GtkTreeIter *pIter) +{ + gtk_list_store_remove(GTK_LIST_STORE(pTreeModel), pIter); +} + +void tree_store_swap(GtkTreeModel* pTreeModel, GtkTreeIter* pIter1, GtkTreeIter* pIter2) +{ + gtk_tree_store_swap(GTK_TREE_STORE(pTreeModel), pIter1, pIter2); +} + +void list_store_swap(GtkTreeModel* pTreeModel, GtkTreeIter* pIter1, GtkTreeIter* pIter2) +{ + gtk_list_store_swap(GTK_LIST_STORE(pTreeModel), pIter1, pIter2); +} + +void tree_store_set_value(GtkTreeModel* pTreeModel, GtkTreeIter* pIter, gint nColumn, GValue* pValue) +{ + gtk_tree_store_set_value(GTK_TREE_STORE(pTreeModel), pIter, nColumn, pValue); +} + +void list_store_set_value(GtkTreeModel* pTreeModel, GtkTreeIter* pIter, gint nColumn, GValue* pValue) +{ + gtk_list_store_set_value(GTK_LIST_STORE(pTreeModel), pIter, nColumn, pValue); +} + +int promote_arg(bool bArg) +{ + return static_cast<int>(bArg); +} + class GtkInstanceTreeView : public GtkInstanceContainer, public virtual weld::TreeView { private: GtkTreeView* m_pTreeView; - GtkTreeStore* m_pTreeStore; + GtkTreeModel* m_pTreeModel; + + typedef void(*setterFnc)(GtkTreeModel*, GtkTreeIter*, ...); + setterFnc m_Setter; + + typedef void(*insertWithValuesFnc)(GtkTreeModel*, GtkTreeIter*, GtkTreeIter*, gint, gint, const gchar*, gint, const gchar*); + insertWithValuesFnc m_InsertWithValues; + + typedef void(*insertFnc)(GtkTreeModel*, GtkTreeIter*, GtkTreeIter*, gint); + insertFnc m_Insert; + + typedef void(*prependFnc)(GtkTreeModel*, GtkTreeIter*, GtkTreeIter*); + prependFnc m_Prepend; + + typedef void(*clearFnc)(GtkTreeModel*); + clearFnc m_Clear; + + typedef void(*removeFnc)(GtkTreeModel*, GtkTreeIter*); + removeFnc m_Remove; + + typedef void(*swapFnc)(GtkTreeModel*, GtkTreeIter*, GtkTreeIter*); + swapFnc m_Swap; + + typedef void(*setValueFnc)(GtkTreeModel*, GtkTreeIter*, gint, GValue*); + setValueFnc m_SetValue; + std::unique_ptr<comphelper::string::NaturalStringSorter> m_xSorter; GList *m_pColumns; std::vector<gulong> m_aColumnSignalIds; @@ -8016,6 +8232,9 @@ private: std::map<int, int> m_aSensitiveMap; // map from text column to text align column std::map<int, int> m_aAlignMap; + // currently expanding parent that logically, but not currently physically, + // contain placeholders + o3tl::sorted_vector<GtkTreePath*, CompareGtkTreePath> m_aExpandingPlaceHolderParents; std::vector<GtkSortType> m_aSavedSortTypes; std::vector<int> m_aSavedSortColumns; bool m_bWorkAroundBadDragRegion; @@ -8069,7 +8288,7 @@ private: GtkInstanceTreeIter aIter(nullptr); if (!get_cursor(&aIter)) return; - if (iter_has_child(aIter)) + if (gtk_tree_model_iter_has_child(m_pTreeModel, &aIter.iter)) get_row_expanded(aIter) ? collapse_row(aIter) : expand_row(aIter); } @@ -8088,14 +8307,14 @@ private: void insert_row(GtkTreeIter& iter, const GtkTreeIter* parent, int pos, const OUString* pId, const OUString* pText, const OUString* pIconName, const VirtualDevice* pDevice, const OUString* pExpanderName) { - gtk_tree_store_insert_with_values(m_pTreeStore, &iter, const_cast<GtkTreeIter*>(parent), pos, - m_nTextCol, !pText ? nullptr : OUStringToOString(*pText, RTL_TEXTENCODING_UTF8).getStr(), - m_nIdCol, !pId ? nullptr : OUStringToOString(*pId, RTL_TEXTENCODING_UTF8).getStr(), - -1); + m_InsertWithValues(m_pTreeModel, &iter, const_cast<GtkTreeIter*>(parent), pos, + m_nTextCol, !pText ? nullptr : OUStringToOString(*pText, RTL_TEXTENCODING_UTF8).getStr(), + m_nIdCol, !pId ? nullptr : OUStringToOString(*pId, RTL_TEXTENCODING_UTF8).getStr()); + if (pIconName) { GdkPixbuf* pixbuf = getPixbuf(*pIconName); - gtk_tree_store_set(m_pTreeStore, &iter, m_nImageCol, pixbuf, -1); + m_Setter(m_pTreeModel, &iter, m_nImageCol, pixbuf, -1); if (pixbuf) g_object_unref(pixbuf); } @@ -8114,14 +8333,14 @@ private: cairo_paint(cr); cairo_destroy(cr); - gtk_tree_store_set(m_pTreeStore, &iter, m_nImageCol, target, -1); + m_Setter(m_pTreeModel, &iter, m_nImageCol, target, -1); cairo_surface_destroy(target); } - if (pExpanderName) + if (pExpanderName && GTK_IS_TREE_STORE(m_pTreeModel)) { GdkPixbuf* pixbuf = getPixbuf(*pExpanderName); - gtk_tree_store_set(m_pTreeStore, &iter, m_nExpanderImageCol, pixbuf, -1); + gtk_tree_store_set(GTK_TREE_STORE(m_pTreeModel), &iter, m_nExpanderImageCol, pixbuf, -1); if (pixbuf) g_object_unref(pixbuf); } @@ -8129,9 +8348,8 @@ private: OUString get(const GtkTreeIter& iter, int col) const { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); gchar* pStr; - gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&iter), col, &pStr, -1); + gtk_tree_model_get(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, &pStr, -1); OUString sRet(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8); g_free(pStr); return sRet; @@ -8140,9 +8358,8 @@ private: OUString get(int pos, int col) const { OUString sRet; - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) sRet = get(iter, col); return sRet; } @@ -8150,36 +8367,32 @@ private: gint get_int(const GtkTreeIter& iter, int col) const { gint nRet(-1); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&iter), col, &nRet, -1); + gtk_tree_model_get(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, &nRet, -1); return nRet; } gint get_int(int pos, int col) const { gint nRet(-1); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) nRet = get_int(iter, col); - gtk_tree_model_get(pModel, &iter, col, &nRet, -1); + gtk_tree_model_get(m_pTreeModel, &iter, col, &nRet, -1); return nRet; } bool get_bool(const GtkTreeIter& iter, int col) const { gboolean bRet(false); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&iter), col, &bRet, -1); + gtk_tree_model_get(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, &bRet, -1); return bRet; } bool get_bool(int pos, int col) const { bool bRet(false); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) bRet = get_bool(iter, col); return bRet; } @@ -8193,71 +8406,67 @@ private: if (eState == TRISTATE_INDET) { - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), - m_aToggleVisMap[col], true, // checkbuttons are invisible until toggled on or off - m_aToggleTriStateMap[col], true, // tristate on - -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), + m_aToggleVisMap[col], promote_arg(true), // checkbuttons are invisible until toggled on or off + m_aToggleTriStateMap[col], promote_arg(true), // tristate on + -1); } else { - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), - m_aToggleVisMap[col], true, // checkbuttons are invisible until toggled on or off - m_aToggleTriStateMap[col], false, // tristate off - col, eState == TRISTATE_TRUE, // set toggle state - -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), + m_aToggleVisMap[col], promote_arg(true), // checkbuttons are invisible until toggled on or off + m_aToggleTriStateMap[col], promote_arg(false), // tristate off + col, promote_arg(eState == TRISTATE_TRUE), // set toggle state + -1); } } void set(const GtkTreeIter& iter, int col, const OUString& rText) { OString aStr(OUStringToOString(rText, RTL_TEXTENCODING_UTF8)); - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, aStr.getStr(), -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, aStr.getStr(), -1); } void set(int pos, int col, const OUString& rText) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) set(iter, col, rText); } void set(const GtkTreeIter& iter, int col, bool bOn) { - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, bOn, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, promote_arg(bOn), -1); } void set(int pos, int col, bool bOn) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) set(iter, col, bOn); } void set(const GtkTreeIter& iter, int col, gint bInt) { - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, bInt, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, bInt, -1); } void set(int pos, int col, gint bInt) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) set(iter, col, bInt); } void set(const GtkTreeIter& iter, int col, double fValue) { - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, fValue, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, fValue, -1); } void set(int pos, int col, double fValue) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) set(iter, col, fValue); } @@ -8273,35 +8482,58 @@ private: return !pThis->signal_test_collapse_row(*iter); } - bool signal_test_expand_row(GtkTreeIter& iter) + bool child_is_placeholder(GtkInstanceTreeIter& rGtkIter) const { - disable_notify_events(); - GtkInstanceTreeIter aIter(nullptr); + GtkTreePath* pPath = gtk_tree_model_get_path(m_pTreeModel, &rGtkIter.iter); + bool bExpanding = m_aExpandingPlaceHolderParents.count(pPath); + gtk_tree_path_free(pPath); + if (bExpanding) + return true; - // if there's a preexisting placeholder child, required to make this - // potentially expandable in the first place, now we remove it bool bPlaceHolder = false; - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter tmp; - if (gtk_tree_model_iter_children(pModel, &tmp, &iter)) + if (gtk_tree_model_iter_children(m_pTreeModel, &tmp, &rGtkIter.iter)) { - aIter.iter = tmp; - if (get_text(aIter, -1) == "<dummy>") + rGtkIter.iter = tmp; + if (get_text(rGtkIter, -1) == "<dummy>") { - gtk_tree_store_remove(m_pTreeStore, &tmp); bPlaceHolder = true; } } + return bPlaceHolder; + } + + bool signal_test_expand_row(GtkTreeIter& iter) + { + disable_notify_events(); + + // if there's a preexisting placeholder child, required to make this + // potentially expandable in the first place, now we remove it + GtkInstanceTreeIter aIter(iter); + GtkTreePath* pPlaceHolderPath = nullptr; + bool bPlaceHolder = child_is_placeholder(aIter); + if (bPlaceHolder) + { + m_Remove(m_pTreeModel, &aIter.iter); + + pPlaceHolderPath = gtk_tree_model_get_path(m_pTreeModel, &iter); + m_aExpandingPlaceHolderParents.insert(pPlaceHolderPath); + } aIter.iter = iter; bool bRet = signal_expanding(aIter); - //expand disallowed, restore placeholder - if (!bRet && bPlaceHolder) + if (bPlaceHolder) { - GtkTreeIter subiter; - OUString sDummy("<dummy>"); - insert_row(subiter, &iter, -1, nullptr, &sDummy, nullptr, nullptr, nullptr); + //expand disallowed, restore placeholder + if (!bRet) + { + GtkTreeIter subiter; + OUString sDummy("<dummy>"); + insert_row(subiter, &iter, -1, nullptr, &sDummy, nullptr, nullptr, nullptr); + } + m_aExpandingPlaceHolderParents.erase(pPlaceHolderPath); + gtk_tree_path_free(pPlaceHolderPath); } enable_notify_events(); @@ -8334,14 +8566,13 @@ private: // node was clicked gtk_tree_view_set_cursor(m_pTreeView, tree_path, nullptr, false); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - gtk_tree_model_get_iter(pModel, &iter, tree_path); + gtk_tree_model_get_iter(m_pTreeModel, &iter, tree_path); gboolean bRet(false); - gtk_tree_model_get(pModel, &iter, nCol, &bRet, -1); + gtk_tree_model_get(m_pTreeModel, &iter, nCol, &bRet, -1); bRet = !bRet; - gtk_tree_store_set(m_pTreeStore, &iter, nCol, bRet, -1); + m_Setter(m_pTreeModel, &iter, nCol, bRet, -1); gint depth; @@ -8365,9 +8596,8 @@ private: { GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkInstanceTreeIter aGtkIter(nullptr); - gtk_tree_model_get_iter(pModel, &aGtkIter.iter, tree_path); + gtk_tree_model_get_iter(m_pTreeModel, &aGtkIter.iter, tree_path); gtk_tree_path_free(tree_path); return signal_editing_started(aGtkIter); @@ -8392,9 +8622,8 @@ private: { GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkInstanceTreeIter aGtkIter(nullptr); - gtk_tree_model_get_iter(pModel, &aGtkIter.iter, tree_path); + gtk_tree_model_get_iter(m_pTreeModel, &aGtkIter.iter, tree_path); gtk_tree_path_free(tree_path); OUString sText(pNewText, pNewText ? strlen(pNewText) : 0, RTL_TEXTENCODING_UTF8); @@ -8486,17 +8715,6 @@ private: return default_sort_func(pModel, a, b, m_xSorter.get()); } - static void signalDragBegin(GtkWidget*, GdkDragContext*, gpointer widget) - { - GtkInstanceTreeView* pThis = static_cast<GtkInstanceTreeView*>(widget); - g_DragSource = pThis; - } - - static void signalDragEnd(GtkWidget*, GdkDragContext*, gpointer) - { - g_DragSource = nullptr; - } - bool signal_key_press(GdkEventKey* pEvent) { if (pEvent->keyval != GDK_KEY_Left && pEvent->keyval != GDK_KEY_Right) @@ -8506,9 +8724,11 @@ private: if (!get_cursor(&aIter)) return false; + bool bHasChild = gtk_tree_model_iter_has_child(m_pTreeModel, &aIter.iter); + if (pEvent->keyval == GDK_KEY_Right) { - if (iter_has_child(aIter) && !get_row_expanded(aIter)) + if (bHasChild && !get_row_expanded(aIter)) { expand_row(aIter); return true; @@ -8516,7 +8736,7 @@ private: return false; } - if (iter_has_child(aIter) && get_row_expanded(aIter)) + if (bHasChild && get_row_expanded(aIter)) { collapse_row(aIter); return true; @@ -8542,11 +8762,11 @@ private: void set_font_color(const GtkTreeIter& iter, const Color& rColor) { if (rColor == COL_AUTO) - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, nullptr, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, nullptr, -1); else { GdkRGBA aColor{rColor.GetRed()/255.0, rColor.GetGreen()/255.0, rColor.GetBlue()/255.0, 0}; - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, &aColor, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, &aColor, -1); } } @@ -8584,11 +8804,10 @@ private: bool iter_next(weld::TreeIter& rIter, bool bOnlyExpanded) const { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter tmp; GtkTreeIter iter = rGtkIter.iter; - bool ret = gtk_tree_model_iter_children(pModel, &tmp, &iter); + bool ret = gtk_tree_model_iter_children(m_pTreeModel, &tmp, &iter); if (ret && bOnlyExpanded && !get_row_expanded(rGtkIter)) ret = false; rGtkIter.iter = tmp; @@ -8601,7 +8820,7 @@ private: } tmp = iter; - if (gtk_tree_model_iter_next(pModel, &tmp)) + if (gtk_tree_model_iter_next(m_pTreeModel, &tmp)) { rGtkIter.iter = tmp; //on-demand dummy entry doesn't count @@ -8610,10 +8829,10 @@ private: return true; } // Move up level(s) until we find the level where the next node exists. - while (gtk_tree_model_iter_parent(pModel, &tmp, &iter)) + while (gtk_tree_model_iter_parent(m_pTreeModel, &tmp, &iter)) { iter = tmp; - if (gtk_tree_model_iter_next(pModel, &tmp)) + if (gtk_tree_model_iter_next(m_pTreeModel, &tmp)) { rGtkIter.iter = tmp; //on-demand dummy entry doesn't count @@ -8629,7 +8848,7 @@ public: GtkInstanceTreeView(GtkTreeView* pTreeView, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : GtkInstanceContainer(GTK_CONTAINER(pTreeView), pBuilder, bTakeOwnership) , m_pTreeView(pTreeView) - , m_pTreeStore(GTK_TREE_STORE(gtk_tree_view_get_model(m_pTreeView))) + , m_pTreeModel(gtk_tree_view_get_model(m_pTreeView)) , m_bWorkAroundBadDragRegion(false) , m_bInDrag(false) , m_nTextCol(-1) @@ -8649,6 +8868,34 @@ public: , m_pVAdjustment(gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(pTreeView))) , m_pChangeEvent(nullptr) { + if (GTK_IS_TREE_STORE(m_pTreeModel)) + { + m_Setter = tree_store_set; + m_InsertWithValues = tree_store_insert_with_values; + m_Insert = tree_store_insert; + m_Prepend = tree_store_prepend; + m_Remove = tree_store_remove; + m_Swap = tree_store_swap; + m_SetValue = tree_store_set_value; + m_Clear = tree_store_clear; + } + else + { + /* + tdf#136559 see: https://gitlab.gnome.org/GNOME/gtk/-/issues/2693 + If we only need a list and not a tree we can get a performance boost from using a ListStore + */ + assert(!gtk_tree_view_get_show_expanders(m_pTreeView) && "a liststore can only be used if no tree structure is needed"); + m_Setter = list_store_set; + m_InsertWithValues = list_store_insert_with_values; + m_Insert = list_store_insert; + m_Prepend = list_store_prepend; + m_Remove = list_store_remove; + m_Swap = list_store_swap; + m_SetValue = list_store_set_value; + m_Clear = list_store_clear; + } + /* The outside concept of a column maps to a gtk CellRenderer, rather than a TreeViewColumn. If the first TreeViewColumn has a leading Toggle Renderer and/or a leading Image Renderer, those are considered special expander @@ -8716,9 +8963,8 @@ public: for (auto& a : m_aAlignMap) a.second = nIndex++; - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - m_nRowDeletedSignalId = g_signal_connect(pModel, "row-deleted", G_CALLBACK(signalRowDeleted), this); - m_nRowInsertedSignalId = g_signal_connect(pModel, "row-inserted", G_CALLBACK(signalRowInserted), this); + m_nRowDeletedSignalId = g_signal_connect(m_pTreeModel, "row-deleted", G_CALLBACK(signalRowDeleted), this); + m_nRowInsertedSignalId = g_signal_connect(m_pTreeModel, "row-inserted", G_CALLBACK(signalRowInserted), this); } virtual void columns_autosize() override @@ -8812,14 +9058,19 @@ public: void set_font_color(const GtkTreeIter& iter, const Color& rColor) const { - GdkRGBA aColor{rColor.GetRed()/255.0, rColor.GetGreen()/255.0, rColor.GetBlue()/255.0, 0}; - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, &aColor, -1); + if (rColor == COL_AUTO) + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, nullptr, -1); + else + { + GdkRGBA aColor{rColor.GetRed()/255.0, rColor.GetGreen()/255.0, rColor.GetBlue()/255.0, 0}; + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), m_nIdCol + 1, &aColor, -1); + } } virtual void set_font_color(int pos, const Color& rColor) const override { GtkTreeIter iter; - gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(m_pTreeStore), &iter, nullptr, pos); + gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos); set_font_color(iter, rColor); } @@ -8833,22 +9084,22 @@ public: { disable_notify_events(); GtkTreeIter iter; - gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(m_pTreeStore), &iter, nullptr, pos); - gtk_tree_store_remove(m_pTreeStore, &iter); + gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos); + m_Remove(m_pTreeModel, &iter); enable_notify_events(); } virtual int find_text(const OUString& rText) const override { Search aSearch(rText, m_nTextCol); - gtk_tree_model_foreach(GTK_TREE_MODEL(m_pTreeStore), foreach_find, &aSearch); + gtk_tree_model_foreach(m_pTreeModel, foreach_find, &aSearch); return aSearch.index; } virtual int find_id(const OUString& rId) const override { Search aSearch(rId, m_nIdCol); - gtk_tree_model_foreach(GTK_TREE_MODEL(m_pTreeStore), foreach_find, &aSearch); + gtk_tree_model_foreach(m_pTreeModel, foreach_find, &aSearch); return aSearch.index; } @@ -8865,7 +9116,7 @@ public: while (nSourceCount) { // tdf#125241 inserting backwards is massively faster - gtk_tree_store_prepend(m_pTreeStore, &aGtkIter.iter, nullptr); + m_Prepend(m_pTreeModel, &aGtkIter.iter, nullptr); func(aGtkIter, --nSourceCount); } @@ -8876,15 +9127,13 @@ public: { disable_notify_events(); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreeIter iter1; - gtk_tree_model_iter_nth_child(pModel, &iter1, nullptr, pos1); + gtk_tree_model_iter_nth_child(m_pTreeModel, &iter1, nullptr, pos1); GtkTreeIter iter2; - gtk_tree_model_iter_nth_child(pModel, &iter2, nullptr, pos2); + gtk_tree_model_iter_nth_child(m_pTreeModel, &iter2, nullptr, pos2); - gtk_tree_store_swap(m_pTreeStore, &iter1, &iter2); + m_Swap(m_pTreeModel, &iter1, &iter2); enable_notify_events(); } @@ -8892,7 +9141,8 @@ public: virtual void clear() override { disable_notify_events(); - gtk_tree_store_clear(m_pTreeStore); + gtk_tree_view_set_row_separator_func(m_pTreeView, nullptr, nullptr, nullptr); + m_Clear(m_pTreeModel); enable_notify_events(); } @@ -8903,7 +9153,7 @@ public: m_xSorter.reset(new comphelper::string::NaturalStringSorter( ::comphelper::getProcessComponentContext(), Application::GetSettings().GetUILanguageTag().getLocale())); - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_set_sort_func(pSortable, m_nTextCol, sortFunc, this, nullptr); gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, GTK_SORT_ASCENDING); } @@ -8913,7 +9163,7 @@ public: m_xSorter.reset(); int nSortColumn; GtkSortType eSortType; - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_get_sort_column_id(pSortable, &nSortColumn, &eSortType); gtk_tree_sortable_set_sort_column_id(pSortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, eSortType); } @@ -8923,18 +9173,19 @@ public: GtkSortType eSortType = bAscending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING; gint sort_column_id(0); - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_get_sort_column_id(pSortable, &sort_column_id, nullptr); gtk_tree_sortable_set_sort_column_id(pSortable, sort_column_id, eSortType); } virtual bool get_sort_order() const override { + int nSortColumn; GtkSortType eSortType; - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); - gtk_tree_sortable_get_sort_column_id(pSortable, nullptr, &eSortType); - return eSortType == GTK_SORT_ASCENDING; + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); + gtk_tree_sortable_get_sort_column_id(pSortable, &nSortColumn, &eSortType); + return nSortColumn != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID && eSortType == GTK_SORT_ASCENDING; } virtual void set_sort_indicator(TriState eState, int col) override @@ -8965,7 +9216,7 @@ public: virtual int get_sort_column() const override { - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gint sort_column_id(0); if (!gtk_tree_sortable_get_sort_column_id(pSortable, &sort_column_id, nullptr)) return -1; @@ -8980,7 +9231,7 @@ public: return; } GtkSortType eSortType; - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_get_sort_column_id(pSortable, nullptr, &eSortType); int nSortCol = to_internal_model(nColumn); gtk_tree_sortable_set_sort_func(pSortable, nSortCol, sortFunc, this, nullptr); @@ -8990,13 +9241,13 @@ public: virtual void set_sort_func(const std::function<int(const weld::TreeIter&, const weld::TreeIter&)>& func) override { weld::TreeView::set_sort_func(func); - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_sort_column_changed(pSortable); } virtual int n_children() const override { - return gtk_tree_model_iter_n_children(GTK_TREE_MODEL(m_pTreeStore), nullptr); + return gtk_tree_model_iter_n_children(m_pTreeModel, nullptr); } virtual void select(int pos) override @@ -9037,7 +9288,7 @@ public: virtual bool is_selected(int pos) const override { GtkTreeIter iter; - gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(m_pTreeStore), &iter, nullptr, pos); + gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos); return gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(m_pTreeView), &iter); } @@ -9109,31 +9360,34 @@ public: virtual void visible_foreach(const std::function<bool(weld::TreeIter&)>& func) override { + g_object_freeze_notify(G_OBJECT(m_pTreeModel)); + GtkTreePath* start_path; GtkTreePath* end_path; - if (gtk_tree_view_get_visible_range(m_pTreeView, &start_path, &end_path)) + if (!gtk_tree_view_get_visible_range(m_pTreeView, &start_path, &end_path)) + return; + + GtkInstanceTreeIter aGtkIter(nullptr); + gtk_tree_model_get_iter(m_pTreeModel, &aGtkIter.iter, start_path); + + do { - GtkInstanceTreeIter aGtkIter(nullptr); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - gtk_tree_model_get_iter(pModel, &aGtkIter.iter, start_path); + if (func(aGtkIter)) + break; + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, &aGtkIter.iter); + bool bContinue = gtk_tree_path_compare(path, end_path) != 0; + gtk_tree_path_free(path); + if (!bContinue) + break; + if (!iter_next(aGtkIter)) + break; + } while(true); - do - { - if (func(aGtkIter)) - break; - GtkTreePath* path = gtk_tree_model_get_path(pModel, &aGtkIter.iter); - bool bContinue = gtk_tree_path_compare(path, end_path) != 0; - gtk_tree_path_free(path); - if (!bContinue) - break; - if (!iter_next(aGtkIter)) - break; - } while(true); + gtk_tree_path_free(start_path); + gtk_tree_path_free(end_path); - gtk_tree_path_free(start_path); - gtk_tree_path_free(end_path); - } + g_object_thaw_notify(G_OBJECT(m_pTreeModel)); } virtual void connect_visible_range_changed(const Link<weld::TreeView&, void>& rLink) override @@ -9198,21 +9452,14 @@ public: virtual void set_toggle(const weld::TreeIter& rIter, TriState eState, int col) override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + set_toggle(rGtkIter.iter, eState, col); + } - if (col == -1) - col = m_nExpanderToggleCol; - else - col = to_internal_model(col); - - // checkbuttons are invisible until toggled on or off - set(rGtkIter.iter, m_aToggleVisMap[col], true); - if (eState == TRISTATE_INDET) - set(rGtkIter.iter, m_aToggleTriStateMap[col], true); - else - { - set(rGtkIter.iter, m_aToggleTriStateMap[col], false); - set(rGtkIter.iter, col, eState == TRISTATE_TRUE); - } + virtual void set_toggle(int pos, TriState eState, int col) override + { + GtkTreeIter iter; + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) + set_toggle(iter, eState, col); } virtual void enable_toggle_buttons(weld::ColumnToggleType eType) override @@ -9233,14 +9480,6 @@ public: } } - virtual void set_toggle(int pos, TriState eState, int col) override - { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) - set_toggle(iter, eState, col); - } - virtual void set_text_emphasis(const weld::TreeIter& rIter, bool bOn, int col) override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); @@ -9307,16 +9546,15 @@ public: col = m_nExpanderImageCol; else col = to_internal_model(col); - gtk_tree_store_set(m_pTreeStore, const_cast<GtkTreeIter*>(&iter), col, pixbuf, -1); + m_Setter(m_pTreeModel, const_cast<GtkTreeIter*>(&iter), col, pixbuf, -1); if (pixbuf) g_object_unref(pixbuf); } void set_image(int pos, GdkPixbuf* pixbuf, int col) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter iter; - if (gtk_tree_model_iter_nth_child(pModel, &iter, nullptr, pos)) + if (gtk_tree_model_iter_nth_child(m_pTreeModel, &iter, nullptr, pos)) { set_image(iter, col, pixbuf); } @@ -9369,8 +9607,7 @@ public: { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); gint depth; gint* indices = gtk_tree_path_get_indices_with_depth(path, &depth); @@ -9386,9 +9623,8 @@ public: const GtkInstanceTreeIter& rGtkIterA = static_cast<const GtkInstanceTreeIter&>(a); const GtkInstanceTreeIter& rGtkIterB = static_cast<const GtkInstanceTreeIter&>(b); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* pathA = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIterA.iter)); - GtkTreePath* pathB = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIterB.iter)); + GtkTreePath* pathA = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIterA.iter)); + GtkTreePath* pathB = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIterB.iter)); int nRet = gtk_tree_path_compare(pathA, pathB); @@ -9401,33 +9637,31 @@ public: // by copy and delete of old copy void move_subtree(GtkTreeIter& rFromIter, GtkTreeIter* pGtkParentIter, int nIndexInNewParent) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - - int nCols = gtk_tree_model_get_n_columns(pModel); + int nCols = gtk_tree_model_get_n_columns(m_pTreeModel); GValue value; GtkTreeIter toiter; - gtk_tree_store_insert(m_pTreeStore, &toiter, pGtkParentIter, nIndexInNewParent); + m_Insert(m_pTreeModel, &toiter, pGtkParentIter, nIndexInNewParent); for (int i = 0; i < nCols; ++i) { memset(&value, 0, sizeof(GValue)); - gtk_tree_model_get_value(pModel, &rFromIter, i, &value); - gtk_tree_store_set_value(m_pTreeStore, &toiter, i, &value); + gtk_tree_model_get_value(m_pTreeModel, &rFromIter, i, &value); + m_SetValue(m_pTreeModel, &toiter, i, &value); g_value_unset(&value); } GtkTreeIter tmpfromiter; - if (gtk_tree_model_iter_children(pModel, &tmpfromiter, &rFromIter)) + if (gtk_tree_model_iter_children(m_pTreeModel, &tmpfromiter, &rFromIter)) { int j = 0; do { move_subtree(tmpfromiter, &toiter, j++); - } while (gtk_tree_model_iter_next(pModel, &tmpfromiter)); + } while (gtk_tree_model_iter_next(m_pTreeModel, &tmpfromiter)); } - gtk_tree_store_remove(m_pTreeStore, &rFromIter); + m_Remove(m_pTreeModel, &rFromIter); } virtual void move_subtree(weld::TreeIter& rNode, const weld::TreeIter* pNewParent, int nIndexInNewParent) override @@ -9534,8 +9768,7 @@ public: gtk_tree_view_get_cursor(m_pTreeView, &path, nullptr); if (pGtkIter && path) { - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - gtk_tree_model_get_iter(pModel, &pGtkIter->iter, path); + gtk_tree_model_get_iter(m_pTreeModel, &pGtkIter->iter, path); } if (!path) return false; @@ -9563,8 +9796,16 @@ public: virtual void set_cursor(const weld::TreeIter& rIter) override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreeIter Iter; + if (gtk_tree_model_iter_parent(m_pTreeModel, &Iter, const_cast<GtkTreeIter*>(&rGtkIter.iter))) + { + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, &Iter); + if (!gtk_tree_view_row_expanded(m_pTreeView, path)) + gtk_tree_view_expand_to_path(m_pTreeView, path); + gtk_tree_path_free(path); + } + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0); gtk_tree_view_set_cursor(m_pTreeView, path, nullptr, false); gtk_tree_path_free(path); } @@ -9572,49 +9813,25 @@ public: virtual bool get_iter_first(weld::TreeIter& rIter) const override { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - return gtk_tree_model_get_iter_first(pModel, &rGtkIter.iter); + return gtk_tree_model_get_iter_first(m_pTreeModel, &rGtkIter.iter); } virtual bool iter_next_sibling(weld::TreeIter& rIter) const override { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - return gtk_tree_model_iter_next(pModel, &rGtkIter.iter); + return gtk_tree_model_iter_next(m_pTreeModel, &rGtkIter.iter); } virtual bool iter_next(weld::TreeIter& rIter) const override { - GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreeIter iter = rGtkIter.iter; - if (iter_children(rGtkIter)) - return true; - GtkTreeIter tmp = iter; - if (gtk_tree_model_iter_next(pModel, &tmp)) - { - rGtkIter.iter = tmp; - return true; - } - // Move up level(s) until we find the level where the next sibling exists. - while (gtk_tree_model_iter_parent(pModel, &tmp, &iter)) - { - iter = tmp; - if (gtk_tree_model_iter_next(pModel, &tmp)) - { - rGtkIter.iter = tmp; - return true; - } - } - return false; + return iter_next(rIter, false); } virtual bool iter_children(weld::TreeIter& rIter) const override { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter tmp; - bool ret = gtk_tree_model_iter_children(pModel, &tmp, &rGtkIter.iter); + bool ret = gtk_tree_model_iter_children(m_pTreeModel, &tmp, &rGtkIter.iter); rGtkIter.iter = tmp; if (ret) { @@ -9627,9 +9844,8 @@ public: virtual bool iter_parent(weld::TreeIter& rIter) const override { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); GtkTreeIter tmp; - auto ret = gtk_tree_model_iter_parent(pModel, &tmp, &rGtkIter.iter); + auto ret = gtk_tree_model_iter_parent(m_pTreeModel, &tmp, &rGtkIter.iter); rGtkIter.iter = tmp; return ret; } @@ -9638,7 +9854,7 @@ public: { disable_notify_events(); const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - gtk_tree_store_remove(m_pTreeStore, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + m_Remove(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); enable_notify_events(); } @@ -9658,7 +9874,7 @@ public: g_list_free_full(pList, reinterpret_cast<GDestroyNotify>(gtk_tree_path_free)); for (auto& iter : aIters) - gtk_tree_store_remove(m_pTreeStore, &iter); + m_Remove(m_pTreeModel, &iter); enable_notify_events(); } @@ -9677,8 +9893,8 @@ public: assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen"); disable_notify_events(); const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + gtk_tree_view_expand_to_path(m_pTreeView, path); gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0); gtk_tree_path_free(path); enable_notify_events(); @@ -9696,8 +9912,7 @@ public: virtual int get_iter_depth(const weld::TreeIter& rIter) const override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); int ret = gtk_tree_path_get_depth(path) - 1; gtk_tree_path_free(path); return ret; @@ -9716,8 +9931,7 @@ public: virtual bool get_row_expanded(const weld::TreeIter& rIter) const override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); bool ret = gtk_tree_view_row_expanded(m_pTreeView, path); gtk_tree_path_free(path); return ret; @@ -9728,8 +9942,7 @@ public: assert(gtk_tree_view_get_model(m_pTreeView) && "don't expand when frozen"); const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); if (!gtk_tree_view_row_expanded(m_pTreeView, path)) gtk_tree_view_expand_to_path(m_pTreeView, path); gtk_tree_path_free(path); @@ -9738,8 +9951,7 @@ public: virtual void collapse_row(const weld::TreeIter& rIter) override { const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); if (gtk_tree_view_row_expanded(m_pTreeView, path)) gtk_tree_view_collapse_row(m_pTreeView, path); gtk_tree_path_free(path); @@ -9780,14 +9992,14 @@ public: virtual void freeze() override { disable_notify_events(); - g_object_ref(m_pTreeStore); + g_object_ref(m_pTreeModel); GtkInstanceContainer::freeze(); gtk_tree_view_set_model(m_pTreeView, nullptr); if (m_xSorter) { int nSortColumn; GtkSortType eSortType; - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_get_sort_column_id(pSortable, &nSortColumn, &eSortType); gtk_tree_sortable_set_sort_column_id(pSortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, eSortType); @@ -9802,14 +10014,14 @@ public: disable_notify_events(); if (m_xSorter) { - GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore); + GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeModel); gtk_tree_sortable_set_sort_column_id(pSortable, m_aSavedSortColumns.back(), m_aSavedSortTypes.back()); m_aSavedSortTypes.pop_back(); m_aSavedSortColumns.pop_back(); } - gtk_tree_view_set_model(m_pTreeView, GTK_TREE_MODEL(m_pTreeStore)); + gtk_tree_view_set_model(m_pTreeView, GTK_TREE_MODEL(m_pTreeModel)); GtkInstanceContainer::thaw(); - g_object_unref(m_pTreeStore); + g_object_unref(m_pTreeModel); enable_notify_events(); } @@ -9897,7 +10109,7 @@ public: int starts_with(const OUString& rStr, int nStartRow, bool bCaseSensitive) { - return ::starts_with(GTK_TREE_MODEL(m_pTreeStore), rStr, m_nTextCol, nStartRow, bCaseSensitive); + return ::starts_with(m_pTreeModel, rStr, m_nTextCol, nStartRow, bCaseSensitive); } virtual void disable_notify_events() override @@ -9905,9 +10117,8 @@ public: g_signal_handler_block(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId); g_signal_handler_block(m_pTreeView, m_nRowActivatedSignalId); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - g_signal_handler_block(pModel, m_nRowDeletedSignalId); - g_signal_handler_block(pModel, m_nRowInsertedSignalId); + g_signal_handler_block(m_pTreeModel, m_nRowDeletedSignalId); + g_signal_handler_block(m_pTreeModel, m_nRowInsertedSignalId); GtkInstanceContainer::disable_notify_events(); } @@ -9916,9 +10127,8 @@ public: { GtkInstanceContainer::enable_notify_events(); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - g_signal_handler_unblock(pModel, m_nRowDeletedSignalId); - g_signal_handler_unblock(pModel, m_nRowInsertedSignalId); + g_signal_handler_unblock(m_pTreeModel, m_nRowDeletedSignalId); + g_signal_handler_unblock(m_pTreeModel, m_nRowInsertedSignalId); g_signal_handler_unblock(m_pTreeView, m_nRowActivatedSignalId); g_signal_handler_unblock(gtk_tree_view_get_selection(m_pTreeView), m_nChangedSignalId); @@ -9950,7 +10160,7 @@ public: &path, >kpos); // find the last entry in the model for comparison - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); + GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeModel); int nChildren = gtk_tree_model_iter_n_children(pModel, nullptr); GtkTreePath *lastpath; if (nChildren) @@ -9982,7 +10192,7 @@ public: if (ret && pResult) { GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(*pResult); - gtk_tree_model_get_iter(pModel, &rGtkIter.iter, path); + gtk_tree_model_get_iter(m_pTreeModel, &rGtkIter.iter, path); } if (m_bInDrag) @@ -10028,8 +10238,7 @@ public: assert(pColumn && "wrong column"); const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + GtkTreePath* path = gtk_tree_model_get_path(m_pTreeModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); // allow editing of cells which are not usually editable, so we can have double click // do its usual row-activate but if we explicitly want to edit (remote files dialog) @@ -10065,7 +10274,7 @@ public: gtk_cell_area_stop_editing(gtk_cell_layout_get_area(GTK_CELL_LAYOUT(focus_column)), true); } - virtual TreeView* get_drag_source() const override + virtual weld::TreeView* get_drag_source() const override { return g_DragSource; } @@ -10115,9 +10324,8 @@ public: g_signal_handler_disconnect(m_pTreeView, m_nDragEndSignalId); g_signal_handler_disconnect(m_pTreeView, m_nDragBeginSignalId); g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - g_signal_handler_disconnect(pModel, m_nRowDeletedSignalId); - g_signal_handler_disconnect(pModel, m_nRowInsertedSignalId); + g_signal_handler_disconnect(m_pTreeModel, m_nRowDeletedSignalId); + g_signal_handler_disconnect(m_pTreeModel, m_nRowInsertedSignalId); if (m_nVAdjustmentChangedSignalId) { @@ -10139,6 +10347,8 @@ public: } }; +} + IMPL_LINK_NOARG(GtkInstanceTreeView, async_signal_changed, void*, void) { m_pChangeEvent = nullptr; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits