summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-02-18 12:11:08 +0000
committerCaolán McNamara <caolanm@redhat.com>2019-02-19 22:18:10 +0100
commit12a59a1f2948274c6a845ab4a0963bab8aff45b8 (patch)
treed7877f8e78aad8b53df428773947228e88a151f3 /vcl
parente9bc6efbb8f1c1d012e60f3fc9877d311a48ee03 (diff)
weld ChineseDictionaryDialog
and ChineseTranslationDialog Change-Id: I3b754c405c8379fc0c5fa94437cc0464a1dea999 Reviewed-on: https://gerrit.libreoffice.org/67991 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/app/salvtables.cxx129
-rw-r--r--vcl/source/treelist/treelistbox.cxx13
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx132
3 files changed, 229 insertions, 45 deletions
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index df7de9561743..827256ca41d7 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -2087,6 +2087,7 @@ private:
VclPtr<SvTabListBox> m_xTreeView;
SvLBoxButtonData m_aCheckButtonData;
SvLBoxButtonData m_aRadioButtonData;
+ int m_nSortColumn;
DECL_LINK(SelectHdl, SvTreeListBox*, void);
DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool);
@@ -2095,12 +2096,14 @@ private:
DECL_LINK(HeaderBarClickedHdl, HeaderBar*, void);
DECL_LINK(ToggleHdl, SvLBoxButtonData*, void);
DECL_LINK(VisibleRangeChangedHdl, SvTreeListBox*, void);
+ DECL_LINK(CompareHdl, const SvSortData&, sal_Int32);
public:
SalInstanceTreeView(SvTabListBox* pTreeView, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
: SalInstanceContainer(pTreeView, pBuilder, bTakeOwnership)
, m_xTreeView(pTreeView)
, m_aCheckButtonData(pTreeView, false)
, m_aRadioButtonData(pTreeView, true)
+ , m_nSortColumn(-1)
{
m_xTreeView->SetNodeDefaultImages();
m_xTreeView->SetSelectHdl(LINK(this, SalInstanceTreeView, SelectHdl));
@@ -2186,8 +2189,8 @@ public:
}
virtual void insert(weld::TreeIter* pParent, int pos, const OUString* pStr, const OUString* pId,
- const OUString* pIconName, VirtualDevice* pImageSurface, const OUString* pExpanderName,
- bool bChildrenOnDemand) override
+ const OUString* pIconName, VirtualDevice* pImageSurface,
+ const OUString* pExpanderName, bool bChildrenOnDemand, weld::TreeIter* pRet) override
{
SalInstanceTreeIter* pVclIter = static_cast<SalInstanceTreeIter*>(pParent);
SvTreeListEntry* iter = pVclIter ? pVclIter->iter : nullptr;
@@ -2224,6 +2227,12 @@ public:
m_xTreeView->SetCollapsedEntryBmp(pEntry, aImage);
}
+ if (pRet)
+ {
+ SalInstanceTreeIter* pVclRetIter = static_cast<SalInstanceTreeIter*>(pRet);
+ pVclRetIter->iter = pEntry;
+ }
+
if (bChildrenOnDemand)
{
m_xTreeView->InsertEntry("<dummy>", pEntry, false, 0, nullptr);
@@ -2455,13 +2464,18 @@ public:
return *pRet;
}
- virtual void set_id(int pos, const OUString& rId) override
+ void set_id(SvTreeListEntry* pEntry, const OUString& rId)
{
- SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
m_aUserData.emplace_back(std::make_unique<OUString>(rId));
pEntry->SetUserData(m_aUserData.back().get());
}
+ virtual void set_id(int pos, const OUString& rId) override
+ {
+ SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos);
+ set_id(pEntry, rId);
+ }
+
virtual int get_selected_index() const override
{
assert(m_xTreeView->IsUpdateMode() && "don't request selection when frozen");
@@ -2644,6 +2658,12 @@ public:
return OUString();
}
+ virtual void set_id(weld::TreeIter& rIter, const OUString& rId) override
+ {
+ SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rIter);
+ set_id(rVclIter.iter, rId);
+ }
+
virtual void set_expander_image(const weld::TreeIter& rIter, const OUString& rImage) override
{
const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter);
@@ -2704,36 +2724,76 @@ public:
virtual void make_sorted() override
{
m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT);
+ m_xTreeView->GetModel()->SetCompareHdl(LINK(this, SalInstanceTreeView, CompareHdl));
set_sort_order(true);
}
virtual void set_sort_order(bool bAscending) override
{
+ SvTreeList* pListModel = m_xTreeView->GetModel();
+ pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
+ pListModel->Resort();
+ }
+
+ virtual bool get_sort_order() const override
+ {
+ return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
+ }
+
+ virtual void set_sort_indicator(TriState eState, int col) override
+ {
+ if (col == -1)
+ col = 0;
+
SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get());
if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
{
- sal_uInt16 nTextId = pHeaderBar->GetItemId(0);
+ sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
- if (nBits & HeaderBarItemBits::CLICKABLE)
+ nBits &= ~HeaderBarItemBits::UPARROW;
+ nBits &= ~HeaderBarItemBits::DOWNARROW;
+ if (eState != TRISTATE_INDET)
{
- nBits &= ~HeaderBarItemBits::UPARROW;
- nBits &= ~HeaderBarItemBits::DOWNARROW;
- if (bAscending)
+ if (eState == TRISTATE_TRUE)
nBits |= HeaderBarItemBits::DOWNARROW;
else
nBits |= HeaderBarItemBits::UPARROW;
- pHeaderBar->SetItemBits(nTextId, nBits);
}
+ pHeaderBar->SetItemBits(nTextId, nBits);
}
+ }
- SvTreeList* pListModel = m_xTreeView->GetModel();
- pListModel->SetSortMode(bAscending ? SortAscending : SortDescending);
- pListModel->Resort();
+ virtual TriState get_sort_indicator(int col) const override
+ {
+ if (col == -1)
+ col = 0;
+
+ SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get());
+ if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr)
+ {
+ sal_uInt16 nTextId = pHeaderBar->GetItemId(col);
+ HeaderBarItemBits nBits = pHeaderBar->GetItemBits(nTextId);
+ if (nBits & HeaderBarItemBits::DOWNARROW)
+ return TRISTATE_TRUE;
+ if (nBits & HeaderBarItemBits::UPARROW)
+ return TRISTATE_FALSE;
+ }
+
+ return TRISTATE_INDET;
}
- virtual bool get_sort_order() const override
+ virtual int get_sort_column() const override
{
- return m_xTreeView->GetModel()->GetSortMode() == SortAscending;
+ return m_nSortColumn;
+ }
+
+ virtual void set_sort_column(int nColumn) override
+ {
+ if (nColumn != m_nSortColumn)
+ {
+ m_nSortColumn = nColumn;
+ m_xTreeView->GetModel()->Resort();
+ }
}
SvTabListBox& getTreeView()
@@ -2756,6 +2816,45 @@ public:
}
};
+IMPL_LINK(SalInstanceTreeView, CompareHdl, const SvSortData&, rSortData, sal_Int32)
+{
+ const SvTreeListEntry* pLHS = rSortData.pLeft;
+ const SvTreeListEntry* pRHS = rSortData.pRight;
+ assert(pLHS && pRHS);
+
+ const SvLBoxString* pLeftTextItem;
+ const SvLBoxString* pRightTextItem;
+
+ if (m_nSortColumn != -1)
+ {
+ size_t col = m_nSortColumn;
+
+ ++col; //skip dummy/expander column
+
+ if (col < pLHS->ItemCount())
+ {
+ const SvLBoxString& rLeftTextItem = static_cast<const SvLBoxString&>(pLHS->GetItem(col));
+ pLeftTextItem = &rLeftTextItem;
+ }
+ else
+ pLeftTextItem = nullptr;
+ if (col < pRHS->ItemCount())
+ {
+ const SvLBoxString& rRightTextItem = static_cast<const SvLBoxString&>(pRHS->GetItem(col));
+ pRightTextItem = &rRightTextItem;
+ }
+ else
+ pRightTextItem = nullptr;
+ }
+ else
+ {
+ pLeftTextItem = static_cast<const SvLBoxString*>(pLHS->GetFirstItem(SvLBoxItemType::String));
+ pRightTextItem = static_cast<const SvLBoxString*>(pRHS->GetFirstItem(SvLBoxItemType::String));
+ }
+
+ return m_xTreeView->DefaultCompare(pLeftTextItem, pRightTextItem);
+}
+
IMPL_LINK_NOARG(SalInstanceTreeView, VisibleRangeChangedHdl, SvTreeListBox*, void)
{
signal_visible_range_changed();
diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx
index e306d7df0e47..6c45fc325ebe 100644
--- a/vcl/source/treelist/treelistbox.cxx
+++ b/vcl/source/treelist/treelistbox.cxx
@@ -3312,16 +3312,21 @@ void SvTreeListBox::RequestHelp( const HelpEvent& rHEvt )
Control::RequestHelp( rHEvt );
}
+sal_Int32 SvTreeListBox::DefaultCompare(const SvLBoxString* pLeftText, const SvLBoxString* pRightText)
+{
+ OUString aLeft = pLeftText ? pLeftText->GetText() : OUString();
+ OUString aRight = pRightText ? pRightText->GetText() : OUString();
+ pImpl->UpdateStringSorter();
+ return pImpl->m_pStringSorter->compare(aLeft, aRight);
+}
+
IMPL_LINK( SvTreeListBox, DefaultCompare, const SvSortData&, rData, sal_Int32 )
{
const SvTreeListEntry* pLeft = rData.pLeft;
const SvTreeListEntry* pRight = rData.pRight;
const SvLBoxString* pLeftText = static_cast<const SvLBoxString*>(pLeft->GetFirstItem(SvLBoxItemType::String));
const SvLBoxString* pRightText = static_cast<const SvLBoxString*>(pRight->GetFirstItem(SvLBoxItemType::String));
- OUString aLeft = pLeftText ? pLeftText->GetText() : OUString();
- OUString aRight = pRightText ? pRightText->GetText() : OUString();
- pImpl->UpdateStringSorter();
- return pImpl->m_pStringSorter->compare(aLeft, aRight);
+ return DefaultCompare(pLeftText, pRightText);
}
void SvTreeListBox::ModelNotification( SvListAction nActionId, SvTreeListEntry* pEntry1,
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 84295d62f64d..51b52a6626a6 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -5155,8 +5155,11 @@ private:
std::vector<gulong> m_aColumnSignalIds;
// map from toggle column to toggle visibility column
std::map<int, int> m_aToggleVisMap;
+ std::vector<GtkSortType> m_aSavedSortTypes;
+ std::vector<int> m_aSavedSortColumns;
+ std::vector<int> m_aViewColToModelCol;
+ std::vector<int> m_aModelColToViewCol;
gint m_nTextCol;
- gint m_nTextColHeader;
gint m_nImageCol;
gint m_nExpanderImageCol;
gint m_nIdCol;
@@ -5164,7 +5167,6 @@ private:
gulong m_nRowActivatedSignalId;
gulong m_nTestExpandRowSignalId;
gulong m_nVAdjustmentChangedSignalId;
- GtkSortType m_eSortType;
DECL_LINK(async_signal_changed, void*, void);
@@ -5379,13 +5381,22 @@ private:
pThis->signal_visible_range_changed();
}
+ int get_model_col(int viewcol) const
+ {
+ return m_aViewColToModelCol[viewcol];
+ }
+
+ int get_view_col(int modelcol) const
+ {
+ return m_aModelColToViewCol[modelcol];
+ }
+
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_nTextCol(-1)
- , m_nTextColHeader(-1)
, m_nImageCol(-1)
, m_nExpanderImageCol(-1)
, m_nChangedSignalId(g_signal_connect(gtk_tree_view_get_selection(pTreeView), "changed",
@@ -5393,10 +5404,9 @@ public:
, m_nRowActivatedSignalId(g_signal_connect(pTreeView, "row-activated", G_CALLBACK(signalRowActivated), this))
, m_nTestExpandRowSignalId(g_signal_connect(pTreeView, "test-expand-row", G_CALLBACK(signalTestExpandRow), this))
, m_nVAdjustmentChangedSignalId(0)
- , m_eSortType(GTK_SORT_ASCENDING)
{
m_pColumns = gtk_tree_view_get_columns(m_pTreeView);
- int nIndex(0), nHeader(0);
+ int nIndex(0);
for (GList* pEntry = g_list_first(m_pColumns); pEntry; pEntry = g_list_next(pEntry))
{
GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
@@ -5408,7 +5418,6 @@ public:
if (m_nTextCol == -1 && GTK_IS_CELL_RENDERER_TEXT(pCellRenderer))
{
m_nTextCol = nIndex;
- m_nTextColHeader = nHeader;
}
else if (GTK_IS_CELL_RENDERER_TOGGLE(pCellRenderer))
{
@@ -5424,10 +5433,11 @@ public:
else if (m_nImageCol == -1)
m_nImageCol = nIndex;
}
+ m_aModelColToViewCol.push_back(m_aViewColToModelCol.size());
++nIndex;
}
g_list_free(pRenderers);
- ++nHeader;
+ m_aViewColToModelCol.push_back(nIndex - 1);
}
m_nIdCol = nIndex++;
for (auto& a : m_aToggleVisMap)
@@ -5472,7 +5482,8 @@ public:
}
virtual void insert(weld::TreeIter* pParent, int pos, const OUString* pText, const OUString* pId, const OUString* pIconName,
- VirtualDevice* pImageSurface, const OUString* pExpanderName, bool bChildrenOnDemand) override
+ VirtualDevice* pImageSurface, const OUString* pExpanderName,
+ bool bChildrenOnDemand, weld::TreeIter* pRet) override
{
disable_notify_events();
GtkTreeIter iter;
@@ -5484,6 +5495,11 @@ public:
OUString sDummy("<dummy>");
insert_row(subiter, &iter, -1, nullptr, &sDummy, nullptr, nullptr, nullptr);
}
+ if (pRet)
+ {
+ GtkInstanceTreeIter* pGtkRetIter = static_cast<GtkInstanceTreeIter*>(pRet);
+ pGtkRetIter->iter = iter;
+ }
enable_notify_events();
}
@@ -5560,18 +5576,66 @@ public:
virtual void set_sort_order(bool bAscending) override
{
- m_eSortType = bAscending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
+ GtkSortType eSortType = bAscending ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
+
+ gint sort_column_id(0);
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, m_eSortType);
- GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, m_nTextColHeader));
- assert(pColumn && "wrong count");
- if (gtk_tree_view_column_get_sort_indicator(pColumn))
- gtk_tree_view_column_set_sort_order(pColumn, m_eSortType);
+ 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
{
- return m_eSortType == GTK_SORT_ASCENDING;
+ GtkSortType eSortType;
+
+ GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
+ gtk_tree_sortable_get_sort_column_id(pSortable, nullptr, &eSortType);
+ return eSortType == GTK_SORT_ASCENDING;
+ }
+
+ virtual void set_sort_indicator(TriState eState, int col) override
+ {
+ if (col == -1)
+ col = get_view_col(m_nTextCol);
+
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, col));
+ assert(pColumn && "wrong count");
+ if (eState == TRISTATE_INDET)
+ gtk_tree_view_column_set_sort_indicator(pColumn, false);
+ else
+ {
+ gtk_tree_view_column_set_sort_indicator(pColumn, true);
+ GtkSortType eSortType = eState == TRISTATE_TRUE ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
+ gtk_tree_view_column_set_sort_order(pColumn, eSortType);
+ }
+ }
+
+ virtual TriState get_sort_indicator(int col) const override
+ {
+ if (col == -1)
+ col = get_view_col(m_nTextCol);
+
+ GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(g_list_nth_data(m_pColumns, col));
+ if (!gtk_tree_view_column_get_sort_indicator(pColumn))
+ return TRISTATE_INDET;
+ return gtk_tree_view_column_get_sort_order(pColumn) == GTK_SORT_ASCENDING ? TRISTATE_TRUE : TRISTATE_FALSE;
+ }
+
+ virtual int get_sort_column() const override
+ {
+ GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
+ gint sort_column_id(0);
+ if (!gtk_tree_sortable_get_sort_column_id(pSortable, &sort_column_id, nullptr))
+ return -1;
+ return get_view_col(sort_column_id);
+ }
+
+ virtual void set_sort_column(int nColumn) override
+ {
+ GtkSortType eSortType;
+ GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
+ gtk_tree_sortable_get_sort_column_id(pSortable, nullptr, &eSortType);
+ gtk_tree_sortable_set_sort_column_id(pSortable, get_model_col(nColumn), eSortType);
}
virtual int n_children() const override
@@ -5707,23 +5771,26 @@ public:
{
if (col == -1)
return get(pos, m_nTextCol);
- return get(pos, col);
+ return get(pos, get_model_col(col));
}
virtual void set_text(int pos, const OUString& rText, int col) override
{
if (col == -1)
col = m_nTextCol;
+ else
+ col = get_model_col(col);
return set(pos, col, rText);
}
virtual bool get_toggle(int pos, int col) const override
{
- return get_bool(pos, col);
+ return get_bool(pos, get_model_col(col));
}
virtual void set_toggle(int pos, bool bOn, int col) override
{
+ col = get_model_col(col);
// checkbuttons are invisible until toggled on or off
set(pos, m_aToggleVisMap[col], true);
return set(pos, col, bOn);
@@ -5959,6 +6026,8 @@ public:
const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
if (col == -1)
col = m_nTextCol;
+ else
+ col = get_model_col(col);
return get(rGtkIter.iter, col);
}
@@ -5967,18 +6036,21 @@ public:
GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter);
if (col == -1)
col = m_nTextCol;
+ else
+ col = get_model_col(col);
set(rGtkIter.iter, col, rText);
}
virtual OUString get_id(const weld::TreeIter& rIter) const override
{
const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
- GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore);
- gchar* pStr;
- gtk_tree_model_get(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter), m_nIdCol, &pStr, -1);
- OUString sRet(pStr, pStr ? strlen(pStr) : 0, RTL_TEXTENCODING_UTF8);
- g_free(pStr);
- return sRet;
+ return get(rGtkIter.iter, m_nIdCol);
+ }
+
+ virtual void set_id(weld::TreeIter& rIter, const OUString& rId) override
+ {
+ GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rIter);
+ set(rGtkIter.iter, m_nIdCol, rId);
}
virtual void set_expander_image(const weld::TreeIter& rIter, const OUString& rExpanderName) override
@@ -6000,8 +6072,14 @@ public:
gtk_tree_view_set_model(m_pTreeView, nullptr);
if (m_xSorter)
{
+ int nSortColumn;
+ GtkSortType eSortType;
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, m_eSortType);
+ 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);
+
+ m_aSavedSortColumns.push_back(nSortColumn);
+ m_aSavedSortTypes.push_back(eSortType);
}
enable_notify_events();
}
@@ -6012,7 +6090,9 @@ public:
if (m_xSorter)
{
GtkTreeSortable* pSortable = GTK_TREE_SORTABLE(m_pTreeStore);
- gtk_tree_sortable_set_sort_column_id(pSortable, m_nTextCol, m_eSortType);
+ 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));
GtkInstanceContainer::thaw();
@@ -6119,7 +6199,7 @@ public:
int starts_with(const OUString& rStr, int col, int nStartRow)
{
- return ::starts_with(GTK_TREE_MODEL(m_pTreeStore), rStr, col, nStartRow);
+ return ::starts_with(GTK_TREE_MODEL(m_pTreeStore), rStr, get_model_col(col), nStartRow);
}
virtual void disable_notify_events() override