sw/qa/uitest/writer_tests/trackedChanges.py | 65 ++++++++++++++++++++++++++++ sw/source/uibase/inc/redlndlg.hxx | 3 + sw/source/uibase/misc/redlndlg.cxx | 13 +++++ 3 files changed, 80 insertions(+), 1 deletion(-)
New commits: commit 952fb2a4386a6ae2187b646e372131a5345f59fe Author: László Németh <nem...@numbertext.org> AuthorDate: Thu Jun 22 17:33:16 2023 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Fri Jun 23 10:29:33 2023 +0200 tdf#155847 sw tracked table column: fix crash in Manage Changes In Manage Changes dialog window, accept/Reject multiple tracked table columns need major tree list update because of not continuous redline ranges in the child lists of the multiple tree list parents, otherwise assert/crash could occur. Follow-up to commit 4a40a42afc3ba551e6e58947fc2e44689979b629 "tdf#155847 sw tracked table column: manage multiple changes". Change-Id: I3c7f61d35cbb433067c1f4fd28b80ad7da8ba12e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153464 Tested-by: László Németh <nem...@numbertext.org> Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/sw/qa/uitest/writer_tests/trackedChanges.py b/sw/qa/uitest/writer_tests/trackedChanges.py index 0b0c38d27533..8681140bb695 100644 --- a/sw/qa/uitest/writer_tests/trackedChanges.py +++ b/sw/qa/uitest/writer_tests/trackedChanges.py @@ -597,4 +597,69 @@ class trackedchanges(UITestCase): self.assertEqual(0, len(changesList.getChildren())) + def test_tdf155847_multiple_tracked_columns_crash(self): + with self.ui_test.load_file(get_url_for_data_file("TC-table-del-add.docx")) as document: + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + # accept all changes and insert new columns with change tracking + self.xUITest.executeCommand(".uno:AcceptAllTrackedChanges") + tables = document.getTextTables() + self.assertEqual(2, len(tables)) + self.assertEqual(len(tables[0].getColumns()), 3) + self.xUITest.executeCommand(".uno:InsertColumnsAfter") + self.xUITest.executeCommand(".uno:DeleteColumns") + self.assertEqual(len(tables[0].getColumns()), 4) + + xToolkit = self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit') + xToolkit.processEventsToIdle() + + # check and reject changes + with self.ui_test.execute_modeless_dialog_through_command(".uno:AcceptTrackedChanges", close_button="close") as xTrackDlg: + changesList = xTrackDlg.getChild("writerchanges") + + # six changes, but only one visible in the Manage Changes dialog window + state = get_state_as_dict(changesList) + self.assertEqual(state['Children'], '6') + + # This was 4 (missing handling of multiple different columns) + self.assertEqual(state['VisibleCount'], '2') + # Now: 2 changes (deleted and inserted columns) + self.assertEqual(2, len(changesList.getChildren())) + + # select second tracked table column in tree list + xToolkit = self.xContext.ServiceManager.createInstance('com.sun.star.awt.Toolkit') + changesList.executeAction("TYPE", mkPropertyValues({"KEYCODE": "DOWN"})) + + # while not empty, i.e. starts with CH_TXT_TRACKED_DUMMY_CHAR + while len(get_state_as_dict(xWriterEdit)["SelectedText"]): + xToolkit.processEventsToIdle() + + # reject column insertion + + xAccBtn = xTrackDlg.getChild("reject") + # Without the fix in place, it would have crashed here + xAccBtn.executeAction("CLICK", tuple()) + + # inserted column is removed + + self.assertEqual(len(tables[0].getColumns()), 3) + + # single parent left in the dialog window + self.assertEqual(1, len(changesList.getChildren())) + + # accept column deletion + + xAccBtn = xTrackDlg.getChild("accept") + xAccBtn.executeAction("CLICK", tuple()) + + # deleted column is removed + + self.assertEqual(len(tables[0].getColumns()), 2) + + # no changes in the dialog window + + self.assertEqual(0, len(changesList.getChildren())) + # vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sw/source/uibase/inc/redlndlg.hxx b/sw/source/uibase/inc/redlndlg.hxx index 7337f1fadce4..c8cfd8cc8262 100644 --- a/sw/source/uibase/inc/redlndlg.hxx +++ b/sw/source/uibase/inc/redlndlg.hxx @@ -77,6 +77,9 @@ class SW_DLLPUBLIC SwRedlineAcceptDlg final // prevent update dialog data during longer operations (cf #102657#) bool m_bInhibitActivate; + // table column changes have not continuous redline ranges: it needs major tree list update + bool m_bHasTrackedColumn; + std::unique_ptr<SvxAcceptChgCtr> m_xTabPagesCTRL; std::unique_ptr<weld::Menu> m_xPopup, m_xSortMenu; SvxTPView* m_pTPView; diff --git a/sw/source/uibase/misc/redlndlg.cxx b/sw/source/uibase/misc/redlndlg.cxx index 35a15fa940e3..1a9d168bee61 100644 --- a/sw/source/uibase/misc/redlndlg.cxx +++ b/sw/source/uibase/misc/redlndlg.cxx @@ -153,6 +153,7 @@ SwRedlineAcceptDlg::SwRedlineAcceptDlg(std::shared_ptr<weld::Window> xParent, we , m_bOnlyFormatedRedlines(false) , m_bRedlnAutoFormat(bAutoFormat) , m_bInhibitActivate(false) + , m_bHasTrackedColumn(false) , m_xTabPagesCTRL(new SvxAcceptChgCtr(pContentArea)) , m_xPopup(pBuilder->weld_menu("writermenu")) , m_xSortMenu(pBuilder->weld_menu("writersortmenu")) @@ -489,7 +490,7 @@ void SwRedlineAcceptDlg::Activate() SwRedlineTable::size_type SwRedlineAcceptDlg::CalcDiff(SwRedlineTable::size_type nStart, bool bChild) { - if (!nStart) + if (!nStart || m_bHasTrackedColumn) { Init(); return SwRedlineTable::npos; @@ -767,6 +768,10 @@ void SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli SwRedlineTable::size_type nCount = pSh->GetRedlineCount(); nEnd = std::min(nEnd, (nCount - 1)); // also treats nEnd=SwRedlineTable::npos (until the end) + // reset m_bHasTrackedColumn before searching tracked column again + if ( m_bHasTrackedColumn && nStart == 0 ) + m_bHasTrackedColumn = false; + if (nEnd == SwRedlineTable::npos) return; // no redlines in the document @@ -872,6 +877,12 @@ void SwRedlineAcceptDlg::InsertParents(SwRedlineTable::size_type nStart, SwRedli // table redline didn't fit in the stored ones, create new parent aTableParents.push_back(i); } + + // it needs major tree update later because of tracked table columns + if ( !m_bHasTrackedColumn && !bRowChange ) + { + m_bHasTrackedColumn = true; + } } else {