tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / sw / qa / extras / uiwriter / uiwriter5.cxx
blob73c1a95f4395c891bcc58df50d04bf725d01cde6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <swmodeltestbase.hxx>
12 #include <boost/property_tree/json_parser.hpp>
14 #include <com/sun/star/awt/FontSlant.hpp>
15 #include <com/sun/star/awt/FontUnderline.hpp>
16 #include <com/sun/star/awt/FontWeight.hpp>
17 #include <com/sun/star/chart/XChartDocument.hpp>
18 #include <com/sun/star/chart2/XChartDocument.hpp>
19 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
20 #include <com/sun/star/view/XSelectionSupplier.hpp>
21 #include <com/sun/star/text/XTextTable.hpp>
22 #include <comphelper/propertysequence.hxx>
23 #include <comphelper/propertyvalue.hxx>
24 #include <comphelper/configuration.hxx>
25 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
26 #include <vcl/scheduler.hxx>
27 #include <vcl/settings.hxx>
28 #include <ndtxt.hxx>
29 #include <swdtflvr.hxx>
30 #include <wrtsh.hxx>
31 #include <IDocumentRedlineAccess.hxx>
32 #include <flyfrm.hxx>
33 #include <fmtanchr.hxx>
34 #include <UndoManager.hxx>
35 #include <sortedobjs.hxx>
36 #include <xmloff/odffields.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <comphelper/lok.hxx>
40 #include <txtfrm.hxx>
41 #include <tabfrm.hxx>
42 #include <view.hxx>
43 #include <cmdid.h>
44 #include <AnnotationWin.hxx>
45 #include <PostItMgr.hxx>
46 #include <fmtcntnt.hxx>
47 #include <frameformats.hxx>
48 #include <shellio.hxx>
49 #include <editeng/fontitem.hxx>
50 #include <tools/json_writer.hxx>
51 #include <unotxdoc.hxx>
52 #include <IDocumentLayoutAccess.hxx>
53 #include <rootfrm.hxx>
54 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
55 #include <redline.hxx>
57 /// Second set of tests asserting the behavior of Writer user interface shells.
58 class SwUiWriterTest5 : public SwModelTestBase
60 public:
61 SwUiWriterTest5()
62 : SwModelTestBase(u"/sw/qa/extras/uiwriter/data/"_ustr)
66 protected:
67 AllSettings m_aSavedSettings;
70 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf139127)
72 createSwDoc("tdf139127.fodt");
73 SwDoc* pDoc = getSwDoc();
75 // switch on "Show changes in margin" mode
76 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
78 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
79 CPPUNIT_ASSERT(pWrtShell->GetViewOptions()->IsShowChangesInMargin());
81 // turn on red-lining and show changes
82 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowInsert
83 | RedlineFlags::ShowDelete);
84 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
85 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
86 CPPUNIT_ASSERT_MESSAGE(
87 "redlines should be visible",
88 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
90 // two pages
91 CPPUNIT_ASSERT_EQUAL(2, getPages());
93 // delete the last two characters with a page break at the end of the document
94 dispatchCommand(mxComponent, u".uno:GoToEndOfDoc"_ustr, {});
95 dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
96 dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
97 CPPUNIT_ASSERT_EQUAL(1, getPages());
98 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
99 CPPUNIT_ASSERT_EQUAL(u"First page"_ustr, xTextDocument->getText()->getString());
101 // Undo
102 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
103 // this would crash due to bad redline range
104 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
105 CPPUNIT_ASSERT_EQUAL(2, getPages());
106 CPPUNIT_ASSERT_EQUAL(u"First page"_ustr, getParagraph(1)->getString());
107 CPPUNIT_ASSERT_EQUAL(u"B"_ustr, getParagraph(2)->getString());
109 // switch off "Show changes in margin" mode
110 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
111 CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
114 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138479)
116 createSwDoc();
117 SwDoc* const pDoc = getSwDoc();
119 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
121 pWrtShell->Insert(u"Lorem"_ustr);
122 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, getParagraph(1)->getString());
124 //turn on red-lining and show changes
125 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
126 | RedlineFlags::ShowInsert);
127 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
128 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
129 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
130 CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible",
131 !IDocumentRedlineAccess::IsShowChanges(
132 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
134 // switch on "Show changes in margin" mode
135 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
137 // delete "r" in "Lorem"
138 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 3, /*bBasicCall=*/false);
139 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
140 CPPUNIT_ASSERT_EQUAL(u"Loem"_ustr, getParagraph(1)->getString());
142 // delete "oe" in "Loem"
143 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
144 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 2, /*bBasicCall=*/false);
145 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
146 CPPUNIT_ASSERT_EQUAL(u"Lm"_ustr, getParagraph(1)->getString());
148 // test embedded Undo in ChangesInMargin mode
149 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
150 CPPUNIT_ASSERT_EQUAL(u"Loem"_ustr, getParagraph(1)->getString());
152 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
153 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, getParagraph(1)->getString());
155 // this would crash due to bad redline range
156 for (int i = 0; i < 5; ++i)
157 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
159 // switch off "Show changes in margin" mode
160 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
161 CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
164 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138666)
166 createSwDoc("tdf39721.fodt");
167 SwDoc* pDoc = getSwDoc();
169 //turn on red-lining and show changes
170 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
171 | RedlineFlags::ShowInsert);
172 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
173 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
174 CPPUNIT_ASSERT_MESSAGE(
175 "redlines should be visible",
176 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
178 // show deletions inline
179 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, getParagraph(1)->getString());
180 CPPUNIT_ASSERT_EQUAL(u"dolor sit"_ustr, getParagraph(2)->getString());
182 // switch on "Show changes in margin" mode
183 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
185 // show deletions in margin
186 CPPUNIT_ASSERT_EQUAL(u"Loremm"_ustr, getParagraph(1)->getString());
187 CPPUNIT_ASSERT_EQUAL(u"dolsit"_ustr, getParagraph(2)->getString());
189 // switch off "Show changes in margin" mode
190 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
192 // show deletions inline again
193 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, getParagraph(1)->getString());
194 CPPUNIT_ASSERT_EQUAL(u"dolor sit"_ustr, getParagraph(2)->getString());
197 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf140982)
199 createSwDoc("tdf115815.odt");
200 SwDoc* pDoc = getSwDoc();
202 //turn on red-lining and show changes
203 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
204 | RedlineFlags::ShowInsert);
205 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
206 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
207 CPPUNIT_ASSERT_MESSAGE(
208 "redlines should be visible",
209 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
211 // show deletions inline
212 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum dolor sit amet..."_ustr, getParagraph(1)->getString());
214 // switch on "Show changes in margin" mode
215 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
217 // show deletions in margin
218 CPPUNIT_ASSERT_EQUAL(u"Lorem amet..."_ustr, getParagraph(1)->getString());
220 // switch off "Show changes in margin" mode
221 dispatchCommand(mxComponent, u".uno:ShowChangesInMargin"_ustr, {});
223 // show deletions inline again
224 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum dolor sit amet..."_ustr, getParagraph(1)->getString());
226 // Save it and load it back.
227 saveAndReload(u"writer8"_ustr);
229 // Test comment range feature on tracked deletion.
230 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
231 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
232 uno::UNO_QUERY);
233 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
234 uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
235 uno::UNO_QUERY);
236 uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
237 bool bAnnotationStart = false;
238 bool bBeforeAnnotation = true;
239 OUString sTextBeforeAnnotation;
240 while (xRunEnum->hasMoreElements())
242 uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
243 OUString aType = getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr);
244 // there is no AnnotationEnd with preceding AnnotationStart,
245 // i.e. annotation with lost range
246 CPPUNIT_ASSERT(aType != "AnnotationEnd" || !bAnnotationStart);
248 bAnnotationStart = (aType == "Annotation");
250 // collect paragraph text before the first annotation
251 if (bBeforeAnnotation)
253 if (bAnnotationStart)
254 bBeforeAnnotation = false;
255 else if (aType == "Text")
257 uno::Reference<text::XTextRange> xRun(xPropertySet, uno::UNO_QUERY);
258 sTextBeforeAnnotation += xRun->getString();
263 // This was "Lorem ipsum" (collapsed annotation range)
264 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, sTextBeforeAnnotation);
267 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126206)
269 createSwDoc("tdf126206.docx");
271 // normal text (it was bold)
272 auto xText = getParagraph(1)->getText();
273 CPPUNIT_ASSERT(xText.is());
275 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 4)));
276 CPPUNIT_ASSERT(xCursor.is());
277 CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
278 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
279 getProperty<float>(xCursor, u"CharWeight"_ustr));
282 // reject tracked changes
283 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
285 // bold text again
286 xText = getParagraph(1)->getText();
287 CPPUNIT_ASSERT(xText.is());
289 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 3)));
290 CPPUNIT_ASSERT(xCursor.is());
291 CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
292 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
293 getProperty<float>(xCursor, u"CharWeight"_ustr));
297 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447)
299 createSwDoc("tdf126206.docx");
301 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
303 // bold text
304 auto xText = getParagraph(1)->getText();
305 CPPUNIT_ASSERT(xText.is());
307 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
308 CPPUNIT_ASSERT(xCursor.is());
309 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
310 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
311 getProperty<float>(xCursor, u"CharWeight"_ustr));
314 // remove bold formatting with change tracking
315 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
316 dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
318 xText = getParagraph(1)->getText();
319 CPPUNIT_ASSERT(xText.is());
321 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
322 CPPUNIT_ASSERT(xCursor.is());
323 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
324 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
325 getProperty<float>(xCursor, u"CharWeight"_ustr));
328 // reject tracked changes
329 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
331 // bold text again
332 xText = getParagraph(1)->getText();
333 CPPUNIT_ASSERT(xText.is());
335 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
336 CPPUNIT_ASSERT(xCursor.is());
337 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
338 // This was NORMAL
339 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
340 getProperty<float>(xCursor, u"CharWeight"_ustr));
344 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143918)
346 createSwDoc("tdf126206.docx");
348 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
350 // bold text
351 auto xText = getParagraph(1)->getText();
352 CPPUNIT_ASSERT(xText.is());
354 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
355 CPPUNIT_ASSERT(xCursor.is());
356 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
357 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
358 getProperty<float>(xCursor, u"CharWeight"_ustr));
361 // remove bold formatting with change tracking and after that, apply underline, too
362 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
363 dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
364 dispatchCommand(mxComponent, u".uno:Underline"_ustr, {});
366 xText = getParagraph(1)->getText();
367 CPPUNIT_ASSERT(xText.is());
369 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
370 CPPUNIT_ASSERT(xCursor.is());
371 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
372 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
373 getProperty<float>(xCursor, u"CharWeight"_ustr));
376 // reject tracked changes
377 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
379 // bold text again
380 xText = getParagraph(1)->getText();
381 CPPUNIT_ASSERT(xText.is());
383 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
384 CPPUNIT_ASSERT(xCursor.is());
385 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
386 // This was NORMAL (only underlining was removed)
387 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
388 getProperty<float>(xCursor, u"CharWeight"_ustr));
392 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143938)
394 createSwDoc("tdf54819.fodt");
395 SwDoc* pDoc = getSwDoc();
397 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
399 // select first paragraph, add underline without change tracking
400 pWrtShell->EndPara(/*bSelect=*/true);
401 dispatchCommand(mxComponent, u".uno:Underline"_ustr, {});
403 auto xText = getParagraph(1)->getText();
404 CPPUNIT_ASSERT(xText.is());
406 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
407 CPPUNIT_ASSERT(xCursor.is());
408 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, xCursor->getString());
409 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
410 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
411 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
412 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
415 // turn on red-lining and show changes
416 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
417 | RedlineFlags::ShowInsert);
418 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
419 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
420 CPPUNIT_ASSERT_MESSAGE(
421 "redlines should be visible",
422 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
424 // apply italic with change tracking
425 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
426 dispatchCommand(mxComponent, u".uno:Italic"_ustr, {});
428 xText = getParagraph(1)->getText();
429 CPPUNIT_ASSERT(xText.is());
431 // (first empty run is associated to the redline)
432 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
433 CPPUNIT_ASSERT(xCursor.is());
434 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, xCursor->getString());
435 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
436 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
437 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
438 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
441 // reject tracked changes
442 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
444 // no italic, but still underline direct formatting
445 xText = getParagraph(1)->getText();
446 CPPUNIT_ASSERT(xText.is());
448 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
449 CPPUNIT_ASSERT(xCursor.is());
450 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum"_ustr, xCursor->getString());
451 // This wasn't underlined (lost direct formatting)
452 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
453 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
454 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
455 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
459 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143939)
461 createSwDoc("tdf126206.docx");
463 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
465 // bold text
466 auto xText = getParagraph(1)->getText();
467 CPPUNIT_ASSERT(xText.is());
469 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
470 CPPUNIT_ASSERT(xCursor.is());
471 CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, xCursor->getString());
472 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
473 getProperty<float>(xCursor, u"CharWeight"_ustr));
476 // positionate the text cursor inside the first word
477 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
478 // remove bold formatting with change tracking without selection
479 dispatchCommand(mxComponent, u".uno:Bold"_ustr, {});
481 xText = getParagraph(1)->getText();
482 CPPUNIT_ASSERT(xText.is());
484 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
485 CPPUNIT_ASSERT(xCursor.is());
486 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString());
487 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL,
488 getProperty<float>(xCursor, u"CharWeight"_ustr));
491 // reject tracked changes
492 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
494 // bold text again
495 xText = getParagraph(1)->getText();
496 CPPUNIT_ASSERT(xText.is());
498 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
499 CPPUNIT_ASSERT(xCursor.is());
500 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString());
501 // This was NORMAL
502 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
503 getProperty<float>(xCursor, u"CharWeight"_ustr));
507 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447_keep_hints)
509 createSwDoc("tdf50447.fodt");
510 SwDoc* pDoc = getSwDoc();
512 // first paragraph (_Lorem_ /ipsum/)
514 auto xText = getParagraph(1)->getText();
515 CPPUNIT_ASSERT(xText.is());
517 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
518 CPPUNIT_ASSERT(xCursor.is());
519 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString());
520 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
521 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
522 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
523 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
525 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
526 CPPUNIT_ASSERT(xCursor.is());
527 CPPUNIT_ASSERT_EQUAL(u" "_ustr, xCursor->getString());
528 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
529 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
530 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
531 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
533 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
534 CPPUNIT_ASSERT(xCursor.is());
535 CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
536 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
537 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
538 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
539 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
542 // second paragraph (_dolor_ sit /amet/.)
544 xText = getParagraph(2)->getText();
545 CPPUNIT_ASSERT(xText.is());
547 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
548 CPPUNIT_ASSERT(xCursor.is());
549 CPPUNIT_ASSERT_EQUAL(u"dolor"_ustr, xCursor->getString());
550 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
551 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
552 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
553 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
555 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
556 CPPUNIT_ASSERT(xCursor.is());
557 CPPUNIT_ASSERT_EQUAL(u" sit "_ustr, xCursor->getString());
558 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
559 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
560 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
561 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
563 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
564 CPPUNIT_ASSERT(xCursor.is());
565 CPPUNIT_ASSERT_EQUAL(u"amet"_ustr, xCursor->getString());
566 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
567 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
568 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
569 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
572 // turn on red-lining and show changes
573 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
574 | RedlineFlags::ShowInsert);
575 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
576 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
577 CPPUNIT_ASSERT_MESSAGE(
578 "redlines should be visible",
579 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
581 // modify character formatting of the all the text
583 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
584 dispatchCommand(mxComponent, u".uno:SuperScript"_ustr, {});
586 // multiple format redlines for the multiple hints
588 SwEditShell* const pEditShell(pDoc->GetEditShell());
589 CPPUNIT_ASSERT(pEditShell);
590 // This was 1.
591 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
593 // reject tracked changes
595 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
597 // all hints and text portions between them got back the original formatting
599 xText = getParagraph(1)->getText();
600 CPPUNIT_ASSERT(xText.is());
602 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
603 CPPUNIT_ASSERT(xCursor.is());
604 CPPUNIT_ASSERT_EQUAL(u"Lorem"_ustr, xCursor->getString());
605 // This was NONE
606 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
607 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
608 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
609 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
611 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
612 CPPUNIT_ASSERT(xCursor.is());
613 CPPUNIT_ASSERT_EQUAL(u" "_ustr, xCursor->getString());
614 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
615 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
616 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
617 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
619 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
620 CPPUNIT_ASSERT(xCursor.is());
621 CPPUNIT_ASSERT_EQUAL(u"ipsum"_ustr, xCursor->getString());
622 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
623 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
624 // This was NONE
625 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
626 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
629 // second paragraph (_dolor_ sit /amet/.)
631 xText = getParagraph(2)->getText();
632 CPPUNIT_ASSERT(xText.is());
634 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
635 CPPUNIT_ASSERT(xCursor.is());
636 CPPUNIT_ASSERT_EQUAL(u"dolor"_ustr, xCursor->getString());
637 // This was NONE
638 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
639 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
640 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
641 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
643 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
644 CPPUNIT_ASSERT(xCursor.is());
645 CPPUNIT_ASSERT_EQUAL(u" sit "_ustr, xCursor->getString());
646 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
647 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
648 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
649 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
651 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
652 CPPUNIT_ASSERT(xCursor.is());
653 CPPUNIT_ASSERT_EQUAL(u"amet"_ustr, xCursor->getString());
654 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
655 getProperty<sal_Int16>(xCursor, u"CharUnderline"_ustr));
656 // This was NONE
657 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
658 getProperty<awt::FontSlant>(xCursor, u"CharPosture"_ustr));
662 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144272)
664 createSwDoc("tdf50447.fodt");
665 SwDoc* pDoc = getSwDoc();
667 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
669 // turn on red-lining and show changes
670 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
671 | RedlineFlags::ShowInsert);
672 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
673 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
674 CPPUNIT_ASSERT_MESSAGE(
675 "redlines should be visible",
676 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
678 // paragraph style of the first paragraph: Heading 1, second paragraph: Standard
680 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
681 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
682 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
683 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
685 // modify with track changes: Standard and Heading 2
687 uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
688 { "Style", uno::Any(u"Standard"_ustr) },
689 { "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
691 dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
692 pWrtShell->Down(/*bSelect=*/false);
693 aPropertyValues = comphelper::InitPropertySequence({
694 { "Style", uno::Any(u"Heading 2"_ustr) },
695 { "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
697 dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
699 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
700 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
701 CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
702 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
704 // reject tracked changes
705 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
707 // This was Standard (missing reject)
708 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
709 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
710 // This was Heading 2 (missing reject)
711 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
712 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
715 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf101873)
717 createSwDoc();
718 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
719 CPPUNIT_ASSERT(pWrtShell);
721 // Insert some content.
722 pWrtShell->Insert(u"something"_ustr);
724 // Search for something which does not exist, twice.
725 uno::Sequence<beans::PropertyValue> aFirst(comphelper::InitPropertySequence({
726 { "SearchItem.SearchString", uno::Any(u"fig"_ustr) },
727 { "SearchItem.Backward", uno::Any(false) },
728 }));
729 dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aFirst);
730 dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aFirst);
732 uno::Sequence<beans::PropertyValue> aSecond(comphelper::InitPropertySequence({
733 { "SearchItem.SearchString", uno::Any(u"something"_ustr) },
734 { "SearchItem.Backward", uno::Any(false) },
735 }));
736 dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aSecond);
738 // Without the accompanying fix in place, this test would have failed with "Expected: something;
739 // Actual:", i.e. searching for "something" failed, even if it was inserted above.
740 SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
741 CPPUNIT_ASSERT_EQUAL(u"something"_ustr, pShellCursor->GetText());
744 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTextFormFieldInsertion)
746 createSwDoc();
747 SwDoc* pDoc = getSwDoc();
748 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
749 CPPUNIT_ASSERT(pMarkAccess);
750 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
752 // Insert a text form field
753 dispatchCommand(mxComponent, u".uno:TextFormField"_ustr, {});
754 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
756 // Check whether the fieldmark is created
757 auto aIter = pMarkAccess->getAllMarksBegin();
758 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
759 ::sw::mark::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
760 CPPUNIT_ASSERT(pFieldmark);
761 CPPUNIT_ASSERT_EQUAL(ODF_FORMTEXT, pFieldmark->GetFieldname());
763 // The text form field has the placeholder text in it
764 uno::Reference<text::XTextRange> xPara = getParagraph(1);
765 CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
767 // Undo insertion
768 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
769 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
770 xPara.set(getParagraph(1));
771 CPPUNIT_ASSERT(xPara->getString().isEmpty());
773 // Redo insertion
774 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
775 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
776 xPara.set(getParagraph(1));
777 CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
780 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testCheckboxFormFieldInsertion)
782 createSwDoc();
783 SwDoc* pDoc = getSwDoc();
785 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
786 CPPUNIT_ASSERT(pMarkAccess);
787 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
789 // Insert a checkbox form field
790 dispatchCommand(mxComponent, u".uno:CheckBoxFormField"_ustr, {});
791 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
793 // Check whether the fieldmark is created
794 auto aIter = pMarkAccess->getAllMarksBegin();
795 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
796 ::sw::mark::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
797 CPPUNIT_ASSERT(pFieldmark);
798 CPPUNIT_ASSERT_EQUAL(ODF_FORMCHECKBOX, pFieldmark->GetFieldname());
799 // The checkbox is not checked by default
800 ::sw::mark::CheckboxFieldmark* pCheckBox
801 = dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark);
802 CPPUNIT_ASSERT(pCheckBox);
803 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
805 // Undo insertion
806 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
807 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
809 // Redo insertion
810 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
811 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
812 aIter = pMarkAccess->getAllMarksBegin();
813 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
814 pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
815 CPPUNIT_ASSERT(pFieldmark);
816 CPPUNIT_ASSERT_EQUAL(ODF_FORMCHECKBOX, pFieldmark->GetFieldname());
818 // tdf#147008 this would crash
819 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
820 pWrtShell->StartOfSection(false);
821 pWrtShell->SplitNode();
822 CPPUNIT_ASSERT_EQUAL(pFieldmark->GetMarkPos().GetNodeIndex(),
823 pFieldmark->GetOtherMarkPos().GetNodeIndex());
824 CPPUNIT_ASSERT_EQUAL(sal_Int32(pFieldmark->GetMarkPos().GetContentIndex() + 1),
825 pFieldmark->GetOtherMarkPos().GetContentIndex());
828 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDropDownFormFieldInsertion)
830 createSwDoc();
831 SwDoc* pDoc = getSwDoc();
833 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
834 CPPUNIT_ASSERT(pMarkAccess);
835 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
837 // Insert a drop-down form field
838 dispatchCommand(mxComponent, u".uno:DropDownFormField"_ustr, {});
839 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
841 // Check whether the fieldmark is created
842 auto aIter = pMarkAccess->getAllMarksBegin();
843 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
844 ::sw::mark::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
845 CPPUNIT_ASSERT(pFieldmark);
846 CPPUNIT_ASSERT_EQUAL(ODF_FORMDROPDOWN, pFieldmark->GetFieldname());
847 // Check drop down field's parameters. By default these params are not set
848 const sw::mark::Fieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
849 auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
850 CPPUNIT_ASSERT(bool(pListEntries == pParameters->end()));
851 auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
852 CPPUNIT_ASSERT(bool(pResult == pParameters->end()));
854 // Undo insertion
855 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
856 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
858 // Redo insertion
859 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
860 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
861 aIter = pMarkAccess->getAllMarksBegin();
862 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
863 pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
864 CPPUNIT_ASSERT(pFieldmark);
865 CPPUNIT_ASSERT_EQUAL(ODF_FORMDROPDOWN, pFieldmark->GetFieldname());
868 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testMixedFormFieldInsertion)
870 createSwDoc();
871 SwDoc* pDoc = getSwDoc();
873 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
874 CPPUNIT_ASSERT(pMarkAccess);
875 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
877 // Insert fields
878 dispatchCommand(mxComponent, u".uno:TextFormField"_ustr, {});
879 dispatchCommand(mxComponent, u".uno:CheckBoxFormField"_ustr, {});
880 dispatchCommand(mxComponent, u".uno:DropDownFormField"_ustr, {});
881 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
883 // Undo insertion
884 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
885 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
886 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
887 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
889 // Redo insertion
890 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
891 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
892 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
893 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
896 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147723)
898 createSwDoc("tdf147723.docx");
899 SwDoc* const pDoc = getSwDoc();
901 IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
902 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
904 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
905 dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
907 // Without the fix in place, this test would have crashed here
908 dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
909 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
910 dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
911 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), rIDMA.getAllMarksCount());
912 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
913 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
914 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
915 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
918 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147006)
920 createSwDoc("tdf147006.rtf");
921 SwDoc* const pDoc = getSwDoc();
923 IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
924 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
925 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
926 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
927 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getFieldmarksCount());
929 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
930 // this crashed
931 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
932 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
933 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
934 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
935 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
936 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
937 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
938 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
939 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
940 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
941 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
942 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
943 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
944 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
945 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
946 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
947 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
948 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
949 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
950 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
953 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDocxAttributeTableExport)
955 createSwDoc("floating-table-position.docx");
957 // get the table frame, set new values and dismiss the references
959 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
961 // change the properties
962 // 8133 -> 8000
963 xShape->setPropertyValue(u"VertOrientPosition"_ustr,
964 uno::Any(static_cast<sal_Int32>(8000)));
965 // 5964 -> 5000
966 xShape->setPropertyValue(u"HoriOrientPosition"_ustr,
967 uno::Any(static_cast<sal_Int32>(5000)));
968 // 0 (frame) -> 8 (page print area)
969 xShape->setPropertyValue(u"VertOrientRelation"_ustr, uno::Any(static_cast<sal_Int16>(8)));
970 // 8 (page print area) -> 0 (frame)
971 xShape->setPropertyValue(u"HoriOrientRelation"_ustr, uno::Any(static_cast<sal_Int16>(0)));
973 // save it to docx
974 saveAndReload(u"Office Open XML Text"_ustr);
976 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
978 // test the new values
979 sal_Int32 nValue = getProperty<sal_Int32>(xShape, u"VertOrientPosition"_ustr);
980 CPPUNIT_ASSERT(sal_Int32(7999) <= nValue);
981 CPPUNIT_ASSERT(nValue <= sal_Int32(8001));
982 nValue = getProperty<sal_Int32>(xShape, u"HoriOrientPosition"_ustr);
983 CPPUNIT_ASSERT(sal_Int32(4999) <= nValue);
984 CPPUNIT_ASSERT(nValue <= sal_Int32(5001));
986 CPPUNIT_ASSERT_EQUAL(sal_Int16(8), getProperty<sal_Int16>(xShape, u"VertOrientRelation"_ustr));
987 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape, u"HoriOrientRelation"_ustr));
990 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118699_redline_numbering)
992 createSwDoc("tdf118699.docx");
993 SwDoc* pDoc = getSwDoc();
995 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
996 rIDRA.AcceptAllRedline(true);
998 uno::Reference<beans::XPropertySet> xProps(getParagraph(2), uno::UNO_QUERY_THROW);
999 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
1000 !xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
1002 CPPUNIT_ASSERT_MESSAGE("first paragraph after the second deletion: missing numbering",
1003 getProperty<uno::Reference<container::XIndexAccess>>(
1004 getParagraph(5), u"NumberingRules"_ustr)
1005 .is());
1008 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125881_redline_list_level)
1010 createSwDoc("tdf125881.docx");
1012 uno::Reference<beans::XPropertySet> xProps(getParagraph(8), uno::UNO_QUERY_THROW);
1013 CPPUNIT_ASSERT_MESSAGE("deleted paragraph: erroneous numbering",
1014 !xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
1016 // deleted paragraph gets the numbering of the next paragraph
1017 uno::Reference<beans::XPropertySet> xProps2(getParagraph(9), uno::UNO_QUERY_THROW);
1018 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: missing numbering",
1019 xProps2->getPropertyValue(u"NumberingRules"_ustr).hasValue());
1021 // check numbering level at deletion (1 instead of 0)
1022 CPPUNIT_ASSERT_EQUAL(sal_Int16(1),
1023 getProperty<sal_Int16>(getParagraph(9), u"NumberingLevel"_ustr));
1026 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125916_redline_restart_numbering)
1028 createSwDoc("tdf125916.docx");
1029 SwDoc* pDoc = getSwDoc();
1031 // moveFrom/moveTo are imported as separated redlines from fixing tdf#145718.
1032 // Accept the first inline moveFrom redline before accepting the remaining ones
1033 // to leave a paragraph long deletion to test the fix for tdf#125916.
1034 SwEditShell* const pEditShell(pDoc->GetEditShell());
1035 CPPUNIT_ASSERT(pEditShell);
1036 CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
1037 pEditShell->AcceptRedline(0);
1039 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1040 rIDRA.AcceptAllRedline(true);
1042 // check unnecessary numbering
1043 uno::Reference<beans::XPropertySet> xProps(getParagraph(3), uno::UNO_QUERY_THROW);
1044 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
1045 !xProps->getPropertyValue(u"NumberingRules"_ustr).hasValue());
1048 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310)
1050 createSwDoc("tdf125310.fodt");
1051 SwDoc* pDoc = getSwDoc();
1053 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1054 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
1055 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
1056 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
1057 CPPUNIT_ASSERT_EQUAL(1, getPages());
1059 // turn on red-lining and show changes
1060 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1061 | RedlineFlags::ShowInsert);
1062 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1063 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1064 CPPUNIT_ASSERT_MESSAGE(
1065 "redlines should be visible",
1066 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1068 // paragraph join
1069 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1070 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1071 pWrtShell->EndPara(/*bSelect=*/true);
1072 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1073 dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
1075 // copied paragraph style
1076 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1077 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
1079 // without copying the page break
1080 CPPUNIT_ASSERT_EQUAL(1, getPages());
1083 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310b)
1085 createSwDoc("tdf125310b.fodt");
1086 SwDoc* pDoc = getSwDoc();
1087 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1089 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
1090 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
1091 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1092 getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
1093 CPPUNIT_ASSERT_EQUAL(2, getPages());
1095 // turn on red-lining and show changes
1096 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1097 | RedlineFlags::ShowInsert);
1098 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1099 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1101 // remove second paragraph with the page break
1102 pWrtShell->Down(/*bSelect=*/false);
1103 pWrtShell->Down(/*bSelect=*/false);
1104 pWrtShell->Up(/*bSelect=*/true);
1105 pWrtShell->DelLeft();
1107 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1108 rIDRA.AcceptAllRedline(true);
1110 // losing the page break, as without redlining
1111 CPPUNIT_ASSERT_EQUAL(1, getPages());
1114 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120336)
1116 createSwDoc("tdf120336.docx");
1117 SwDoc* pDoc = getSwDoc();
1119 // turn on red-lining and show changes
1120 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1121 | RedlineFlags::ShowInsert);
1122 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1123 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1124 CPPUNIT_ASSERT_MESSAGE(
1125 "redlines should be visible",
1126 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1128 CPPUNIT_ASSERT_EQUAL(2, getPages());
1130 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1131 rIDRA.AcceptAllRedline(true);
1133 // keep page break, as without redlining
1134 CPPUNIT_ASSERT_EQUAL(2, getPages());
1137 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf106843)
1139 createSwDoc("tdf106843.docx");
1140 SwDoc* pDoc = getSwDoc();
1142 // try to turn off red-lining
1143 dispatchCommand(mxComponent, u".uno:TrackChanges"_ustr, {});
1145 // but the protection doesn't allow it
1146 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1147 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1150 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageComment)
1152 // Load a document with an as-char image in it.
1153 createSwDoc("image-comment.odt");
1154 SwDoc* pDoc = getSwDoc();
1155 SwView* pView = getSwDocShell()->GetView();
1157 // Test document has "before<image>after", remove the content before the image.
1158 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1159 pWrtShell->SttEndDoc(/*bStart=*/true);
1160 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
1161 pWrtShell->Delete();
1163 // Select the image.
1164 selectShape(1);
1166 // Insert a comment while the image is selected.
1167 pView->GetViewFrame().GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON);
1169 // Verify that the comment is around the image.
1170 // Without the accompanying fix in place, this test would have failed, as FN_POSTIT was disabled
1171 // in the frame shell.
1172 // Then this test would have failed, as in case the as-char anchored image was at the start of
1173 // the paragraph, the comment of the image covered the character after the image, not the image.
1174 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1175 CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr,
1176 getProperty<OUString>(getRun(xPara, 1), u"TextPortionType"_ustr));
1177 CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr,
1178 getProperty<OUString>(getRun(xPara, 2), u"TextPortionType"_ustr));
1179 CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr,
1180 getProperty<OUString>(getRun(xPara, 3), u"TextPortionType"_ustr));
1181 CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
1182 getProperty<OUString>(getRun(xPara, 4), u"TextPortionType"_ustr));
1184 // Insert content to the comment, and select the image again.
1185 SfxStringItem aItem(FN_INSERT_STRING, u"x"_ustr);
1186 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
1187 { &aItem });
1188 selectShape(1);
1190 #if !defined(MACOSX)
1191 // Calc the left edge of the as-char frame.
1192 SwRootFrame* pLayout = pWrtShell->GetLayout();
1193 SwFrame* pPage = pLayout->GetLower();
1194 SwFrame* pBody = pPage->GetLower();
1195 SwFrame* pTextFrame = pBody->GetLower();
1196 CPPUNIT_ASSERT(pTextFrame->GetDrawObjs());
1197 const SwSortedObjs& rAnchored = *pTextFrame->GetDrawObjs();
1198 CPPUNIT_ASSERT_GREATER(static_cast<size_t>(0), rAnchored.size());
1199 SwAnchoredObject* pObject = rAnchored[0];
1200 tools::Long nFrameLeft = pObject->GetObjRect().Left();
1201 tools::Long nFrameTop = pObject->GetObjRect().Top();
1203 // Make sure that the anchor points to the bottom left corner of the image.
1204 // Without the accompanying fix in place, this test would have failed with:
1205 // - Expected less or equal than: 1418
1206 // - Actual: 2442
1207 // The anchor pointed to the bottom right corner, so as-char and at-char was inconsistent.
1208 Scheduler::ProcessEventsToIdle();
1209 SwPostItMgr* pPostItMgr = pView->GetPostItMgr();
1210 for (const auto& pItem : *pPostItMgr)
1212 const SwRect& rAnchor = pItem->mpPostIt->GetAnchorRect();
1213 CPPUNIT_ASSERT_EQUAL(nFrameLeft, rAnchor.Left());
1216 // Test the comment anchor we expose via the LOK API.
1217 // Without the accompanying fix in place, this test would have failed with:
1218 // - Expected: 1418, 1418, 0, 0
1219 // - Actual : 1418, 1418, 1024, 1024
1220 // I.e. the anchor position had a non-empty size, which meant different rendering via tiled
1221 // rendering and on the desktop.
1222 tools::JsonWriter aJsonWriter;
1223 SwXTextDocument* pTextDoc = getSwTextDoc();
1224 pTextDoc->getPostIts(aJsonWriter);
1225 OString pChar = aJsonWriter.finishAndGetAsOString();
1226 std::stringstream aStream((std::string(pChar)));
1227 boost::property_tree::ptree aTree;
1228 boost::property_tree::read_json(aStream, aTree);
1229 for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("comments"))
1231 const boost::property_tree::ptree& rComment = rValue.second;
1232 OString aAnchorPos(rComment.get<std::string>("anchorPos"));
1233 OString aExpected
1234 = OString::number(nFrameLeft) + ", " + OString::number(nFrameTop) + ", 0, 0";
1235 CPPUNIT_ASSERT_EQUAL(aExpected, aAnchorPos);
1238 #endif
1240 // Now delete the image.
1241 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1242 // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual:
1243 // 1', i.e. the comment of the image was not deleted when the image was deleted.
1244 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
1245 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1248 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageCommentAtChar)
1250 // Load a document with an at-char image in it.
1251 createSwDoc("image-comment-at-char.odt");
1252 SwDoc* pDoc = getSwDoc();
1253 SwView* pView = getSwDocShell()->GetView();
1255 // Select the image.
1256 selectShape(1);
1258 // Insert a comment while the image is selected.
1259 pView->GetViewFrame().GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON);
1261 // Verify that the comment is around the image.
1262 // Without the accompanying fix in place, this test would have failed, as the comment was
1263 // anchored at the end of the paragraph, it was not around the image.
1264 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1265 CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
1266 getProperty<OUString>(getRun(xPara, 1), u"TextPortionType"_ustr));
1267 CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr,
1268 getProperty<OUString>(getRun(xPara, 2), u"TextPortionType"_ustr));
1269 CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr,
1270 getProperty<OUString>(getRun(xPara, 3), u"TextPortionType"_ustr));
1271 CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr,
1272 getProperty<OUString>(getRun(xPara, 4), u"TextPortionType"_ustr));
1273 CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,
1274 getProperty<OUString>(getRun(xPara, 5), u"TextPortionType"_ustr));
1276 // Insert content to the comment, and select the image again.
1277 SfxStringItem aItem(FN_INSERT_STRING, u"x"_ustr);
1278 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
1279 { &aItem });
1280 selectShape(1);
1281 // Now delete the image.
1282 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1283 // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual:
1284 // 1', i.e. the comment of the image was not deleted when the image was deleted.
1285 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
1286 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1288 // Undo the deletion and move the image down, so the anchor changes.
1289 pView->GetViewFrame().GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1290 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
1291 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1292 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1293 Point aNewAnchor = pWrtShell->GetFlyRect().TopLeft();
1294 aNewAnchor.Move(0, 600);
1295 pWrtShell->SetFlyPos(aNewAnchor);
1297 // Get the image anchor doc model position.
1298 SwFlyFrame* pFly = pWrtShell->GetCurrFlyFrame(false);
1299 CPPUNIT_ASSERT(pFly);
1300 SwFrameFormat* pFlyFormat = pFly->GetFrameFormat();
1301 const SwPosition* pImageAnchor = pFlyFormat->GetAnchor().GetContentAnchor();
1302 CPPUNIT_ASSERT(pImageAnchor);
1304 // Get the annotation mark doc model start.
1305 auto it = pDoc->getIDocumentMarkAccess()->getAnnotationMarksBegin();
1306 CPPUNIT_ASSERT(it != pDoc->getIDocumentMarkAccess()->getAnnotationMarksEnd());
1307 const sw::mark::MarkBase* pMark = *it;
1308 const SwPosition& rAnnotationMarkStart = pMark->GetMarkPos();
1310 // Without the accompanying fix in place, this test would have failed with:
1311 // - Expected: SwPosition (node 14, offset 15)
1312 // - Actual : SwPosition (node 12, offset 3)
1313 // This means moving the image anchor did not move the comment anchor / annotation mark, so the
1314 // image and its comment got out of sync.
1315 CPPUNIT_ASSERT_EQUAL(*pImageAnchor, rAnnotationMarkStart);
1318 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageDeletion)
1320 // load a document with an image anchored to paragraph in it
1321 createSwDoc("image.odt");
1322 SwDoc* pDoc = getSwDoc();
1323 SwView* pView = getSwDocShell()->GetView();
1325 // select the image
1326 selectShape(1);
1328 // turn on red-lining and show changes
1329 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1331 rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert);
1332 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1333 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1334 CPPUNIT_ASSERT_MESSAGE(
1335 "redlines should be visible",
1336 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1338 // now delete the image with track changes
1339 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1341 const SwRedlineTable& rTable = rIDRA.GetRedlineTable();
1342 // this was 0 (missing recording of deletion of images)
1343 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
1345 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
1346 // tdf#142701 this was AS_CHARACTER (convert AT_PARA to AT_CHAR to keep the layout)
1347 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
1348 getProperty<text::TextContentAnchorType>(xShape, u"AnchorType"_ustr));
1351 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageInsertion)
1353 createSwDoc();
1354 SwDoc* pDoc = getSwDoc();
1356 // turn on red-lining and show changes
1357 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1359 rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert);
1360 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1361 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1362 CPPUNIT_ASSERT_MESSAGE(
1363 "redlines should be visible",
1364 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1366 // Insert an image with change tracking
1367 uno::Sequence<beans::PropertyValue> aArgs = {
1368 comphelper::makePropertyValue(u"FileName"_ustr, createFileURL(u"ole2.png")),
1370 dispatchCommand(mxComponent, u".uno:InsertGraphic"_ustr, aArgs);
1372 const SwRedlineTable& rTable = rIDRA.GetRedlineTable();
1373 // this was 0 (missing recording of insertion of images)
1374 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
1377 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120338)
1379 createSwDoc("tdf120338.docx");
1381 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1382 getProperty<sal_Int32>(getParagraph(2), u"ParaAdjust"_ustr)); // right
1383 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1384 getProperty<sal_Int32>(getParagraph(3), u"ParaAdjust"_ustr)); // right
1385 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1386 getProperty<sal_Int32>(getParagraph(4), u"ParaAdjust"_ustr)); // left
1387 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1388 getProperty<sal_Int32>(getParagraph(5), u"ParaAdjust"_ustr)); // right
1390 CPPUNIT_ASSERT_EQUAL(u""_ustr,
1391 getProperty<OUString>(getParagraph(7), u"NumberingStyleName"_ustr));
1393 CPPUNIT_ASSERT_EQUAL(u"WWNum2"_ustr,
1394 getProperty<OUString>(getParagraph(8), u"NumberingStyleName"_ustr));
1396 CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
1397 getProperty<OUString>(getParagraph(10), u"ParaStyleName"_ustr));
1398 CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
1399 getProperty<OUString>(getParagraph(11), u"ParaStyleName"_ustr));
1401 // reject tracked paragraph adjustments
1402 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
1404 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1405 getProperty<sal_Int32>(getParagraph(2), u"ParaAdjust"_ustr)); // left
1406 CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
1407 getProperty<sal_Int32>(getParagraph(3), u"ParaAdjust"_ustr)); // center
1408 CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
1409 getProperty<sal_Int32>(getParagraph(4), u"ParaAdjust"_ustr)); // center
1410 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1411 getProperty<sal_Int32>(getParagraph(5), u"ParaAdjust"_ustr)); // left
1413 // tdf#126245 revert numbering changes
1414 CPPUNIT_ASSERT_EQUAL(u"WWNum2"_ustr,
1415 getProperty<OUString>(getParagraph(7), u"NumberingStyleName"_ustr));
1417 CPPUNIT_ASSERT_EQUAL(u""_ustr,
1418 getProperty<OUString>(getParagraph(8), u"NumberingStyleName"_ustr));
1420 // tdf#126243 revert paragraph styles
1421 CPPUNIT_ASSERT_EQUAL(u"Standard"_ustr,
1422 getProperty<OUString>(getParagraph(10), u"ParaStyleName"_ustr));
1423 CPPUNIT_ASSERT_EQUAL(u"Heading 3"_ustr,
1424 getProperty<OUString>(getParagraph(11), u"ParaStyleName"_ustr));
1427 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120338_multiple_paragraph_join)
1429 createSwDoc("redline-para-join.docx");
1431 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1432 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
1433 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1434 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
1435 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1436 getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
1438 // reject tracked paragraph styles
1439 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
1441 CPPUNIT_ASSERT_EQUAL(u"Heading 1"_ustr,
1442 getProperty<OUString>(getParagraph(1), u"ParaStyleName"_ustr));
1443 CPPUNIT_ASSERT_EQUAL(u"Heading 2"_ustr,
1444 getProperty<OUString>(getParagraph(2), u"ParaStyleName"_ustr));
1445 CPPUNIT_ASSERT_EQUAL(u"Heading 3"_ustr,
1446 getProperty<OUString>(getParagraph(3), u"ParaStyleName"_ustr));
1449 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testShapePageMove)
1451 // Load a document with 2 pages, shape on the first page.
1452 createSwDoc("shape-page-move.odt");
1453 SwDoc* pDoc = getSwDoc();
1454 SwView* pView = getSwDocShell()->GetView();
1455 // Make sure that the 2nd page is below the 1st one.
1456 pView->SetViewLayout(/*nColumns=*/1, /*bBookMode=*/false);
1457 calcLayout();
1459 // Select the shape.
1460 selectShape(1);
1462 // Move the shape down to the 2nd page.
1463 SfxInt32Item aXItem(SID_ATTR_TRANSFORM_POS_X, 4000);
1464 SfxInt32Item aYItem(SID_ATTR_TRANSFORM_POS_Y, 12000);
1465 pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, SfxCallMode::SYNCHRON,
1466 { &aXItem, &aYItem });
1468 // Check if the shape anchor was moved to the 2nd page as well.
1469 auto pShapeFormats = pDoc->GetSpzFrameFormats();
1470 CPPUNIT_ASSERT(!pShapeFormats->empty());
1471 auto it = pShapeFormats->begin();
1472 auto pShapeFormat = *it;
1473 const SwPosition* pAnchor = pShapeFormat->GetAnchor().GetContentAnchor();
1474 CPPUNIT_ASSERT(pAnchor);
1476 // Find out the node index of the 1st para on the 2nd page.
1477 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1478 SwFrame* pFirstPage = pLayout->Lower();
1479 SwFrame* pSecondPage = pFirstPage->GetNext();
1480 CPPUNIT_ASSERT(pSecondPage->IsLayoutFrame());
1481 SwFrame* pBodyFrame = static_cast<SwLayoutFrame*>(pSecondPage)->GetLower();
1482 CPPUNIT_ASSERT(pBodyFrame->IsLayoutFrame());
1483 SwFrame* pTextFrame = static_cast<SwLayoutFrame*>(pBodyFrame)->GetLower();
1484 CPPUNIT_ASSERT(pTextFrame->IsTextFrame());
1485 SwNodeOffset nNodeIndex = static_cast<SwTextFrame*>(pTextFrame)->GetTextNodeFirst()->GetIndex();
1487 // Without the accompanying fix in place, this test would have failed with "Expected: 13;
1488 // Actual: 12", i.e. the shape was anchored to the last paragraph of the 1st page, not to a
1489 // paragraph on the 2nd page.
1490 CPPUNIT_ASSERT_EQUAL(nNodeIndex, pAnchor->GetNodeIndex());
1493 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldInsertion)
1495 createSwDoc();
1496 SwDoc* pDoc = getSwDoc();
1497 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1498 CPPUNIT_ASSERT(pMarkAccess);
1499 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1501 // Insert a date form field
1502 dispatchCommand(mxComponent, u".uno:DatePickerFormField"_ustr, {});
1503 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1505 // Check whether the fieldmark is created
1506 auto aIter = pMarkAccess->getAllMarksBegin();
1507 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1508 ::sw::mark::Fieldmark* pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
1509 CPPUNIT_ASSERT(pFieldmark);
1510 CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
1512 // The date form field has the placeholder text in it
1513 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1514 CPPUNIT_ASSERT_EQUAL(vEnSpaces, xPara->getString());
1516 // Undo insertion
1517 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1518 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1520 // Redo insertion
1521 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
1522 aIter = pMarkAccess->getAllMarksBegin();
1523 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1524 pFieldmark = dynamic_cast<::sw::mark::Fieldmark*>(*aIter);
1525 CPPUNIT_ASSERT(pFieldmark);
1526 CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
1529 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldContentOperations)
1531 createSwDoc();
1532 SwDoc* pDoc = getSwDoc();
1533 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1534 CPPUNIT_ASSERT(pMarkAccess);
1535 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1537 // Insert a date form field
1538 dispatchCommand(mxComponent, u".uno:DatePickerFormField"_ustr, {});
1539 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1541 // Check whether the fieldmark is created
1542 auto aIter = pMarkAccess->getAllMarksBegin();
1543 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1544 ::sw::mark::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
1545 CPPUNIT_ASSERT(pFieldmark);
1546 CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
1548 // Check the default content added by insertion
1549 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1550 CPPUNIT_ASSERT_EQUAL(vEnSpaces, pFieldmark->GetContent());
1552 // Set content to empty string
1553 pFieldmark->ReplaceContent(u""_ustr);
1554 CPPUNIT_ASSERT_EQUAL(u""_ustr, pFieldmark->GetContent());
1556 // Replace empty string with a valid content
1557 pFieldmark->ReplaceContent(u"2019-10-23"_ustr);
1558 CPPUNIT_ASSERT_EQUAL(u"2019-10-23"_ustr, pFieldmark->GetContent());
1561 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateHandling)
1563 createSwDoc();
1564 SwDoc* pDoc = getSwDoc();
1565 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1566 CPPUNIT_ASSERT(pMarkAccess);
1567 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1569 // Insert a date form field
1570 dispatchCommand(mxComponent, u".uno:DatePickerFormField"_ustr, {});
1571 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1573 // Check whether the fieldmark is created
1574 auto aIter = pMarkAccess->getAllMarksBegin();
1575 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1576 ::sw::mark::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
1577 CPPUNIT_ASSERT(pFieldmark);
1578 CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
1580 // The default content is not a valid date
1581 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1582 CPPUNIT_ASSERT_EQUAL(vEnSpaces, pFieldmark->GetContent());
1583 std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
1584 CPPUNIT_ASSERT(!aResult.first);
1586 // Check empty string
1587 pFieldmark->ReplaceContent(u""_ustr);
1588 aResult = pFieldmark->GetCurrentDate();
1589 CPPUNIT_ASSERT(!aResult.first);
1591 // Check valid date
1592 // Set date format first
1593 sw::mark::Fieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
1594 (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= u"YYYY/MM/DD"_ustr;
1595 (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= u"en-US"_ustr;
1597 // Set date value and check whether the content is formatted correctly
1598 pFieldmark->SetCurrentDate(48000.0);
1599 aResult = pFieldmark->GetCurrentDate();
1600 CPPUNIT_ASSERT(aResult.first);
1601 CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
1602 CPPUNIT_ASSERT_EQUAL(u"2031/06/01"_ustr, pFieldmark->GetContent());
1603 // Current date param contains date in a "standard format"
1604 OUString sCurrentDate;
1605 auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
1606 if (pResult != pParameters->end())
1608 pResult->second >>= sCurrentDate;
1610 CPPUNIT_ASSERT_EQUAL(u"2031-06-01"_ustr, sCurrentDate);
1613 #if !defined(_WIN32)
1614 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateInvalidation)
1616 createSwDoc();
1617 SwDoc* pDoc = getSwDoc();
1618 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1619 CPPUNIT_ASSERT(pMarkAccess);
1620 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1622 // Insert a date form field
1623 dispatchCommand(mxComponent, u".uno:DatePickerFormField"_ustr, {});
1624 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1626 // Check whether the fieldmark is created
1627 auto aIter = pMarkAccess->getAllMarksBegin();
1628 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1629 ::sw::mark::DateFieldmark* pFieldmark = dynamic_cast<::sw::mark::DateFieldmark*>(*aIter);
1630 CPPUNIT_ASSERT(pFieldmark);
1631 CPPUNIT_ASSERT_EQUAL(ODF_FORMDATE, pFieldmark->GetFieldname());
1633 // Set a date first
1634 sw::mark::Fieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
1635 pFieldmark->SetCurrentDate(48000.0);
1636 std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
1637 CPPUNIT_ASSERT(aResult.first);
1638 CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
1640 // Do the layouting to trigger invalidation
1641 // Since we have the current date consistent with the field content
1642 // This invalidation won't change anything
1643 calcLayout();
1644 Scheduler::ProcessEventsToIdle();
1646 // Current date param contains date in a "standard format"
1647 OUString sCurrentDate;
1648 auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
1649 if (pResult != pParameters->end())
1651 pResult->second >>= sCurrentDate;
1653 // We have the current date parameter set
1654 CPPUNIT_ASSERT_EQUAL(u"2031-06-01"_ustr, sCurrentDate);
1656 // Now change the content of the field
1657 pFieldmark->ReplaceContent(u"[select date]"_ustr);
1658 // Do the layouting to trigger invalidation
1659 calcLayout();
1660 Scheduler::ProcessEventsToIdle();
1662 sCurrentDate.clear();
1663 pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
1664 if (pResult != pParameters->end())
1666 pResult->second >>= sCurrentDate;
1668 CPPUNIT_ASSERT_EQUAL(u""_ustr, sCurrentDate);
1670 #endif
1672 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testOleSaveWhileEdit)
1674 // Enable LOK mode, otherwise OCommonEmbeddedObject::SwitchStateTo_Impl() will throw when it
1675 // finds out that the test runs headless.
1676 comphelper::LibreOfficeKit::setActive();
1678 // Load a document with a Draw doc in it.
1679 createSwDoc("ole-save-while-edit.odt");
1680 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1682 selectShape(1);
1684 // Start editing the OLE object.
1685 pWrtShell->LaunchOLEObj();
1687 // Save the document without existing the OLE edit.
1688 uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
1689 xStorable->storeToURL(maTempFile.GetURL(), {});
1691 uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
1692 = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
1693 maTempFile.GetURL());
1694 // Without the accompanying fix in place, this test would have failed: the OLE object lost its
1695 // replacement on save if the edit was active while saving.
1696 CPPUNIT_ASSERT(xNameAccess->hasByName(u"ObjectReplacements/Object 1"_ustr));
1698 // Dispose the document while LOK is still active to avoid leaks.
1699 mxComponent->dispose();
1700 mxComponent.clear();
1701 comphelper::LibreOfficeKit::setActive(false);
1704 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf105330)
1706 createSwDoc("tdf105330.odt");
1707 SwDoc* pDoc = getSwDoc();
1709 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1710 pWrtShell->Down(/*bSelect=*/false);
1711 SwView* pView = getSwDocShell()->GetView();
1712 SfxUInt16Item aRows(SID_ATTR_TABLE_ROW, 1);
1713 SfxUInt16Item aColumns(SID_ATTR_TABLE_COLUMN, 1);
1714 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_TABLE, SfxCallMode::SYNCHRON,
1715 { &aRows, &aColumns });
1717 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
1718 rUndoManager.Undo();
1720 // Without the accompanying fix in place, height was only 1 twips (practically invisible).
1721 // Require at least 12pt height (font size under the cursor), in twips.
1722 CPPUNIT_ASSERT_GREATEREQUAL(
1723 static_cast<tools::Long>(240),
1724 pWrtShell->GetVisibleCursor()->GetTextCursor().GetSize().getHeight());
1727 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118311)
1729 createSwDoc("tdf118311.fodt");
1731 // Jump to the first cell, selecting its content
1732 uno::Sequence<beans::PropertyValue> aSearch(comphelper::InitPropertySequence({
1733 { "SearchItem.SearchString", uno::Any(u"a"_ustr) },
1734 { "SearchItem.Backward", uno::Any(false) },
1735 }));
1736 dispatchCommand(mxComponent, u".uno:ExecuteSearch"_ustr, aSearch);
1738 // .uno:Cut doesn't remove the table, only the selected content of the first cell
1739 dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
1741 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1742 assertXPath(pXmlDoc, "//page[1]//body/tab");
1744 // .uno:SelectAll selects the whole table, and UNO command Cut cuts it
1745 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
1746 dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
1748 pXmlDoc = parseLayoutDump();
1749 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1752 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletion)
1754 // load a 1-row table, and delete the row with enabled change tracking:
1755 // now the row is not deleted silently, but keeps the deleted cell contents,
1756 // and only accepting all of them will result the deletion of the table row.
1757 createSwDoc("tdf118311.fodt");
1758 SwDoc* pDoc = getSwDoc();
1760 // turn on red-lining and show changes
1761 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1762 | RedlineFlags::ShowInsert);
1763 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1764 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1765 CPPUNIT_ASSERT_MESSAGE(
1766 "redlines should be visible",
1767 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1769 // check table
1770 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1771 assertXPath(pXmlDoc, "//page[1]//body/tab");
1773 // delete table row with enabled change tracking
1774 // (HasTextChangesOnly property of the row will be false)
1775 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
1777 // This was deleted without change tracking
1778 pXmlDoc = parseLayoutDump();
1779 assertXPath(pXmlDoc, "//page[1]//body/tab");
1781 // accept the deletion of the content of the first cell
1782 SwEditShell* const pEditShell(pDoc->GetEditShell());
1783 CPPUNIT_ASSERT(pEditShell);
1784 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
1785 pEditShell->AcceptRedline(0);
1787 // table row was still not deleted
1788 pXmlDoc = parseLayoutDump();
1789 assertXPath(pXmlDoc, "//page[1]//body/tab");
1791 // accept last redline
1792 pEditShell->AcceptRedline(0);
1794 // table row (and the 1-row table) was deleted finally
1795 pXmlDoc = parseLayoutDump();
1796 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1798 // Undo, and repeat the previous test, but only with deletion of the text content of the cells
1799 // (HasTextChangesOnly property will be removed by Undo)
1801 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1802 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1803 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1805 // table exists again
1806 pXmlDoc = parseLayoutDump();
1807 assertXPath(pXmlDoc, "//page[1]//body/tab");
1809 // delete table row with enabled change tracking
1810 dispatchCommand(mxComponent, u".uno:SelectRow"_ustr, {});
1811 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
1813 // Table row still exists
1814 pXmlDoc = parseLayoutDump();
1815 assertXPath(pXmlDoc, "//page[1]//body/tab");
1817 // accept the deletion of the content of the first cell
1818 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
1819 pEditShell->AcceptRedline(0);
1821 // table row was still not deleted
1822 pXmlDoc = parseLayoutDump();
1823 assertXPath(pXmlDoc, "//page[1]//body/tab");
1825 // accept last redline
1826 pEditShell->AcceptRedline(0);
1828 // table row (and the 1-row table) still exists
1829 // (HasTextChangesOnly property wasn't set for table row deletion)
1830 pXmlDoc = parseLayoutDump();
1831 assertXPath(pXmlDoc, "//page[1]//body/tab");
1833 // Undo, and delete the row without change tracking
1835 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1836 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1837 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
1839 // table exists again
1840 pXmlDoc = parseLayoutDump();
1841 assertXPath(pXmlDoc, "//page[1]//body/tab");
1843 // disable change tracking
1844 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
1845 | RedlineFlags::ShowInsert);
1847 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1848 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1850 // delete table row without change tracking
1851 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
1853 // the table (row) was deleted
1854 pXmlDoc = parseLayoutDump();
1855 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1858 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150976)
1860 // load a 1-row table, and delete the row with track changes
1861 createSwDoc("select-row.fodt");
1862 SwDoc* pDoc = getSwDoc();
1864 // turn on red-lining and show changes
1865 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1866 | RedlineFlags::ShowInsert);
1867 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1868 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1869 CPPUNIT_ASSERT_MESSAGE(
1870 "redlines should be visible",
1871 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1873 // check table
1874 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1875 assertXPath(pXmlDoc, "//page[1]//body/tab");
1876 // nested table in the last cell
1877 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1879 // delete table row with enabled change tracking
1880 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
1882 pXmlDoc = parseLayoutDump();
1883 assertXPath(pXmlDoc, "//page[1]//body/tab");
1885 // deleted text content
1886 SwEditShell* const pEditShell(pDoc->GetEditShell());
1887 CPPUNIT_ASSERT(pEditShell);
1888 // This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
1889 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
1891 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1892 SwFrame* pPage = pLayout->Lower();
1893 SwFrame* pBody = pPage->GetLower();
1894 SwFrame* pTable = pBody->GetLower();
1895 CPPUNIT_ASSERT(pTable->IsTabFrame());
1897 SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
1899 // This was false (not deleted row)
1900 CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
1902 // accept all tracked changes
1903 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
1905 pXmlDoc = parseLayoutDump();
1907 // tdf#151658 This was 1: not deleted table row (and table)
1908 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1911 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf151657)
1913 // load a 1-row table, and delete the row with hidden track changes
1914 createSwDoc("select-row.fodt");
1915 SwDoc* pDoc = getSwDoc();
1917 // turn on red-lining and hide changes
1918 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
1919 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1920 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1921 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
1922 !IDocumentRedlineAccess::IsShowChanges(
1923 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1925 // check table
1926 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1927 assertXPath(pXmlDoc, "//page[1]//body/tab");
1928 // nested table in the last cell
1929 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1931 // delete table row with enabled change tracking
1932 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
1934 pXmlDoc = parseLayoutDump();
1935 assertXPath(pXmlDoc, "//page[1]//body/tab");
1937 // deleted text content
1938 SwEditShell* const pEditShell(pDoc->GetEditShell());
1939 CPPUNIT_ASSERT(pEditShell);
1940 // This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
1941 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
1943 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1944 SwFrame* pPage = pLayout->Lower();
1945 SwFrame* pBody = pPage->GetLower();
1946 SwFrame* pTable = pBody->GetLower();
1947 CPPUNIT_ASSERT(pTable->IsTabFrame());
1949 SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
1951 // This was false (not deleted row)
1952 CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
1954 // accept all tracked changes
1955 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
1957 pXmlDoc = parseLayoutDump();
1959 // tdf#151658 This was 1: not deleted table row (and table)
1960 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1963 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testSelectRowWithNestedTable)
1965 // load a 1-row table, and select the row
1966 createSwDoc("select-row.fodt");
1968 // check table
1969 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1970 assertXPath(pXmlDoc, "//page[1]//body/tab");
1971 // nested table in the last cell
1972 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1974 // select table row
1975 dispatchCommand(mxComponent, u".uno:EntireRow"_ustr, {});
1976 // convert selected text content to uppercase
1977 dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
1979 pXmlDoc = parseLayoutDump();
1980 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[1]/txt",
1981 u"NESTED-A1");
1982 // This was "a1" (bad selection of the table row)
1983 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[1]/txt[1]", u"A1");
1984 // This was "nested-b1" (bad selection of the table row)
1985 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[2]/txt",
1986 u"NESTED-B1");
1989 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_row)
1991 // load a 2-row table, and select row 2 by clicking before it
1992 createSwDoc("select-column.fodt");
1993 SwDoc* pDoc = getSwDoc();
1994 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
1995 CPPUNIT_ASSERT(pWrtShell);
1997 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1998 SwFrame* pPage = pLayout->Lower();
1999 SwFrame* pBody = pPage->GetLower();
2000 SwFrame* pTable = pBody->GetLower()->GetNext();
2001 SwFrame* pRow2 = pTable->GetLower()->GetNext();
2002 const SwRect& rRow2Rect = pRow2->getFrameArea();
2003 Point ptRow(rRow2Rect.Left(), rRow2Rect.Top() + rRow2Rect.Height() / 2);
2005 pWrtShell->SelectTableRowCol(ptRow);
2007 // convert selected text content to uppercase
2008 dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
2010 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2011 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", u"a1");
2012 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", u"b1");
2013 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
2014 u"NESTED-A1");
2015 // This was "a2" (bad selection of the table row)
2016 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", u"A2");
2017 // This was "nested-b1" (bad selection of the table row)
2018 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
2019 u"NESTED-B1");
2022 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_column)
2024 // load a 2-row table, and select column B by clicking before them
2025 createSwDoc("select-column.fodt");
2026 SwDoc* pDoc = getSwDoc();
2027 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
2028 CPPUNIT_ASSERT(pWrtShell);
2030 // select table column by using the middle point of the top border of column B
2031 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
2032 SwFrame* pPage = pLayout->Lower();
2033 SwFrame* pBody = pPage->GetLower();
2034 SwFrame* pTable = pBody->GetLower()->GetNext();
2035 SwFrame* pRow1 = pTable->GetLower();
2036 SwFrame* pCellB1 = pRow1->GetLower()->GetNext();
2037 const SwRect& rCellB1Rect = pCellB1->getFrameArea();
2038 Point ptColumn(rCellB1Rect.Left() + rCellB1Rect.Width() / 2, rCellB1Rect.Top() - 5);
2040 pWrtShell->SelectTableRowCol(ptColumn);
2042 // convert selected text content to uppercase
2043 dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
2045 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2047 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", u"a1");
2048 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", u"a2");
2049 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
2050 u"NESTED-A1");
2051 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
2052 u"NESTED-B1");
2053 // This was "b1" (bad selection of the table column)
2054 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", u"B1");
2057 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithExport)
2059 // load a 1-row table, and delete the row with enabled change tracking:
2060 // now the row is not deleted silently, but keeps the deleted cell contents,
2061 // and only accepting all of them will result the deletion of the table row.
2062 createSwDoc("tdf118311.fodt");
2063 SwDoc* pDoc = getSwDoc();
2065 // turn on red-lining and show changes
2066 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2067 | RedlineFlags::ShowInsert);
2068 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2069 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2070 CPPUNIT_ASSERT_MESSAGE(
2071 "redlines should be visible",
2072 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2074 // check table
2075 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2076 assertXPath(pXmlDoc, "//page[1]//body/tab");
2078 // delete table row with enabled change tracking
2079 // (HasTextChangesOnly property of the row will be false)
2080 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
2082 // Deleted text content with change tracking,
2083 // but not table deletion
2084 pXmlDoc = parseLayoutDump();
2085 assertXPath(pXmlDoc, "//page[1]//body/tab");
2087 // Save it and load it back.
2088 saveAndReload(u"writer8"_ustr);
2089 pDoc = getSwDoc();
2091 // accept the deletion of the content of the first cell
2092 SwEditShell* const pEditShell(pDoc->GetEditShell());
2093 CPPUNIT_ASSERT(pEditShell);
2094 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
2095 pEditShell->AcceptRedline(0);
2097 // table row was still not deleted
2098 pXmlDoc = parseLayoutDump();
2099 assertXPath(pXmlDoc, "//page[1]//body/tab");
2101 // accept last redline
2102 pEditShell->AcceptRedline(0);
2104 // table row (and the 1-row table) was deleted finally
2105 // (working export/import of HasTextChangesOnly)
2106 pXmlDoc = parseLayoutDump();
2107 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
2110 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithDOCXExport)
2112 // load a 1-row table, and delete the row with enabled change tracking:
2113 // now the row is not deleted silently, but keeps the deleted cell contents,
2114 // and only accepting all of them will result the deletion of the table row.
2115 createSwDoc("tdf118311.fodt");
2116 SwDoc* pDoc = getSwDoc();
2118 // turn on red-lining and show changes
2119 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2120 | RedlineFlags::ShowInsert);
2121 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2122 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2123 CPPUNIT_ASSERT_MESSAGE(
2124 "redlines should be visible",
2125 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2127 // check table
2128 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2129 assertXPath(pXmlDoc, "//page[1]//body/tab");
2131 // delete table row with enabled change tracking
2132 // (HasTextChangesOnly property of the row will be false)
2133 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
2135 // Deleted text content with change tracking,
2136 // but not table deletion
2137 pXmlDoc = parseLayoutDump();
2138 assertXPath(pXmlDoc, "//page[1]//body/tab");
2140 // Save it to a DOCX and load it back.
2141 // Exporting change tracking of the row wasn't supported.
2142 // Also Manage Changes for the import.
2143 saveAndReload(u"Office Open XML Text"_ustr);
2144 pDoc = getSwDoc();
2146 // accept the deletion of the content of the first cell
2147 SwEditShell* const pEditShell(pDoc->GetEditShell());
2148 CPPUNIT_ASSERT(pEditShell);
2149 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
2150 pEditShell->AcceptRedline(0);
2152 // table row was still not deleted
2153 pXmlDoc = parseLayoutDump();
2154 assertXPath(pXmlDoc, "//page[1]//body/tab");
2156 // accept last redline
2157 pEditShell->AcceptRedline(0);
2159 // table row (and the 1-row table) was deleted finally
2160 // (working export/import of HasTextChangesOnly)
2161 pXmlDoc = parseLayoutDump();
2162 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
2165 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableInsertion)
2167 // load a 3-row table inserted with change tracking by text to table conversion
2168 createSwDoc("TC-table-converttotable.docx");
2169 SwDoc* pDoc = getSwDoc();
2171 // check table count (1)
2172 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2173 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2174 uno::UNO_QUERY);
2175 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2177 // reject the text insertions of the table cells (also reject deletion of the tabulated
2178 // text source of the table, which was used by the tracked text to table conversion)
2179 SwEditShell* const pEditShell(pDoc->GetEditShell());
2180 CPPUNIT_ASSERT(pEditShell);
2181 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
2182 while (pEditShell->GetRedlineCount())
2183 pEditShell->RejectRedline(0);
2185 // rejecting all text insertions must undo the table insertion
2186 // This was 1 (remaining empty table after rejecting all table text insertions)
2187 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2190 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableMoveToFrame)
2192 // load a table with tracked drag & drop: Table1 is the moveFrom,
2193 // Table2 is the moveTo - and framed - table
2194 createSwDoc("TC-table-DnD-move.docx");
2195 SwDoc* pDoc = getSwDoc();
2197 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2198 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2199 uno::UNO_QUERY);
2200 uno::Reference<container::XNameAccess> xTableNames = xTextTablesSupplier->getTextTables();
2201 // check table count (2)
2202 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
2204 // accept tracked table moving, remaining table is Table2
2205 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2206 rIDRA.AcceptAllRedline(true);
2207 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2208 CPPUNIT_ASSERT(xTableNames->hasByName(u"Table2"_ustr));
2209 CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table1"_ustr));
2211 // Undo and reject tracked table moving, remaining table is Table1
2212 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2213 rIDRA.AcceptAllRedline(false);
2214 // This was 2 (not deleted Table2 – framed)
2215 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2216 CPPUNIT_ASSERT(xTableNames->hasByName(u"Table1"_ustr));
2217 CPPUNIT_ASSERT(!xTableNames->hasByName(u"Table2"_ustr));
2220 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_AcceptInsertRedlineCutWithDeletion)
2222 createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
2223 SwDoc* pDoc = getSwDoc();
2225 // turn on red-lining and show changes
2226 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2227 | RedlineFlags::ShowInsert);
2228 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2229 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2230 CPPUNIT_ASSERT_MESSAGE(
2231 "redlines should be visible",
2232 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2234 SwEditShell* const pEditShell(pDoc->GetEditShell());
2235 CPPUNIT_ASSERT(pEditShell);
2236 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
2238 // Accept the insert that splitted into 3 parts .. accept all 3 of them
2239 pEditShell->AcceptRedline(6);
2240 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
2241 // The middle had a delete too, rejecting the delete will remove that redline too.
2242 pEditShell->RejectRedline(6);
2243 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());
2245 // Accept insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
2246 // It will accept only 2 parts, that is not separated. It leave the deletion.
2247 pEditShell->AcceptRedline(0);
2248 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(5), pEditShell->GetRedlineCount());
2249 // Accepting the delete will remove that redline.
2250 // (only that one, as its other half is separated from it with an insert)
2251 pEditShell->AcceptRedline(0);
2252 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
2255 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157662_RejectInsertRedlineCutWithDeletion)
2257 createSwDoc("tdf157662_redlineNestedInsertDelete.odt");
2258 SwDoc* pDoc = getSwDoc();
2260 // turn on red-lining and show changes
2261 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2262 | RedlineFlags::ShowInsert);
2263 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2264 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2265 CPPUNIT_ASSERT_MESSAGE(
2266 "redlines should be visible",
2267 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2269 SwEditShell* const pEditShell(pDoc->GetEditShell());
2270 CPPUNIT_ASSERT(pEditShell);
2271 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
2273 // Reject the insert that splitted into 3 parts. reject all 3 of them
2274 // it even remove the deletion, that was on the 2. insert...
2275 pEditShell->RejectRedline(6);
2276 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(6), pEditShell->GetRedlineCount());
2278 // Reject insert that splitted into 4 parts, but separated to 2-2 parts, with another insert.
2279 // It will reject only 2 parts, that is not separated. It remove the deletion.
2280 pEditShell->RejectRedline(0);
2281 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(4), pEditShell->GetRedlineCount());
2284 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf157663_RedlineMoveRecognition)
2286 createSwDoc("tdf157663_redlineMove.odt");
2287 SwDoc* pDoc = getSwDoc();
2289 // turn on red-lining and show changes
2290 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2291 | RedlineFlags::ShowInsert);
2292 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2293 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2294 CPPUNIT_ASSERT_MESSAGE(
2295 "redlines should be visible",
2296 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2298 SwEditShell* const pEditShell(pDoc->GetEditShell());
2299 CPPUNIT_ASSERT(pEditShell);
2301 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());
2303 // Check if move redlines are recognised as moved, during import
2304 SwRedlineTable& rTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
2305 bool vMovedRedlines[23]
2306 = { false, true, true, true, true, true, true, true, true, true, true, true,
2307 true, false, true, false, true, false, false, false, false, false, false };
2308 // 20. and 22. redline is a delete/insert redline with the same text "three".
2309 // they are not recognised as a move, because 22. redline is not a whole paragraph.
2310 // Note: delete/insert redlines that are just a part of a paragraph decided to be part of
2311 // a move, only if it is at least 6 character long and contain a space "" character.
2312 for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
2314 CPPUNIT_ASSERT_EQUAL(vMovedRedlines[i], rTable[i]->GetMoved() > 0);
2317 // Check if accepting move redlines accept its pairs as well.
2318 pEditShell->AcceptRedline(3); // "9 3/4"
2319 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
2321 pEditShell->AcceptRedline(1); // "sqrt(10)"
2322 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(17), pEditShell->GetRedlineCount());
2324 pEditShell->AcceptRedline(1); // "four"
2325 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(13), pEditShell->GetRedlineCount());
2327 pEditShell->AcceptRedline(3); // "six"
2328 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(11), pEditShell->GetRedlineCount());
2330 pEditShell->AcceptRedline(4); // "sqrt(17)"
2331 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(9), pEditShell->GetRedlineCount());
2333 // Undo back all the 5 redline accepts
2334 for (int i = 0; i < 5; i++)
2336 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2338 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(23), pEditShell->GetRedlineCount());
2340 // Check if rejecting redlines reject its pairs as well.
2341 pEditShell->RejectRedline(3); // "9 3/4"
2342 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(20), pEditShell->GetRedlineCount());
2344 pEditShell->RejectRedline(2); // "sqrt(10)"
2345 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(18), pEditShell->GetRedlineCount());
2347 pEditShell->RejectRedline(2); // "four"
2348 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());
2350 pEditShell->RejectRedline(2); // "sqrt(17)"
2351 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(14), pEditShell->GetRedlineCount());
2353 pEditShell->RejectRedline(2); // "six"
2354 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());
2356 const sal_uInt32 nZeroID = 0;
2358 // Check if there are no more move redlines
2359 for (SwRedlineTable::size_type i = 0; i < rTable.size(); i++)
2361 CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[i]->GetMoved());
2364 // Check if moving paragraphs generate redline moves
2366 // move a paragraph that has delete redlines inside of it
2367 // original text: "Seve ent teen"
2368 // deleted texts: "e " and " t"
2369 // moved new text: "Seventeen"
2370 pEditShell->GotoRedline(6, true);
2371 pEditShell->UpdateCursor();
2372 pEditShell->MoveParagraph(SwNodeOffset(1));
2373 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());
2375 sal_uInt32 nMovedID = rTable[6]->GetMoved();
2376 //moved text from here
2377 CPPUNIT_ASSERT(nMovedID > 0); // "Sev"
2378 CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[7]->GetMoved()); // "e " deleted text not moved
2379 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[8]->GetMoved()); // "ent"
2380 CPPUNIT_ASSERT_EQUAL(nZeroID, rTable[9]->GetMoved()); // " t"
2381 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[10]->GetMoved()); // "teen"
2382 // moved text to here
2383 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[11]->GetMoved()); // "Seventeen"
2385 // move paragraph that has an insert redline inside of it
2386 // original text: "Eigen"
2387 // inserted text: "hte"
2388 // moved new text :"Eighteen"
2389 pEditShell->GotoRedline(12, true);
2390 pEditShell->UpdateCursor();
2391 pEditShell->MoveParagraph(SwNodeOffset(-2));
2392 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
2394 nMovedID = rTable[12]->GetMoved();
2395 // moved text to here
2396 CPPUNIT_ASSERT(nMovedID > 0); // "Eighteen"
2397 // moved text from here
2398 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[13]->GetMoved()); // "Eigen"
2399 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[14]->GetMoved()); // "hte"
2400 CPPUNIT_ASSERT_EQUAL(nMovedID, rTable[15]->GetMoved()); // "en"
2402 //Check if accept work on both side of the redlines made by manual move paragraphs
2403 pEditShell->AcceptRedline(13); // "Eigen"
2404 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(15), pEditShell->GetRedlineCount());
2405 pEditShell->AcceptRedline(11); // "Seventeen"
2406 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
2408 //undo back the last 2 accept
2409 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2410 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2411 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(19), pEditShell->GetRedlineCount());
2413 //Check if reject work on both side of the redlines made by manual move paragraphs
2414 pEditShell->RejectRedline(13); // "Eigen"
2415 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(16), pEditShell->GetRedlineCount());
2416 pEditShell->RejectRedline(11); // "Seventeen"
2417 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(12), pEditShell->GetRedlineCount());
2420 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143215)
2422 // load a table with tracked insertion of an empty row
2423 createSwDoc("TC-table-rowadd.docx");
2424 SwDoc* pDoc = getSwDoc();
2426 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2427 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2428 uno::UNO_QUERY);
2429 // check table count
2430 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2432 // check table row count
2433 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2434 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2436 // reject insertion of the empty table row
2437 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2438 rIDRA.AcceptAllRedline(false);
2439 // This was 4 (remained empty row)
2440 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2442 // Undo and accept insertion of the table row
2443 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2444 rIDRA.AcceptAllRedline(true);
2445 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2447 // delete it with change tracking, and accept the deletion
2448 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
2449 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2450 rIDRA.AcceptAllRedline(true);
2451 // This was 4 (remained empty row)
2452 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2455 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
2457 // load a table with tracked insertion of an empty row
2458 createSwDoc("TC-table-rowadd.docx");
2460 // check table count
2461 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2462 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2463 uno::UNO_QUERY);
2464 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2466 // check table row count
2467 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2468 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2470 // select the second row (tracked table row insertion)
2471 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
2472 pWrtShell->Down(/*bSelect=*/false);
2474 // delete it, and accept all tracked changes
2475 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
2476 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
2478 // This was 4 (it was not possible to delete only the tracked row insertions)
2479 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2481 // insert a new table row with track changes
2482 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
2483 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2485 // select and delete it
2486 pWrtShell->Down(/*bSelect=*/false);
2487 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
2488 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
2490 // This was 4 (it was not possible to delete own tracked row insertions)
2491 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2494 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666_regression)
2496 // load a table with tracked insertion of an empty row
2497 createSwDoc("TC-table-rowadd.docx");
2499 // check table count
2500 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2501 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2502 uno::UNO_QUERY);
2503 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2505 // check table row count
2506 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2507 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2509 // select the second row (tracked table row insertion)
2510 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
2511 pWrtShell->Down(/*bSelect=*/false);
2513 // insert a new table row with track changes
2514 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
2515 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable->getRows()->getCount());
2517 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
2519 // This was 4 (the inserted table row wasn't tracked)
2520 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2523 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
2525 // load a table with an empty row, and an empty line before the table
2526 // (to allow the easy selection of the full text with the table)
2527 createSwDoc("tdf144748.fodt");
2528 SwDoc* pDoc = getSwDoc();
2530 // turn on red-lining and show changes
2531 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2532 | RedlineFlags::ShowInsert);
2533 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2534 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2535 CPPUNIT_ASSERT_MESSAGE(
2536 "redlines should be visible",
2537 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2539 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2540 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2541 uno::UNO_QUERY);
2542 // there is a table in the text
2543 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2545 // delete full text with the table and check Undo
2547 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
2548 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
2549 // this crashed LibreOffice
2550 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2552 // redo and check redline usage
2554 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
2555 SwEditShell* const pEditShell(pDoc->GetEditShell());
2556 CPPUNIT_ASSERT(pEditShell);
2557 // This was 2 (bad extra redline for the empty row of the deleted table)
2558 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2560 // accept deletion of the text, including the table with the empty row
2562 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2563 rIDRA.AcceptAllRedline(true);
2565 // no table left in the text
2566 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2569 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180)
2571 // load a tracked table insertion (single redline)
2572 createSwDoc("tdf147180.fodt");
2573 SwDoc* pDoc = getSwDoc();
2575 // turn on red-lining and show changes
2576 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2577 | RedlineFlags::ShowInsert);
2578 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2579 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2580 CPPUNIT_ASSERT_MESSAGE(
2581 "redlines should be visible",
2582 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2584 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2585 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2586 uno::UNO_QUERY);
2587 // there is a table in the text
2588 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2590 // insert a character in the first cell with change tracking
2591 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
2592 pWrtShell->Insert(u"x"_ustr);
2594 // reject all the changes, including table insertion
2596 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2597 rIDRA.AcceptAllRedline(/*bAccept=*/false);
2599 // no table left in the text
2601 // This was 1 (lost tracking of the table after modifying its text content)
2602 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2605 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows)
2607 // load a tracked table insertion (single redline) with empty rows
2608 createSwDoc("tdf150824.fodt");
2609 SwDoc* pDoc = getSwDoc();
2611 // turn on red-lining and show changes
2612 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2613 | RedlineFlags::ShowInsert);
2614 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2615 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2616 CPPUNIT_ASSERT_MESSAGE(
2617 "redlines should be visible",
2618 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2620 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2621 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2622 uno::UNO_QUERY);
2623 // there is a table in the text
2624 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2626 // insert a character in the first cell with change tracking
2627 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
2628 pWrtShell->Insert(u"x"_ustr);
2630 // reject all the changes, including table insertion
2632 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2633 rIDRA.AcceptAllRedline(/*bAccept=*/false);
2635 // no table left in the text
2637 // This was 1 (lost tracking of the empty rows after modifying table text content)
2638 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2641 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletion)
2643 // load a table, and delete the first column with enabled change tracking:
2644 // now the column is not deleted silently, but keeps the deleted cell content,
2645 // and only accepting it will result the deletion of the table column.
2646 createSwDoc("tdf118311.fodt");
2647 SwDoc* pDoc = getSwDoc();
2649 // turn on red-lining and show changes
2650 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2651 | RedlineFlags::ShowInsert);
2652 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2653 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2654 CPPUNIT_ASSERT_MESSAGE(
2655 "redlines should be visible",
2656 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2658 // check table
2659 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2660 assertXPath(pXmlDoc, "//page[1]//body/tab");
2661 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2663 // delete table column with enabled change tracking
2664 // (HasTextChangesOnly property of the cell will be false)
2665 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2667 pXmlDoc = parseLayoutDump();
2668 assertXPath(pXmlDoc, "//page[1]//body/tab");
2669 // This was 1 (deleted cell without change tracking)
2670 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2672 // accept the deletion
2673 SwEditShell* const pEditShell(pDoc->GetEditShell());
2674 CPPUNIT_ASSERT(pEditShell);
2675 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2676 pEditShell->AcceptRedline(0);
2678 pXmlDoc = parseLayoutDump();
2679 assertXPath(pXmlDoc, "//page[1]//body/tab");
2680 // deleted column
2681 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2683 // Undo, and repeat the previous test, but only with deletion of the text content of the cells
2684 // (HasTextChangesOnly property will be removed by Undo)
2686 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2687 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2689 // first column exists again
2690 pXmlDoc = parseLayoutDump();
2691 assertXPath(pXmlDoc, "//page[1]//body/tab");
2692 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2694 // delete table column with enabled change tracking
2695 dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
2696 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
2698 // Table column still exists
2699 pXmlDoc = parseLayoutDump();
2700 assertXPath(pXmlDoc, "//page[1]//body/tab");
2701 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2703 // accept the deletion of the content of the first cell
2704 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2705 pEditShell->AcceptRedline(0);
2707 // table column was still not deleted
2708 pXmlDoc = parseLayoutDump();
2709 assertXPath(pXmlDoc, "//page[1]//body/tab");
2710 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2712 // Undo, and delete the column without change tracking
2714 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2715 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2717 // table exists again
2718 pXmlDoc = parseLayoutDump();
2719 assertXPath(pXmlDoc, "//page[1]//body/tab");
2720 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2722 // disable change tracking
2723 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2724 | RedlineFlags::ShowInsert);
2726 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2727 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2729 // delete table column without change tracking
2730 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2732 // the table column was deleted
2733 pXmlDoc = parseLayoutDump();
2734 assertXPath(pXmlDoc, "//page[1]//body/tab");
2735 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2738 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156474)
2740 // load a table, and insert a column with change tracking
2741 createSwDoc("tdf118311.fodt");
2742 SwDoc* pDoc = getSwDoc();
2744 // turn on red-lining and show changes
2745 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2746 | RedlineFlags::ShowInsert);
2747 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2748 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2749 CPPUNIT_ASSERT_MESSAGE(
2750 "redlines should be visible",
2751 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2753 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2754 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2755 uno::UNO_QUERY);
2757 // there is a table in the text with two columns
2758 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2759 uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
2760 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
2762 // insert table column with enabled change tracking
2763 // (HasTextChangesOnly property of the cell will be false)
2764 dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});
2766 // 3 columns
2767 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2769 // accept tracked changes: remove HasTextChangesOnly = false of the inserted cells
2770 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
2772 // still 3 columns
2773 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2775 // delete the text content (dummy character of the previous text change) of the newly
2776 // inserted cell, and accept tracked changes
2777 SwWrtShell* const pWrtShell = getSwDocShell()->GetWrtShell();
2778 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2779 dispatchCommand(mxComponent, u".uno:SwBackspace"_ustr, {});
2780 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
2782 // This was 2 columns (not removed HasTextChangesOnly = false resulted column deletion
2783 // instead of deleting only content of the cell)
2784 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2787 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, tdf156475)
2789 // load a table, and insert a row without change tracking,
2790 // and delete the first column with the empty cell in the second row with change tracking
2791 createSwDoc("tdf118311.fodt");
2792 SwDoc* pDoc = getSwDoc();
2794 // turn off red-lining and show changes
2795 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2796 | RedlineFlags::ShowInsert);
2797 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2798 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2800 CPPUNIT_ASSERT_MESSAGE(
2801 "redlines should be visible",
2802 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2804 // insert table row
2805 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
2807 // check table
2808 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2809 assertXPath(pXmlDoc, "//page[1]//body/tab");
2810 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
2811 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 2);
2812 assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 2);
2814 // turn on red-lining
2815 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2816 | RedlineFlags::ShowInsert);
2817 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2818 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2820 // delete table column with enabled change tracking
2821 // (HasTextChangesOnly property of the cell will be false)
2822 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2824 // go down to the empty cell
2825 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
2826 pWrtShell->Down(/*bSelect=*/false);
2828 // Without the fix in place, this couldn't work
2829 dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
2831 pXmlDoc = parseLayoutDump();
2832 assertXPath(pXmlDoc, "//page[1]//body/tab");
2833 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
2834 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 1);
2835 assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 1);
2837 // test Undo/Redo
2838 for (sal_Int32 i = 0; i < 4; ++i)
2840 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2843 for (sal_Int32 i = 0; i < 4; ++i)
2845 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
2849 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155747)
2851 // load a table, and delete the first column with enabled change tracking:
2852 // now the column is not deleted silently, but keeps the deleted cell content,
2853 // and only accepting it will result the deletion of the table column.
2854 createSwDoc("tdf118311.fodt");
2855 SwDoc* pDoc = getSwDoc();
2857 // turn on red-lining and show changes
2858 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2859 | RedlineFlags::ShowInsert);
2860 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2861 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2862 CPPUNIT_ASSERT_MESSAGE(
2863 "redlines should be visible",
2864 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2866 // delete table column with enabled change tracking
2867 // (HasTextChangesOnly property of the cell will be false)
2868 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2870 // select table
2871 dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
2873 // Without the fix in place, this test would have crashed here
2874 dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
2876 // check removed column
2877 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2878 assertXPath(pXmlDoc, "//page[1]//body/tab");
2879 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2882 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156544)
2884 // load a table, and insert a column without change tracking,
2885 // and delete the first column with the empty cell in the second row with change tracking
2886 createSwDoc("tdf118311.fodt");
2887 SwDoc* pDoc = getSwDoc();
2889 // turn off red-lining and show changes
2890 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2891 | RedlineFlags::ShowInsert);
2892 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2893 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2895 CPPUNIT_ASSERT_MESSAGE(
2896 "redlines should be visible",
2897 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2899 // insert table column without change tracking
2900 // (HasTextChangesOnly property of the cell will be false)
2901 dispatchCommand(mxComponent, u".uno:InsertColumnsBefore"_ustr, {});
2903 // check table
2904 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2905 assertXPath(pXmlDoc, "//page[1]//body/tab");
2906 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2907 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 3);
2909 // turn on red-lining
2910 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2911 | RedlineFlags::ShowInsert);
2912 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2913 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2915 // go to the empty column
2916 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
2917 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2919 // delete table column with enabled change tracking
2920 // (HasTextChangesOnly property of the cell will be false)
2921 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2923 pXmlDoc = parseLayoutDump();
2924 assertXPath(pXmlDoc, "//page[1]//body/tab");
2925 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2927 // This was 2 (deleted column)
2928 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
2930 // accept the deletion of the empty column
2931 dispatchCommand(mxComponent, u".uno:AcceptTrackedChange"_ustr, {});
2933 pXmlDoc = parseLayoutDump();
2934 assertXPath(pXmlDoc, "//page[1]//body/tab");
2935 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2936 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2938 // test Undo/Redo
2939 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
2941 pXmlDoc = parseLayoutDump();
2942 assertXPath(pXmlDoc, "//page[1]//body/tab");
2943 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2944 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
2946 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
2948 pXmlDoc = parseLayoutDump();
2949 assertXPath(pXmlDoc, "//page[1]//body/tab");
2950 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2951 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2954 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156487)
2956 // load a table, and delete a column in Hide Changes mode
2957 createSwDoc("tdf118311.fodt");
2958 SwDoc* pDoc = getSwDoc();
2960 // turn on red-lining and hide changes
2961 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
2962 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2963 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2965 CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible",
2966 !IDocumentRedlineAccess::IsShowChanges(
2967 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2969 // delete table column with enabled change tracking
2970 // (HasTextChangesOnly property of the cell will be false)
2971 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
2973 // Dump the rendering of the first page as an XML file.
2974 SwDocShell* pShell = getSwDocShell();
2975 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2976 MetafileXmlDump dumper;
2977 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2978 CPPUNIT_ASSERT(pXmlDoc);
2980 // This would be 2 without hiding the first cell
2981 assertXPath(pXmlDoc, "/metafile/push/push/push/textarray/text", 1);
2984 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
2986 // load a table, and delete the first column with enabled change tracking:
2987 // now the column is not deleted silently, but keeps the deleted cell content,
2988 // and only accepting it will result the deletion of the table column.
2989 createSwDoc("tdf149498.docx");
2991 // select table, copy, paste and Undo
2992 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
2993 dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
2994 dispatchCommand(mxComponent, u".uno:Paste"_ustr, {});
2996 // this would crash due to bookmark over cell boundary
2997 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3000 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150673_RedlineTableColumnDeletionWithExport)
3002 // load a table, and delete the first column with enabled change tracking:
3003 // now the column is not deleted silently, but keeps the deleted cell contents,
3004 // and only accepting all of them will result the deletion of the table column.
3005 createSwDoc("tdf118311.fodt");
3006 SwDoc* pDoc = getSwDoc();
3008 // turn on red-lining and show changes
3009 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3010 | RedlineFlags::ShowInsert);
3011 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3012 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3013 CPPUNIT_ASSERT_MESSAGE(
3014 "redlines should be visible",
3015 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3017 // check table
3018 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3019 assertXPath(pXmlDoc, "//page[1]//body/tab");
3021 // delete table column with enabled change tracking
3022 // (HasTextChangesOnly property of the cell will be false)
3023 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
3025 // Deleted text content with change tracking,
3026 // but not table deletion
3027 pXmlDoc = parseLayoutDump();
3028 assertXPath(pXmlDoc, "//page[1]//body/tab");
3029 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3031 // Save it and load it back.
3032 saveAndReload(u"writer8"_ustr);
3033 pDoc = getSwDoc();
3035 // accept the deletion of the content of the first cell
3036 SwEditShell* const pEditShell(pDoc->GetEditShell());
3037 CPPUNIT_ASSERT(pEditShell);
3038 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
3039 pEditShell->AcceptRedline(0);
3041 // first table column was deleted finally
3042 // (working export/import of HasTextChangesOnly)
3043 pXmlDoc = parseLayoutDump();
3044 assertXPath(pXmlDoc, "//page[1]//body/tab");
3045 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
3047 // check removing HasTextChangesOnly at acceptance of the deletion
3049 // Undo, and delete the column without change tracking
3050 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3052 // table column exists again
3053 pXmlDoc = parseLayoutDump();
3054 assertXPath(pXmlDoc, "//page[1]//body/tab");
3055 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3057 // reject deletion, setting HasTextChangesOnly to TRUE
3058 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
3059 pEditShell->RejectRedline(0);
3060 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
3062 // delete table column with enabled change tracking
3063 dispatchCommand(mxComponent, u".uno:SelectColumn"_ustr, {});
3064 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
3066 // Table column still exists
3067 pXmlDoc = parseLayoutDump();
3068 assertXPath(pXmlDoc, "//page[1]//body/tab");
3069 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3071 // reject the deletion of the content of the first cell
3072 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
3073 pEditShell->AcceptRedline(0);
3075 // table column is still not deleted
3076 pXmlDoc = parseLayoutDump();
3077 assertXPath(pXmlDoc, "//page[1]//body/tab");
3078 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3081 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletionWithDOCXExport)
3083 // load a 1-row table, and delete the first column with enabled change tracking:
3084 createSwDoc("tdf118311.fodt");
3085 SwDoc* pDoc = getSwDoc();
3087 // turn on red-lining and show changes
3088 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3089 | RedlineFlags::ShowInsert);
3090 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3091 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3092 CPPUNIT_ASSERT_MESSAGE(
3093 "redlines should be visible",
3094 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3096 // check table
3097 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3098 assertXPath(pXmlDoc, "//page[1]//body/tab");
3099 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3101 // delete first table column with enabled change tracking
3102 // (HasTextChangesOnly property of the cell will be false)
3103 dispatchCommand(mxComponent, u".uno:DeleteColumns"_ustr, {});
3105 // Deleted text content with change tracking,
3106 // but not table deletion
3107 pXmlDoc = parseLayoutDump();
3108 assertXPath(pXmlDoc, "//page[1]//body/tab");
3109 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3111 // Save it to a DOCX and load it back.
3112 // Exporting change tracking of the cell wasn't supported.
3113 // Also Manage Changes for the import.
3114 saveAndReload(u"Office Open XML Text"_ustr);
3115 pDoc = getSwDoc();
3117 // accept the deletion of the content of the first cell
3118 SwEditShell* const pEditShell(pDoc->GetEditShell());
3119 CPPUNIT_ASSERT(pEditShell);
3120 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
3121 pEditShell->AcceptRedline(0);
3123 // table column was deleted
3124 // (working export/import of HasTextChangesOnly of table cells)
3125 pXmlDoc = parseLayoutDump();
3126 assertXPath(pXmlDoc, "//page[1]//body/tab");
3127 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
3130 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155341_RedlineTableColumnInsertionWithExport)
3132 // load a table, and insert a new column with enabled change tracking
3133 createSwDoc("tdf118311.fodt");
3134 SwDoc* pDoc = getSwDoc();
3136 // turn on red-lining and show changes
3137 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3138 | RedlineFlags::ShowInsert);
3139 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3140 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3141 CPPUNIT_ASSERT_MESSAGE(
3142 "redlines should be visible",
3143 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3145 // check table
3146 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3147 assertXPath(pXmlDoc, "//page[1]//body/tab");
3149 // insert table column with enabled change tracking
3150 // (HasTextChangesOnly property of the cell will be false)
3151 dispatchCommand(mxComponent, u".uno:InsertColumnsAfter"_ustr, {});
3153 // text content with change tracking (dummy redline)
3154 pXmlDoc = parseLayoutDump();
3155 assertXPath(pXmlDoc, "//page[1]//body/tab");
3156 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
3158 // Save it and load it back.
3159 saveAndReload(u"writer8"_ustr);
3160 pDoc = getSwDoc();
3162 // reject the insertion of the hidden content of the cell
3163 SwEditShell* const pEditShell(pDoc->GetEditShell());
3164 CPPUNIT_ASSERT(pEditShell);
3165 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
3166 pEditShell->RejectRedline(0);
3168 // inserted table column was deleted
3169 // (working export/import of HasTextChangesOnly)
3170 pXmlDoc = parseLayoutDump();
3171 assertXPath(pXmlDoc, "//page[1]//body/tab");
3172 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3175 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
3177 // Load the bugdoc, which has 3 textboxes.
3178 createSwDoc("tdf128335.odt");
3180 // Select the 3rd textbox.
3181 SwView* pView = getSwDocShell()->GetView();
3182 selectShape(1);
3183 SwXTextDocument* pTextDoc = getSwTextDoc();
3184 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3185 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3186 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3187 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3188 Scheduler::ProcessEventsToIdle();
3190 // Cut it.
3191 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3193 // Paste it: this makes the 3rd textbox anchored in the 2nd one.
3194 pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
3196 selectShape(1);
3198 // Cut them.
3199 // Without the accompanying fix in place, this test would have crashed as the textboxes were
3200 // deleted in an incorrect order.
3201 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3204 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithReject)
3206 // load a 1-row table, and delete the row with enabled change tracking:
3207 // now the row is not deleted silently, but keeps the deleted cell contents,
3208 // and only accepting all of them will result the deletion of the table row.
3209 createSwDoc("tdf118311.fodt");
3210 SwDoc* pDoc = getSwDoc();
3212 // turn on red-lining and show changes
3213 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3214 | RedlineFlags::ShowInsert);
3215 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3216 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3217 CPPUNIT_ASSERT_MESSAGE(
3218 "redlines should be visible",
3219 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3221 // check table
3222 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3223 assertXPath(pXmlDoc, "//page[1]//body/tab");
3225 // delete table row with enabled change tracking
3226 // (HasTextChangesOnly property of the row will be false)
3227 dispatchCommand(mxComponent, u".uno:DeleteRows"_ustr, {});
3229 // Deleted text content with change tracking,
3230 // but not table deletion
3231 pXmlDoc = parseLayoutDump();
3232 assertXPath(pXmlDoc, "//page[1]//body/tab");
3234 // Save it and load it back.
3235 saveAndReload(u"writer8"_ustr);
3236 pDoc = getSwDoc();
3238 // reject the deletion of the content of the first cell
3239 // HasTextChangesOnly property of the table row will be true
3240 SwEditShell* const pEditShell(pDoc->GetEditShell());
3241 CPPUNIT_ASSERT(pEditShell);
3242 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3243 pEditShell->RejectRedline(0);
3245 // Select and delete the content of the first cell
3246 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3247 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
3249 // table row was still not deleted
3250 pXmlDoc = parseLayoutDump();
3251 assertXPath(pXmlDoc, "//page[1]//body/tab");
3253 // accept all redlines
3254 while (pEditShell->GetRedlineCount())
3255 pEditShell->AcceptRedline(0);
3257 // This was table row deletion instead of remaining the empty row
3258 // (HasTextChangesOnly was false)
3259 pXmlDoc = parseLayoutDump();
3260 assertXPath(pXmlDoc, "//page[1]//body/tab");
3262 // restore HasTextChangesOnly = false
3263 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3264 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3265 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3266 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3267 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3269 // accept all redlines
3270 while (pEditShell->GetRedlineCount())
3271 pEditShell->AcceptRedline(0);
3273 // table row (and the 1-row table) was deleted finally
3274 pXmlDoc = parseLayoutDump();
3275 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
3278 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowInsertionWithReject)
3280 // load a 1-row table, and insert a row with enabled change tracking
3281 createSwDoc("tdf118311.fodt");
3282 SwDoc* pDoc = getSwDoc();
3284 // turn on red-lining and show changes
3285 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3286 | RedlineFlags::ShowInsert);
3287 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3288 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3289 CPPUNIT_ASSERT_MESSAGE(
3290 "redlines should be visible",
3291 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3293 // check table and its single row
3294 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3295 assertXPath(pXmlDoc, "//page[1]//body/tab");
3296 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3298 // insert rows before and after with enabled change tracking
3299 // (HasTextChangesOnly property of the row will be false, and
3300 // add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
3301 dispatchCommand(mxComponent, u".uno:InsertRowsBefore"_ustr, {});
3302 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
3304 SwEditShell* const pEditShell(pDoc->GetEditShell());
3305 CPPUNIT_ASSERT(pEditShell);
3306 // This was 0 (not tracked row insertion)
3307 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3309 pXmlDoc = parseLayoutDump();
3310 assertXPath(pXmlDoc, "//page[1]//body/tab");
3311 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3313 // reject redlines
3314 pEditShell->RejectRedline(0);
3315 pEditShell->RejectRedline(0);
3317 pXmlDoc = parseLayoutDump();
3318 assertXPath(pXmlDoc, "//page[1]//body/tab");
3319 // This was 3 (not rejected row insertion)
3320 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3323 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145089_RedlineTableRowInsertionDOCX)
3325 // load a 1-row table, and insert a row with enabled change tracking
3326 createSwDoc("tdf118311.fodt");
3327 SwDoc* pDoc = getSwDoc();
3329 // turn on red-lining and show changes
3330 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3331 | RedlineFlags::ShowInsert);
3332 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3333 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3334 CPPUNIT_ASSERT_MESSAGE(
3335 "redlines should be visible",
3336 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3338 // check table and its single row
3339 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3340 assertXPath(pXmlDoc, "//page[1]//body/tab");
3341 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3343 // insert rows before and after with enabled change tracking
3344 // (HasTextChangesOnly property of the row will be false, and
3345 // add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
3346 dispatchCommand(mxComponent, u".uno:InsertRowsBefore"_ustr, {});
3347 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
3349 // save it to DOCX
3350 saveAndReload(u"Office Open XML Text"_ustr);
3351 SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
3352 pViewShell->Reformat();
3353 pXmlDoc = parseLayoutDump();
3355 assertXPath(pXmlDoc, "//page[1]//body/tab");
3356 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3358 // reject redlines
3359 SwDoc* pDOCXDoc(getSwDoc());
3360 SwEditShell* const pEditShell(pDOCXDoc->GetEditShell());
3361 CPPUNIT_ASSERT(pEditShell);
3362 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3363 pEditShell->RejectRedline(0);
3364 pEditShell->RejectRedline(0);
3366 pXmlDoc = parseLayoutDump();
3367 assertXPath(pXmlDoc, "//page[1]//body/tab");
3369 // This was 3 (not rejected row insertion)
3370 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3373 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRow)
3375 // load a 1-row table
3376 createSwDoc("tdf118311.fodt");
3377 SwDoc* pDoc = getSwDoc();
3379 // turn on red-lining and show changes
3380 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3381 | RedlineFlags::ShowInsert);
3382 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3383 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3384 CPPUNIT_ASSERT_MESSAGE(
3385 "redlines should be visible",
3386 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3388 // check table count
3389 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3390 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3391 uno::UNO_QUERY);
3392 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3394 // check table row count
3395 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3396 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3398 // copy table row and paste it by Paste Special->Rows Above
3399 dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
3400 dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
3401 dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
3402 dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
3404 // 2-row table
3405 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3407 // This was 2 (inserted as a nested table in the first cell of the new row)
3408 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3410 // Is it a tracked row insertion? Its rejection results the original 1-row table
3411 dispatchCommand(mxComponent, u".uno:RejectAllTrackedChanges"_ustr, {});
3412 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3414 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3415 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3417 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
3418 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3421 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRowInHideChangesMode)
3423 // load a 1-row table
3424 createSwDoc("tdf118311.fodt");
3425 SwDoc* pDoc = getSwDoc();
3427 // turn on red-lining and show changes
3428 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
3429 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3430 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3431 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
3432 !IDocumentRedlineAccess::IsShowChanges(
3433 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3435 // check table count
3436 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3437 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3438 uno::UNO_QUERY);
3439 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3441 // check table row count
3442 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3443 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3445 // copy table row and paste it by Paste Special->Rows Above
3446 dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
3447 dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
3448 dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
3450 // This resulted freezing
3451 dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
3453 // 2-row table
3454 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3456 // This was 2 (inserted as a nested table in the first cell of the new row)
3457 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3459 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3460 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3461 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
3462 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3464 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
3465 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3468 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf146966)
3470 // load a 4-row table, select more than 1 row and copy them
3471 // to check insertion of unnecessary empty rows
3472 createSwDoc("tdf144748.fodt");
3474 // check table row count
3475 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3476 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3477 uno::UNO_QUERY);
3478 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3479 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3480 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
3482 // copy table row and paste it by Paste Special->Rows Above
3483 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
3484 pWrtShell->Down(/*bSelect=*/false);
3485 dispatchCommand(mxComponent, u".uno:SelectTable"_ustr, {});
3486 dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
3487 dispatchCommand(mxComponent, u".uno:Escape"_ustr, {});
3488 dispatchCommand(mxComponent, u".uno:PasteRowsBefore"_ustr, {});
3490 // This was 35 (extra empty rows)
3491 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
3493 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3494 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3495 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); // FIXME Why 3 Undos?
3496 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
3498 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
3499 dispatchCommand(mxComponent, u".uno:Redo"_ustr, {});
3500 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
3501 // dispatchCommand(mxComponent, ".uno:Redo", {}); // FIXME assert
3504 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145091)
3506 // load a deleted table, reject them, and delete only its text and export to DOCX
3507 createSwDoc("tdf145091.docx");
3508 SwDoc* pDoc = getSwDoc();
3510 // turn on red-lining and show changes
3511 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3512 | RedlineFlags::ShowInsert);
3513 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3514 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3515 CPPUNIT_ASSERT_MESSAGE(
3516 "redlines should be visible",
3517 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3519 // reject all redlines
3520 SwEditShell* const pEditShell(pDoc->GetEditShell());
3521 CPPUNIT_ASSERT(pEditShell);
3522 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
3523 while (pEditShell->GetRedlineCount() > 0)
3524 pEditShell->RejectRedline(0);
3525 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
3527 // delete only table text, but not table
3528 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3529 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3530 dispatchCommand(mxComponent, u".uno:Delete"_ustr, {});
3531 CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
3533 // save it to DOCX
3534 saveAndReload(u"Office Open XML Text"_ustr);
3535 SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
3536 pViewShell->Reformat();
3537 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3539 assertXPath(pXmlDoc, "//page[1]//body/tab");
3540 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3542 // accept all redlines
3543 dispatchCommand(mxComponent, u".uno:AcceptAllTrackedChanges"_ustr, {});
3545 pXmlDoc = parseLayoutDump();
3546 // This was false (deleted table with accepting deletions)
3547 assertXPath(pXmlDoc, "//page[1]//body/tab");
3548 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3551 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128603)
3553 // Load the bugdoc, which has 3 textboxes.
3554 createSwDoc("tdf128603.odt");
3555 SwDoc* pDoc = getSwDoc();
3557 // Select the 3rd textbox.
3558 SwView* pView = getSwDocShell()->GetView();
3559 selectShape(1);
3560 SwXTextDocument* pTextDoc = getSwTextDoc();
3561 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3562 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3563 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3564 pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3565 Scheduler::ProcessEventsToIdle();
3567 // Cut it.
3568 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3570 // Paste it: this makes the 3rd textbox anchored in the 2nd one.
3571 pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
3573 // Undo all of this.
3574 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
3575 rUndoManager.Undo();
3576 rUndoManager.Undo();
3578 // Make sure the content indexes still match.
3579 const auto& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
3580 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), rSpzFrameFormats.size());
3581 const SwNodeIndex* pIndex4 = rSpzFrameFormats[4]->GetContent().GetContentIdx();
3582 CPPUNIT_ASSERT(pIndex4);
3583 const SwNodeIndex* pIndex5 = rSpzFrameFormats[5]->GetContent().GetContentIdx();
3584 CPPUNIT_ASSERT(pIndex5);
3585 // Without the accompanying fix in place, this test would have failed with:
3586 // - Expected: 11
3587 // - Actual : 14
3588 // i.e. the shape content index and the frame content index did not match after undo, even if
3589 // their "other text box format" pointers pointed to each other.
3590 CPPUNIT_ASSERT_EQUAL(pIndex4->GetIndex(), pIndex5->GetIndex());
3593 // only care that it doesn't assert/crash
3594 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testOfz18563)
3596 OUString sURL(m_directories.getURLFromSrc(u"/sw/qa/extras/uiwriter/data/ofz18563.docx"));
3597 SvFileStream aFileStream(sURL, StreamMode::READ);
3598 TestImportDOCX(aFileStream);
3601 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143904)
3603 createSwDoc("tdf143904.odt");
3604 SwDoc* pDoc = getSwDoc();
3606 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
3607 CPPUNIT_ASSERT(pWrtShell);
3609 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3611 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
3612 pWrtShell->Down(false);
3613 pWrtShell->Insert(u"foo"_ustr);
3615 SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3616 CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
3617 nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3618 SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3619 CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTextNodeA2->GetText());
3620 CPPUNIT_ASSERT_EQUAL(false, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
3621 OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
3622 CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr, sFontName);
3625 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf90069)
3627 createSwDoc("tdf90069.docx");
3628 SwDoc* pDoc = getSwDoc();
3630 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
3631 CPPUNIT_ASSERT(pWrtShell);
3633 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3635 dispatchCommand(mxComponent, u".uno:InsertRowsAfter"_ustr, {});
3636 pWrtShell->Down(false);
3637 pWrtShell->Insert(u"foo"_ustr);
3639 SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3640 CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
3641 nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3642 SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3643 CPPUNIT_ASSERT_EQUAL(u"foo"_ustr, pTextNodeA2->GetText());
3644 CPPUNIT_ASSERT_EQUAL(true, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
3645 OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
3646 CPPUNIT_ASSERT_EQUAL(u"Lohit Devanagari"_ustr, sFontName);
3649 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf109266)
3651 // transliteration with redlining
3652 createSwDoc("lorem.fodt");
3653 SwDoc* pDoc = getSwDoc();
3654 SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
3655 CPPUNIT_ASSERT(pWrtShell);
3657 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3658 SwTextNode* pTextNode = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3660 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum..."_ustr, pTextNode->GetText());
3661 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum..."_ustr, pTextNode->GetRedlineText());
3663 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3664 dispatchCommand(mxComponent, u".uno:ChangeCaseToTitleCase"_ustr, {});
3666 CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetText());
3667 CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetRedlineText());
3669 //turn on red-lining and show changes
3670 RedlineFlags const mode(pWrtShell->GetRedlineFlags() | RedlineFlags::On);
3671 CPPUNIT_ASSERT(mode & (RedlineFlags::ShowDelete | RedlineFlags::ShowInsert));
3672 pWrtShell->SetRedlineFlags(mode);
3673 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3674 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3675 CPPUNIT_ASSERT_MESSAGE(
3676 "redlines should be visible",
3677 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3679 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3680 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3681 dispatchCommand(mxComponent, u".uno:ChangeCaseToTitleCase"_ustr, {});
3683 // This was "Lorem Ipsum..." (missing redlining)
3684 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsumIpsum..."_ustr, pTextNode->GetText());
3685 CPPUNIT_ASSERT_EQUAL(u"Lorem Ipsum..."_ustr, pTextNode->GetRedlineText());
3687 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3688 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3689 dispatchCommand(mxComponent, u".uno:ChangeCaseToUpper"_ustr, {});
3691 // This was "LOREM IPSUM..." (missing redlining)
3692 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...LOREM IPSUM..."_ustr, pTextNode->GetText());
3693 CPPUNIT_ASSERT_EQUAL(u"LOREM IPSUM..."_ustr, pTextNode->GetRedlineText());
3695 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3696 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3697 dispatchCommand(mxComponent, u".uno:ChangeCaseToLower"_ustr, {});
3699 // This was "lorem ipsum..." (missing redlining)
3700 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...lorem ipsum..."_ustr, pTextNode->GetText());
3701 CPPUNIT_ASSERT_EQUAL(u"lorem ipsum..."_ustr, pTextNode->GetRedlineText());
3703 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3704 dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
3705 dispatchCommand(mxComponent, u".uno:ChangeCaseToToggleCase"_ustr, {});
3707 // This was "lOREM IPSUM..." (missing redlining)
3708 CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum...lOREM IPSUM..."_ustr, pTextNode->GetText());
3709 CPPUNIT_ASSERT_EQUAL(u"lOREM IPSUM..."_ustr, pTextNode->GetRedlineText());
3712 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf129655)
3714 createSwDoc("tdf129655-vtextbox.odt");
3715 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3716 assertXPath(pXmlDoc, "//anchored/fly/txt[@WritingMode='Vertical']", 1);
3719 static uno::Reference<text::XTextRange> getAssociatedTextRange(uno::Any object)
3721 // possible cases:
3722 // 1. a container of other objects - e.g. selection of 0 to n text portions, or 1 to n drawing objects
3725 uno::Reference<container::XIndexAccess> xIndexAccess(object, uno::UNO_QUERY_THROW);
3726 if (xIndexAccess.is() && xIndexAccess->getCount() > 0)
3728 for (int i = 0; i < xIndexAccess->getCount(); ++i)
3730 uno::Reference<text::XTextRange> xRange
3731 = getAssociatedTextRange(xIndexAccess->getByIndex(i));
3732 if (xRange.is())
3733 return xRange;
3737 catch (const uno::Exception&)
3741 // 2. another TextContent, having an anchor we can use
3744 uno::Reference<text::XTextContent> xTextContent(object, uno::UNO_QUERY_THROW);
3745 if (xTextContent.is())
3747 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
3748 if (xRange.is())
3749 return xRange;
3752 catch (const uno::Exception&)
3756 // an object which supports XTextRange directly
3759 uno::Reference<text::XTextRange> xRange(object, uno::UNO_QUERY_THROW);
3760 if (xRange.is())
3761 return xRange;
3763 catch (const uno::Exception&)
3767 return nullptr;
3770 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf123218)
3772 struct ReverseXAxisOrientationDoughnutChart
3773 : public comphelper::ConfigurationProperty<ReverseXAxisOrientationDoughnutChart, bool>
3775 static OUString path()
3777 return u"/org.openoffice.Office.Compatibility/View/ReverseXAxisOrientationDoughnutChart"_ustr;
3779 ~ReverseXAxisOrientationDoughnutChart() = delete;
3782 struct ClockwisePieChartDirection
3783 : public comphelper::ConfigurationProperty<ClockwisePieChartDirection, bool>
3785 static OUString path()
3787 return u"/org.openoffice.Office.Compatibility/View/ClockwisePieChartDirection"_ustr;
3789 ~ClockwisePieChartDirection() = delete;
3791 auto batch = comphelper::ConfigurationChanges::create();
3793 ReverseXAxisOrientationDoughnutChart::set(false, batch);
3794 ClockwisePieChartDirection::set(true, batch);
3795 batch->commit();
3797 createSwDoc();
3799 // create an OLE shape in the document
3800 uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY_THROW);
3801 CPPUNIT_ASSERT(xMSF);
3802 uno::Reference<beans::XPropertySet> xShapeProps(
3803 xMSF->createInstance(u"com.sun.star.text.TextEmbeddedObject"_ustr), uno::UNO_QUERY);
3804 xShapeProps->setPropertyValue(u"CLSID"_ustr,
3805 uno::Any(u"12dcae26-281f-416f-a234-c3086127382e"_ustr));
3806 uno::Reference<drawing::XShape> xShape(xShapeProps, uno::UNO_QUERY_THROW);
3807 xShape->setSize(awt::Size(16000, 9000));
3808 uno::Reference<text::XTextContent> chartTextContent(xShapeProps, uno::UNO_QUERY_THROW);
3809 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
3810 uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
3811 uno::UNO_QUERY_THROW);
3812 uno::Any aSelection = xSelSupplier->getSelection();
3813 uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
3814 CPPUNIT_ASSERT(xTextRange);
3815 xTextRange->getText()->insertTextContent(xTextRange, chartTextContent, false);
3817 // insert a doughnut chart
3818 uno::Reference<frame::XModel> xDocModel;
3819 xShapeProps->getPropertyValue(u"Model"_ustr) >>= xDocModel;
3820 CPPUNIT_ASSERT(xDocModel);
3821 uno::Reference<chart::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY_THROW);
3822 CPPUNIT_ASSERT(xChartDoc);
3823 uno::Reference<lang::XMultiServiceFactory> xChartMSF(xChartDoc, uno::UNO_QUERY_THROW);
3824 CPPUNIT_ASSERT(xChartMSF);
3825 uno::Reference<chart::XDiagram> xDiagram(
3826 xChartMSF->createInstance(u"com.sun.star.chart.DonutDiagram"_ustr), uno::UNO_QUERY);
3827 xChartDoc->setDiagram(xDiagram);
3829 // test primary X axis Orientation value
3830 uno::Reference<chart2::XChartDocument> xChartDoc2(xChartDoc, uno::UNO_QUERY_THROW);
3831 CPPUNIT_ASSERT(xChartDoc2);
3832 uno::Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(
3833 xChartDoc2->getFirstDiagram(), uno::UNO_QUERY_THROW);
3834 uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence
3835 = xCooSysContainer->getCoordinateSystems();
3836 uno::Reference<chart2::XCoordinateSystem> xCoord = xCooSysSequence[0];
3837 CPPUNIT_ASSERT(xCoord.is());
3838 uno::Reference<chart2::XAxis> xAxis = xCoord->getAxisByDimension(0, 0);
3839 CPPUNIT_ASSERT(xAxis.is());
3840 chart2::ScaleData aScaleData = xAxis->getScaleData();
3841 CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_MATHEMATICAL, aScaleData.Orientation);
3843 // tdf#108059 test primary Y axis Orientation value
3844 uno::Reference<chart2::XAxis> xYAxis = xCoord->getAxisByDimension(1, 0);
3845 CPPUNIT_ASSERT(xYAxis.is());
3846 aScaleData = xYAxis->getScaleData();
3847 CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_REVERSE, aScaleData.Orientation);
3850 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf93747)
3852 createSwDoc();
3853 SwWrtShell* pWrtSh = getSwDocShell()->GetWrtShell();
3855 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
3856 { { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
3858 dispatchCommand(mxComponent, u".uno:InsertTable"_ustr, aArgs);
3860 pWrtSh->Insert(u"Col1"_ustr);
3862 // Move the cursor to B1
3863 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
3865 pWrtSh->Insert(u"Col2"_ustr);
3867 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3868 uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
3869 uno::UNO_QUERY);
3870 uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
3871 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
3872 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
3873 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
3875 uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
3876 CPPUNIT_ASSERT_EQUAL(u"Col1"_ustr, xCellA1->getString());
3878 uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY);
3879 CPPUNIT_ASSERT_EQUAL(u"Col2"_ustr, xCellB1->getString());
3881 // Select backwards B1 and A1
3882 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
3884 // Just select the whole B1
3885 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3887 uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
3888 { "Style", uno::Any(u"Heading 1"_ustr) },
3889 { "FamilyName", uno::Any(u"ParagraphStyles"_ustr) },
3891 dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
3893 // Without the fix in place, this test would have failed with
3894 // - Expected: Table Contents
3895 // - Actual : Heading 1
3896 CPPUNIT_ASSERT_EQUAL(
3897 u"Table Contents"_ustr,
3898 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
3900 CPPUNIT_ASSERT_EQUAL(
3901 u"Heading 1"_ustr,
3902 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
3904 // Now select A1 again
3905 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3907 dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
3909 CPPUNIT_ASSERT_EQUAL(
3910 u"Heading 1"_ustr,
3911 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
3913 CPPUNIT_ASSERT_EQUAL(
3914 u"Heading 1"_ustr,
3915 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
3917 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3919 CPPUNIT_ASSERT_EQUAL(
3920 u"Table Contents"_ustr,
3921 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
3923 CPPUNIT_ASSERT_EQUAL(
3924 u"Heading 1"_ustr,
3925 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
3927 dispatchCommand(mxComponent, u".uno:Undo"_ustr, {});
3929 CPPUNIT_ASSERT_EQUAL(
3930 u"Table Contents"_ustr,
3931 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"ParaStyleName"_ustr));
3933 CPPUNIT_ASSERT_EQUAL(
3934 u"Table Contents"_ustr,
3935 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"ParaStyleName"_ustr));
3938 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145151)
3940 createSwDoc();
3941 SwWrtShell* pWrtSh = getSwDocShell()->GetWrtShell();
3943 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
3944 { { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
3946 dispatchCommand(mxComponent, u".uno:InsertTable"_ustr, aArgs);
3948 pWrtSh->Insert(u"Col1"_ustr);
3950 // Move the cursor to B1
3951 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
3953 pWrtSh->Insert(u"Col2"_ustr);
3955 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3956 uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
3957 uno::UNO_QUERY);
3958 uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
3959 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
3960 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
3961 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
3963 uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
3964 CPPUNIT_ASSERT_EQUAL(u"Col1"_ustr, xCellA1->getString());
3966 uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY);
3967 CPPUNIT_ASSERT_EQUAL(u"Col2"_ustr, xCellB1->getString());
3969 // Select backwards B1 and A1 (select "2loC<cell>" which ends up selecting both cells)
3970 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
3972 // Just select the whole B1
3973 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3975 dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
3977 // B1 should now have a numbering style, but A1 should not be affected.
3978 OUString sNumStyleB1 = getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
3979 u"NumberingStyleName"_ustr);
3980 CPPUNIT_ASSERT(!sNumStyleB1.isEmpty());
3981 CPPUNIT_ASSERT_MESSAGE(
3982 "Only cell B1 was selected. A1 should not have any numbering.",
3983 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), u"NumberingStyleName"_ustr)
3984 .isEmpty());
3986 // Toggle it back off
3987 dispatchCommand(mxComponent, u".uno:DefaultNumbering"_ustr, {});
3989 CPPUNIT_ASSERT_MESSAGE(
3990 "Cell B1 must be able to toggle numbering on and off.",
3991 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"NumberingStyleName"_ustr)
3992 .isEmpty());
3994 // Now test removing numbering/bullets
3995 // Add A1 to the current B1 selection
3996 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3998 // Toggle on bullet numbering
3999 dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
4001 // sanity check - both cells have bullets turned on.
4002 OUString sNumStyleA1 = getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()),
4003 u"NumberingStyleName"_ustr);
4004 CPPUNIT_ASSERT(!sNumStyleA1.isEmpty());
4005 CPPUNIT_ASSERT_EQUAL(sNumStyleA1,
4006 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
4007 u"NumberingStyleName"_ustr));
4008 CPPUNIT_ASSERT(sNumStyleA1 != sNumStyleB1); // therefore B1 changed from numbering to bullets
4010 // Just select cell B1
4011 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
4013 // Toggle off bullet numbering
4014 dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
4016 // B1 should now have removed all numbering, while A1 should still have the bullet.
4017 CPPUNIT_ASSERT(
4018 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), u"NumberingStyleName"_ustr)
4019 .isEmpty());
4020 CPPUNIT_ASSERT_MESSAGE("Only cell B1 was selected. A1 should still have bullets turned on.",
4021 !getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()),
4022 u"NumberingStyleName"_ustr)
4023 .isEmpty());
4025 // Toggle it back on
4026 dispatchCommand(mxComponent, u".uno:DefaultBullet"_ustr, {});
4028 CPPUNIT_ASSERT(!getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()),
4029 u"NumberingStyleName"_ustr)
4030 .isEmpty());
4033 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126735)
4035 createSwDoc("tdf39721.fodt");
4036 SwDoc* pDoc = getSwDoc();
4038 //turn on red-lining and show changes
4039 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
4040 | RedlineFlags::ShowInsert);
4041 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
4042 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
4043 CPPUNIT_ASSERT_MESSAGE(
4044 "redlines should be visible",
4045 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
4047 // check next selected tracked change
4048 dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
4049 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
4050 uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
4051 uno::UNO_QUERY_THROW);
4052 uno::Any aSelection = xSelSupplier->getSelection();
4053 uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
4054 CPPUNIT_ASSERT(xTextRange);
4055 CPPUNIT_ASSERT_EQUAL(u" ipsu"_ustr, xTextRange->getString());
4057 // check next selected tracked change
4058 dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
4059 aSelection = xSelSupplier->getSelection();
4060 xTextRange = getAssociatedTextRange(aSelection);
4061 CPPUNIT_ASSERT(xTextRange);
4062 CPPUNIT_ASSERT_EQUAL(u"or "_ustr, xTextRange->getString());
4064 // check next selected tracked change at the end of the document:
4065 // select the first tracked change of the document
4066 dispatchCommand(mxComponent, u".uno:NextTrackedChange"_ustr, {});
4067 aSelection = xSelSupplier->getSelection();
4068 xTextRange = getAssociatedTextRange(aSelection);
4069 CPPUNIT_ASSERT(xTextRange);
4070 // This was empty (collapsing at the end of the last tracked change)
4071 CPPUNIT_ASSERT_EQUAL(u" ipsu"_ustr, xTextRange->getString());
4073 // check the previous tracked change at the start of the document:
4074 // select the last tracked change of the document
4075 dispatchCommand(mxComponent, u".uno:PreviousTrackedChange"_ustr, {});
4076 aSelection = xSelSupplier->getSelection();
4077 xTextRange = getAssociatedTextRange(aSelection);
4078 CPPUNIT_ASSERT(xTextRange);
4079 // This was empty (collapsing at the start of the last tracked change)
4080 CPPUNIT_ASSERT_EQUAL(u"or "_ustr, xTextRange->getString());
4083 CPPUNIT_PLUGIN_IMPLEMENT();
4085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */