Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / extras / uiwriter / uiwriter5.cxx
blob285a3adb7c615815a80610462b7ed310b3816825
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>
56 /// Second set of tests asserting the behavior of Writer user interface shells.
57 class SwUiWriterTest5 : public SwModelTestBase
59 public:
60 SwUiWriterTest5()
61 : SwModelTestBase("/sw/qa/extras/uiwriter/data/")
65 protected:
66 AllSettings m_aSavedSettings;
69 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf139127)
71 createSwDoc("tdf139127.fodt");
72 SwDoc* pDoc = getSwDoc();
73 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
75 // switch on "Show changes in margin" mode
76 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
78 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->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, ".uno:GoToEndOfDoc", {});
95 dispatchCommand(mxComponent, ".uno:SwBackspace", {});
96 dispatchCommand(mxComponent, ".uno:SwBackspace", {});
97 CPPUNIT_ASSERT_EQUAL(1, getPages());
98 CPPUNIT_ASSERT_EQUAL(OUString("First page"), pTextDoc->getText()->getString());
100 // Undo
101 dispatchCommand(mxComponent, ".uno:Undo", {});
102 // this would crash due to bad redline range
103 dispatchCommand(mxComponent, ".uno:Undo", {});
104 CPPUNIT_ASSERT_EQUAL(2, getPages());
105 CPPUNIT_ASSERT_EQUAL(OUString("First page"), getParagraph(1)->getString());
106 CPPUNIT_ASSERT_EQUAL(OUString("B"), getParagraph(2)->getString());
108 // switch off "Show changes in margin" mode
109 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
110 CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
113 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138479)
115 createSwDoc();
116 SwDoc* const pDoc = getSwDoc();
118 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
120 pWrtShell->Insert("Lorem");
121 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), getParagraph(1)->getString());
123 //turn on red-lining and show changes
124 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
125 | RedlineFlags::ShowInsert);
126 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
127 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
128 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
129 CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible",
130 !IDocumentRedlineAccess::IsShowChanges(
131 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
133 // switch on "Show changes in margin" mode
134 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
136 // delete "r" in "Lorem"
137 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 3, /*bBasicCall=*/false);
138 dispatchCommand(mxComponent, ".uno:Delete", {});
139 CPPUNIT_ASSERT_EQUAL(OUString("Loem"), getParagraph(1)->getString());
141 // delete "oe" in "Loem"
142 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
143 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 2, /*bBasicCall=*/false);
144 dispatchCommand(mxComponent, ".uno:Delete", {});
145 CPPUNIT_ASSERT_EQUAL(OUString("Lm"), getParagraph(1)->getString());
147 // test embedded Undo in ChangesInMargin mode
148 dispatchCommand(mxComponent, ".uno:Undo", {});
149 CPPUNIT_ASSERT_EQUAL(OUString("Loem"), getParagraph(1)->getString());
151 dispatchCommand(mxComponent, ".uno:Undo", {});
152 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), getParagraph(1)->getString());
154 // this would crash due to bad redline range
155 for (int i = 0; i < 5; ++i)
156 dispatchCommand(mxComponent, ".uno:Undo", {});
158 // switch off "Show changes in margin" mode
159 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
160 CPPUNIT_ASSERT(!pWrtShell->GetViewOptions()->IsShowChangesInMargin());
163 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf138666)
165 createSwDoc("tdf39721.fodt");
166 SwDoc* pDoc = getSwDoc();
168 //turn on red-lining and show changes
169 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
170 | RedlineFlags::ShowInsert);
171 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
172 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
173 CPPUNIT_ASSERT_MESSAGE(
174 "redlines should be visible",
175 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
177 // show deletions inline
178 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), getParagraph(1)->getString());
179 CPPUNIT_ASSERT_EQUAL(OUString("dolor sit"), getParagraph(2)->getString());
181 // switch on "Show changes in margin" mode
182 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
184 // show deletions in margin
185 CPPUNIT_ASSERT_EQUAL(OUString("Loremm"), getParagraph(1)->getString());
186 CPPUNIT_ASSERT_EQUAL(OUString("dolsit"), getParagraph(2)->getString());
188 // switch off "Show changes in margin" mode
189 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
191 // show deletions inline again
192 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), getParagraph(1)->getString());
193 CPPUNIT_ASSERT_EQUAL(OUString("dolor sit"), getParagraph(2)->getString());
196 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf140982)
198 createSwDoc("tdf115815.odt");
199 SwDoc* pDoc = getSwDoc();
201 //turn on red-lining and show changes
202 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
203 | RedlineFlags::ShowInsert);
204 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
205 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
206 CPPUNIT_ASSERT_MESSAGE(
207 "redlines should be visible",
208 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
210 // show deletions inline
211 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum dolor sit amet..."), getParagraph(1)->getString());
213 // switch on "Show changes in margin" mode
214 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
216 // show deletions in margin
217 CPPUNIT_ASSERT_EQUAL(OUString("Lorem amet..."), getParagraph(1)->getString());
219 // switch off "Show changes in margin" mode
220 dispatchCommand(mxComponent, ".uno:ShowChangesInMargin", {});
222 // show deletions inline again
223 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum dolor sit amet..."), getParagraph(1)->getString());
225 // Save it and load it back.
226 saveAndReload("writer8");
228 // Test comment range feature on tracked deletion.
229 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
230 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
231 uno::UNO_QUERY);
232 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
233 uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
234 uno::UNO_QUERY);
235 uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
236 bool bAnnotationStart = false;
237 bool bBeforeAnnotation = true;
238 OUString sTextBeforeAnnotation;
239 while (xRunEnum->hasMoreElements())
241 uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
242 OUString aType = getProperty<OUString>(xPropertySet, "TextPortionType");
243 // there is no AnnotationEnd with preceding AnnotationStart,
244 // i.e. annotation with lost range
245 CPPUNIT_ASSERT(aType != "AnnotationEnd" || !bAnnotationStart);
247 bAnnotationStart = (aType == "Annotation");
249 // collect paragraph text before the first annotation
250 if (bBeforeAnnotation)
252 if (bAnnotationStart)
253 bBeforeAnnotation = false;
254 else if (aType == "Text")
256 uno::Reference<text::XTextRange> xRun(xPropertySet, uno::UNO_QUERY);
257 sTextBeforeAnnotation += xRun->getString();
262 // This was "Lorem ipsum" (collapsed annotation range)
263 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), sTextBeforeAnnotation);
266 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126206)
268 createSwDoc("tdf126206.docx");
270 // normal text (it was bold)
271 auto xText = getParagraph(1)->getText();
272 CPPUNIT_ASSERT(xText.is());
274 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 4)));
275 CPPUNIT_ASSERT(xCursor.is());
276 CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xCursor->getString());
277 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
280 // reject tracked changes
281 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
283 // bold text again
284 xText = getParagraph(1)->getText();
285 CPPUNIT_ASSERT(xText.is());
287 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 3)));
288 CPPUNIT_ASSERT(xCursor.is());
289 CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xCursor->getString());
290 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
294 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447)
296 createSwDoc("tdf126206.docx");
297 SwDoc* pDoc = getSwDoc();
299 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
301 // bold text
302 auto xText = getParagraph(1)->getText();
303 CPPUNIT_ASSERT(xText.is());
305 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
306 CPPUNIT_ASSERT(xCursor.is());
307 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
308 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
311 // remove bold formatting with change tracking
312 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
313 dispatchCommand(mxComponent, ".uno:Bold", {});
315 xText = getParagraph(1)->getText();
316 CPPUNIT_ASSERT(xText.is());
318 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
319 CPPUNIT_ASSERT(xCursor.is());
320 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
321 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
324 // reject tracked changes
325 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
327 // bold text again
328 xText = getParagraph(1)->getText();
329 CPPUNIT_ASSERT(xText.is());
331 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
332 CPPUNIT_ASSERT(xCursor.is());
333 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
334 // This was NORMAL
335 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
339 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143918)
341 createSwDoc("tdf126206.docx");
342 SwDoc* pDoc = getSwDoc();
344 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
346 // bold text
347 auto xText = getParagraph(1)->getText();
348 CPPUNIT_ASSERT(xText.is());
350 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
351 CPPUNIT_ASSERT(xCursor.is());
352 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
353 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
356 // remove bold formatting with change tracking and after that, apply underline, too
357 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
358 dispatchCommand(mxComponent, ".uno:Bold", {});
359 dispatchCommand(mxComponent, ".uno:Underline", {});
361 xText = getParagraph(1)->getText();
362 CPPUNIT_ASSERT(xText.is());
364 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
365 CPPUNIT_ASSERT(xCursor.is());
366 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
367 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
370 // reject tracked changes
371 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
373 // bold text again
374 xText = getParagraph(1)->getText();
375 CPPUNIT_ASSERT(xText.is());
377 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
378 CPPUNIT_ASSERT(xCursor.is());
379 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
380 // This was NORMAL (only underlining was removed)
381 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
385 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143938)
387 createSwDoc("tdf54819.fodt");
388 SwDoc* pDoc = getSwDoc();
390 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
392 // select first paragraph, add underline without change tracking
393 pWrtShell->EndPara(/*bSelect=*/true);
394 dispatchCommand(mxComponent, ".uno:Underline", {});
396 auto xText = getParagraph(1)->getText();
397 CPPUNIT_ASSERT(xText.is());
399 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
400 CPPUNIT_ASSERT(xCursor.is());
401 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xCursor->getString());
402 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
403 getProperty<sal_Int16>(xCursor, "CharUnderline"));
404 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
405 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
408 // turn on red-lining and show changes
409 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
410 | RedlineFlags::ShowInsert);
411 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
412 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
413 CPPUNIT_ASSERT_MESSAGE(
414 "redlines should be visible",
415 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
417 // apply italic with change tracking
418 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
419 dispatchCommand(mxComponent, ".uno:Italic", {});
421 xText = getParagraph(1)->getText();
422 CPPUNIT_ASSERT(xText.is());
424 // (first empty run is associated to the redline)
425 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
426 CPPUNIT_ASSERT(xCursor.is());
427 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xCursor->getString());
428 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
429 getProperty<sal_Int16>(xCursor, "CharUnderline"));
430 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
431 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
434 // reject tracked changes
435 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
437 // no italic, but still underline direct formatting
438 xText = getParagraph(1)->getText();
439 CPPUNIT_ASSERT(xText.is());
441 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
442 CPPUNIT_ASSERT(xCursor.is());
443 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xCursor->getString());
444 // This wasn't underlined (lost direct formatting)
445 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
446 getProperty<sal_Int16>(xCursor, "CharUnderline"));
447 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
448 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
452 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143939)
454 createSwDoc("tdf126206.docx");
455 SwDoc* pDoc = getSwDoc();
457 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
459 // bold text
460 auto xText = getParagraph(1)->getText();
461 CPPUNIT_ASSERT(xText.is());
463 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
464 CPPUNIT_ASSERT(xCursor.is());
465 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString());
466 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
469 // positionate the text cursor inside the first word
470 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
471 // remove bold formatting with change tracking without selection
472 dispatchCommand(mxComponent, ".uno:Bold", {});
474 xText = getParagraph(1)->getText();
475 CPPUNIT_ASSERT(xText.is());
477 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2)));
478 CPPUNIT_ASSERT(xCursor.is());
479 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), xCursor->getString());
480 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xCursor, "CharWeight"));
483 // reject tracked changes
484 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
486 // bold text again
487 xText = getParagraph(1)->getText();
488 CPPUNIT_ASSERT(xText.is());
490 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
491 CPPUNIT_ASSERT(xCursor.is());
492 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), xCursor->getString());
493 // This was NORMAL
494 CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xCursor, "CharWeight"));
498 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf50447_keep_hints)
500 createSwDoc("tdf50447.fodt");
501 SwDoc* pDoc = getSwDoc();
503 // first paragraph (_Lorem_ /ipsum/)
505 auto xText = getParagraph(1)->getText();
506 CPPUNIT_ASSERT(xText.is());
508 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
509 CPPUNIT_ASSERT(xCursor.is());
510 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), xCursor->getString());
511 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
512 getProperty<sal_Int16>(xCursor, "CharUnderline"));
513 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
514 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
516 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
517 CPPUNIT_ASSERT(xCursor.is());
518 CPPUNIT_ASSERT_EQUAL(OUString(" "), xCursor->getString());
519 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
520 getProperty<sal_Int16>(xCursor, "CharUnderline"));
521 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
522 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
524 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
525 CPPUNIT_ASSERT(xCursor.is());
526 CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xCursor->getString());
527 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
528 getProperty<sal_Int16>(xCursor, "CharUnderline"));
529 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
530 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
533 // second paragraph (_dolor_ sit /amet/.)
535 xText = getParagraph(2)->getText();
536 CPPUNIT_ASSERT(xText.is());
538 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
539 CPPUNIT_ASSERT(xCursor.is());
540 CPPUNIT_ASSERT_EQUAL(OUString("dolor"), xCursor->getString());
541 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
542 getProperty<sal_Int16>(xCursor, "CharUnderline"));
543 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
544 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
546 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
547 CPPUNIT_ASSERT(xCursor.is());
548 CPPUNIT_ASSERT_EQUAL(OUString(" sit "), xCursor->getString());
549 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
550 getProperty<sal_Int16>(xCursor, "CharUnderline"));
551 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
552 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
554 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
555 CPPUNIT_ASSERT(xCursor.is());
556 CPPUNIT_ASSERT_EQUAL(OUString("amet"), xCursor->getString());
557 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
558 getProperty<sal_Int16>(xCursor, "CharUnderline"));
559 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
560 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
563 // turn on red-lining and show changes
564 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
565 | RedlineFlags::ShowInsert);
566 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
567 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
568 CPPUNIT_ASSERT_MESSAGE(
569 "redlines should be visible",
570 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
572 // modify character formatting of the all the text
574 dispatchCommand(mxComponent, ".uno:SelectAll", {});
575 dispatchCommand(mxComponent, ".uno:SuperScript", {});
577 // multiple format redlines for the multiple hints
579 SwEditShell* const pEditShell(pDoc->GetEditShell());
580 // This was 1.
581 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(7), pEditShell->GetRedlineCount());
583 // reject tracked changes
585 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
587 // all hints and text portions between them got back the original formatting
589 xText = getParagraph(1)->getText();
590 CPPUNIT_ASSERT(xText.is());
592 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1)));
593 CPPUNIT_ASSERT(xCursor.is());
594 CPPUNIT_ASSERT_EQUAL(OUString("Lorem"), xCursor->getString());
595 // This was NONE
596 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
597 getProperty<sal_Int16>(xCursor, "CharUnderline"));
598 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
599 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
601 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 2));
602 CPPUNIT_ASSERT(xCursor.is());
603 CPPUNIT_ASSERT_EQUAL(OUString(" "), xCursor->getString());
604 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
605 getProperty<sal_Int16>(xCursor, "CharUnderline"));
606 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
607 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
609 xCursor = xText->createTextCursorByRange(getRun(getParagraph(1), 3));
610 CPPUNIT_ASSERT(xCursor.is());
611 CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xCursor->getString());
612 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
613 getProperty<sal_Int16>(xCursor, "CharUnderline"));
614 // This was NONE
615 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
616 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
619 // second paragraph (_dolor_ sit /amet/.)
621 xText = getParagraph(2)->getText();
622 CPPUNIT_ASSERT(xText.is());
624 auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(2), 1)));
625 CPPUNIT_ASSERT(xCursor.is());
626 CPPUNIT_ASSERT_EQUAL(OUString("dolor"), xCursor->getString());
627 // This was NONE
628 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::SINGLE),
629 getProperty<sal_Int16>(xCursor, "CharUnderline"));
630 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
631 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
633 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 2));
634 CPPUNIT_ASSERT(xCursor.is());
635 CPPUNIT_ASSERT_EQUAL(OUString(" sit "), xCursor->getString());
636 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
637 getProperty<sal_Int16>(xCursor, "CharUnderline"));
638 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE,
639 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
641 xCursor = xText->createTextCursorByRange(getRun(getParagraph(2), 3));
642 CPPUNIT_ASSERT(xCursor.is());
643 CPPUNIT_ASSERT_EQUAL(OUString("amet"), xCursor->getString());
644 CPPUNIT_ASSERT_EQUAL(sal_Int16(awt::FontUnderline::NONE),
645 getProperty<sal_Int16>(xCursor, "CharUnderline"));
646 // This was NONE
647 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_ITALIC,
648 getProperty<awt::FontSlant>(xCursor, "CharPosture"));
652 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144272)
654 createSwDoc("tdf50447.fodt");
655 SwDoc* pDoc = getSwDoc();
657 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
659 // turn on red-lining and show changes
660 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
661 | RedlineFlags::ShowInsert);
662 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
663 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
664 CPPUNIT_ASSERT_MESSAGE(
665 "redlines should be visible",
666 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
668 // paragraph style of the first paragraph: Heading 1, second paragraph: Standard
670 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
671 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
672 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
673 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
675 // modify with track changes: Standard and Heading 2
677 uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
678 { "Style", uno::Any(OUString("Standard")) },
679 { "FamilyName", uno::Any(OUString("ParagraphStyles")) },
681 dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
682 pWrtShell->Down(/*bSelect=*/false);
683 aPropertyValues = comphelper::InitPropertySequence({
684 { "Style", uno::Any(OUString("Heading 2")) },
685 { "FamilyName", uno::Any(OUString("ParagraphStyles")) },
687 dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
689 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
690 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
691 CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"),
692 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
694 // reject tracked changes
695 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
697 // This was Standard (missing reject)
698 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
699 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
700 // This was Heading 2 (missing reject)
701 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
702 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
705 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf101873)
707 createSwDoc();
708 SwDoc* pDoc = getSwDoc();
709 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
710 CPPUNIT_ASSERT(pWrtShell);
712 // Insert some content.
713 pWrtShell->Insert("something");
715 // Search for something which does not exist, twice.
716 uno::Sequence<beans::PropertyValue> aFirst(comphelper::InitPropertySequence({
717 { "SearchItem.SearchString", uno::Any(OUString("fig")) },
718 { "SearchItem.Backward", uno::Any(false) },
719 }));
720 dispatchCommand(mxComponent, ".uno:ExecuteSearch", aFirst);
721 dispatchCommand(mxComponent, ".uno:ExecuteSearch", aFirst);
723 uno::Sequence<beans::PropertyValue> aSecond(comphelper::InitPropertySequence({
724 { "SearchItem.SearchString", uno::Any(OUString("something")) },
725 { "SearchItem.Backward", uno::Any(false) },
726 }));
727 dispatchCommand(mxComponent, ".uno:ExecuteSearch", aSecond);
729 // Without the accompanying fix in place, this test would have failed with "Expected: something;
730 // Actual:", i.e. searching for "something" failed, even if it was inserted above.
731 SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
732 CPPUNIT_ASSERT_EQUAL(OUString("something"), pShellCursor->GetText());
735 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTextFormFieldInsertion)
737 createSwDoc();
738 SwDoc* pDoc = getSwDoc();
739 CPPUNIT_ASSERT(pDoc);
740 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
741 CPPUNIT_ASSERT(pMarkAccess);
742 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
744 // Insert a text form field
745 dispatchCommand(mxComponent, ".uno:TextFormField", {});
746 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
748 // Check whether the fieldmark is created
749 auto aIter = pMarkAccess->getAllMarksBegin();
750 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
751 ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
752 CPPUNIT_ASSERT(pFieldmark);
753 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMTEXT), pFieldmark->GetFieldname());
755 // The text form field has the placeholder text in it
756 uno::Reference<text::XTextRange> xPara = getParagraph(1);
757 sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
758 CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
760 // Undo insertion
761 dispatchCommand(mxComponent, ".uno:Undo", {});
762 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
763 xPara.set(getParagraph(1));
764 CPPUNIT_ASSERT(xPara->getString().isEmpty());
766 // Redo insertion
767 dispatchCommand(mxComponent, ".uno:Redo", {});
768 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
769 xPara.set(getParagraph(1));
770 CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
773 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testCheckboxFormFieldInsertion)
775 createSwDoc();
776 SwDoc* pDoc = getSwDoc();
777 CPPUNIT_ASSERT(pDoc);
779 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
780 CPPUNIT_ASSERT(pMarkAccess);
781 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
783 // Insert a checkbox form field
784 dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
785 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
787 // Check whether the fieldmark is created
788 auto aIter = pMarkAccess->getAllMarksBegin();
789 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
790 ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
791 CPPUNIT_ASSERT(pFieldmark);
792 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
793 // The checkbox is not checked by default
794 ::sw::mark::ICheckboxFieldmark* pCheckBox
795 = dynamic_cast<::sw::mark::ICheckboxFieldmark*>(pFieldmark);
796 CPPUNIT_ASSERT(pCheckBox);
797 CPPUNIT_ASSERT(!pCheckBox->IsChecked());
799 // Undo insertion
800 dispatchCommand(mxComponent, ".uno:Undo", {});
801 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
803 // Redo insertion
804 dispatchCommand(mxComponent, ".uno:Redo", {});
805 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
806 aIter = pMarkAccess->getAllMarksBegin();
807 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
808 pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
809 CPPUNIT_ASSERT(pFieldmark);
810 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMCHECKBOX), pFieldmark->GetFieldname());
812 // tdf#147008 this would crash
813 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
814 pWrtShell->StartOfSection(false);
815 pWrtShell->SplitNode();
816 CPPUNIT_ASSERT_EQUAL(pFieldmark->GetMarkPos().GetNodeIndex(),
817 pFieldmark->GetOtherMarkPos().GetNodeIndex());
818 CPPUNIT_ASSERT_EQUAL(sal_Int32(pFieldmark->GetMarkPos().GetContentIndex() + 1),
819 pFieldmark->GetOtherMarkPos().GetContentIndex());
822 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDropDownFormFieldInsertion)
824 createSwDoc();
825 SwDoc* pDoc = getSwDoc();
826 CPPUNIT_ASSERT(pDoc);
828 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
829 CPPUNIT_ASSERT(pMarkAccess);
830 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
832 // Insert a drop-down form field
833 dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
834 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
836 // Check whether the fieldmark is created
837 auto aIter = pMarkAccess->getAllMarksBegin();
838 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
839 ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
840 CPPUNIT_ASSERT(pFieldmark);
841 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
842 // Check drop down field's parameters. By default these params are not set
843 const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
844 auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
845 CPPUNIT_ASSERT(bool(pListEntries == pParameters->end()));
846 auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
847 CPPUNIT_ASSERT(bool(pResult == pParameters->end()));
849 // Undo insertion
850 dispatchCommand(mxComponent, ".uno:Undo", {});
851 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
853 // Redo insertion
854 dispatchCommand(mxComponent, ".uno:Redo", {});
855 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
856 aIter = pMarkAccess->getAllMarksBegin();
857 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
858 pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
859 CPPUNIT_ASSERT(pFieldmark);
860 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDROPDOWN), pFieldmark->GetFieldname());
863 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testMixedFormFieldInsertion)
865 createSwDoc();
866 SwDoc* pDoc = getSwDoc();
867 CPPUNIT_ASSERT(pDoc);
869 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
870 CPPUNIT_ASSERT(pMarkAccess);
871 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
873 // Insert fields
874 dispatchCommand(mxComponent, ".uno:TextFormField", {});
875 dispatchCommand(mxComponent, ".uno:CheckBoxFormField", {});
876 dispatchCommand(mxComponent, ".uno:DropDownFormField", {});
877 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
879 // Undo insertion
880 dispatchCommand(mxComponent, ".uno:Undo", {});
881 dispatchCommand(mxComponent, ".uno:Undo", {});
882 dispatchCommand(mxComponent, ".uno:Undo", {});
883 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
885 // Redo insertion
886 dispatchCommand(mxComponent, ".uno:Redo", {});
887 dispatchCommand(mxComponent, ".uno:Redo", {});
888 dispatchCommand(mxComponent, ".uno:Redo", {});
889 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), pMarkAccess->getAllMarksCount());
892 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147723)
894 createSwDoc("tdf147723.docx");
895 SwDoc* const pDoc = getSwDoc();
897 IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
898 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
900 dispatchCommand(mxComponent, ".uno:SelectAll", {});
901 dispatchCommand(mxComponent, ".uno:Copy", {});
903 // Without the fix in place, this test would have crashed here
904 dispatchCommand(mxComponent, ".uno:Paste", {});
905 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
906 dispatchCommand(mxComponent, ".uno:Paste", {});
907 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), rIDMA.getAllMarksCount());
908 dispatchCommand(mxComponent, ".uno:Undo", {});
909 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
910 dispatchCommand(mxComponent, ".uno:Undo", {});
911 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getAllMarksCount());
914 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147006)
916 createSwDoc("tdf147006.rtf");
917 SwDoc* const pDoc = getSwDoc();
919 IDocumentMarkAccess& rIDMA(*pDoc->getIDocumentMarkAccess());
920 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
921 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
922 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
923 CPPUNIT_ASSERT_EQUAL(std::iterator_traits<IDocumentMarkAccess::iterator>::difference_type(1),
924 std::distance(rIDMA.getFieldmarksBegin(), rIDMA.getFieldmarksEnd()));
926 dispatchCommand(mxComponent, ".uno:SelectAll", {});
927 // this crashed
928 dispatchCommand(mxComponent, ".uno:Delete", {});
929 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
930 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
931 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
932 dispatchCommand(mxComponent, ".uno:Undo", {});
933 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
934 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
935 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
936 dispatchCommand(mxComponent, ".uno:Redo", {});
937 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
938 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
939 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
940 dispatchCommand(mxComponent, ".uno:Undo", {});
941 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
942 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
943 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), rIDMA.getAllMarksCount());
944 dispatchCommand(mxComponent, ".uno:Redo", {});
945 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_FRM));
946 CPPUNIT_ASSERT_EQUAL(size_t(0), pDoc->GetFlyCount(FLYCNTTYPE_GRF));
947 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rIDMA.getAllMarksCount());
950 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDocxAttributeTableExport)
952 createSwDoc("floating-table-position.docx");
954 // get the table frame, set new values and dismiss the references
956 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
958 // change the properties
959 // 8133 -> 8000
960 xShape->setPropertyValue("VertOrientPosition", uno::Any(static_cast<sal_Int32>(8000)));
961 // 5964 -> 5000
962 xShape->setPropertyValue("HoriOrientPosition", uno::Any(static_cast<sal_Int32>(5000)));
963 // 0 (frame) -> 8 (page print area)
964 xShape->setPropertyValue("VertOrientRelation", uno::Any(static_cast<sal_Int16>(8)));
965 // 8 (page print area) -> 0 (frame)
966 xShape->setPropertyValue("HoriOrientRelation", uno::Any(static_cast<sal_Int16>(0)));
968 // save it to docx
969 saveAndReload("Office Open XML Text");
971 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
973 // test the new values
974 sal_Int32 nValue = getProperty<sal_Int32>(xShape, "VertOrientPosition");
975 CPPUNIT_ASSERT(sal_Int32(7999) <= nValue);
976 CPPUNIT_ASSERT(nValue <= sal_Int32(8001));
977 nValue = getProperty<sal_Int32>(xShape, "HoriOrientPosition");
978 CPPUNIT_ASSERT(sal_Int32(4999) <= nValue);
979 CPPUNIT_ASSERT(nValue <= sal_Int32(5001));
981 CPPUNIT_ASSERT_EQUAL(sal_Int16(8), getProperty<sal_Int16>(xShape, "VertOrientRelation"));
982 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xShape, "HoriOrientRelation"));
985 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118699_redline_numbering)
987 createSwDoc("tdf118699.docx");
988 SwDoc* pDoc = getSwDoc();
990 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
991 rIDRA.AcceptAllRedline(true);
993 uno::Reference<beans::XPropertySet> xProps(getParagraph(2), uno::UNO_QUERY_THROW);
994 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
995 !xProps->getPropertyValue("NumberingRules").hasValue());
997 CPPUNIT_ASSERT_MESSAGE(
998 "first paragraph after the second deletion: missing numbering",
999 getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(5), "NumberingRules")
1000 .is());
1003 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125881_redline_list_level)
1005 createSwDoc("tdf125881.docx");
1007 uno::Reference<beans::XPropertySet> xProps(getParagraph(8), uno::UNO_QUERY_THROW);
1008 CPPUNIT_ASSERT_MESSAGE("deleted paragraph: erroneous numbering",
1009 !xProps->getPropertyValue("NumberingRules").hasValue());
1011 // deleted paragraph gets the numbering of the next paragraph
1012 uno::Reference<beans::XPropertySet> xProps2(getParagraph(9), uno::UNO_QUERY_THROW);
1013 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: missing numbering",
1014 xProps2->getPropertyValue("NumberingRules").hasValue());
1016 // check numbering level at deletion (1 instead of 0)
1017 CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(getParagraph(9), "NumberingLevel"));
1020 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125916_redline_restart_numbering)
1022 createSwDoc("tdf125916.docx");
1023 SwDoc* pDoc = getSwDoc();
1025 // moveFrom/moveTo are imported as separated redlines from fixing tdf#145718.
1026 // Accept the first inline moveFrom redline before accepting the remaining ones
1027 // to leave a paragraph long deletion to test the fix for tdf#125916.
1028 SwEditShell* const pEditShell(pDoc->GetEditShell());
1029 CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
1030 pEditShell->AcceptRedline(0);
1032 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1033 rIDRA.AcceptAllRedline(true);
1035 // check unnecessary numbering
1036 uno::Reference<beans::XPropertySet> xProps(getParagraph(3), uno::UNO_QUERY_THROW);
1037 CPPUNIT_ASSERT_MESSAGE("first paragraph after the first deletion: erroneous numbering",
1038 !xProps->getPropertyValue("NumberingRules").hasValue());
1041 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310)
1043 createSwDoc("tdf125310.fodt");
1044 SwDoc* pDoc = getSwDoc();
1046 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1047 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
1048 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
1049 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
1050 CPPUNIT_ASSERT_EQUAL(1, getPages());
1052 // turn on red-lining and show changes
1053 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1054 | RedlineFlags::ShowInsert);
1055 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1056 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1057 CPPUNIT_ASSERT_MESSAGE(
1058 "redlines should be visible",
1059 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1061 // paragraph join
1062 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1063 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
1064 pWrtShell->EndPara(/*bSelect=*/true);
1065 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
1066 dispatchCommand(mxComponent, ".uno:Cut", {});
1068 // copied paragraph style
1069 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1070 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
1072 // without copying the page break
1073 CPPUNIT_ASSERT_EQUAL(1, getPages());
1076 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf125310b)
1078 createSwDoc("tdf125310b.fodt");
1079 SwDoc* pDoc = getSwDoc();
1080 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1082 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
1083 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
1084 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1085 getProperty<OUString>(getParagraph(3), "ParaStyleName"));
1086 CPPUNIT_ASSERT_EQUAL(2, getPages());
1088 // turn on red-lining and show changes
1089 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1090 | RedlineFlags::ShowInsert);
1091 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1092 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1094 // remove second paragraph with the page break
1095 pWrtShell->Down(/*bSelect=*/false);
1096 pWrtShell->Down(/*bSelect=*/false);
1097 pWrtShell->Up(/*bSelect=*/true);
1098 pWrtShell->DelLeft();
1100 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1101 rIDRA.AcceptAllRedline(true);
1103 // losing the page break, as without redlining
1104 CPPUNIT_ASSERT_EQUAL(1, getPages());
1107 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120336)
1109 createSwDoc("tdf120336.docx");
1110 SwDoc* pDoc = getSwDoc();
1112 // turn on red-lining and show changes
1113 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1114 | RedlineFlags::ShowInsert);
1115 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1116 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1117 CPPUNIT_ASSERT_MESSAGE(
1118 "redlines should be visible",
1119 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1121 CPPUNIT_ASSERT_EQUAL(2, getPages());
1123 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1124 rIDRA.AcceptAllRedline(true);
1126 // keep page break, as without redlining
1127 CPPUNIT_ASSERT_EQUAL(2, getPages());
1130 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf106843)
1132 createSwDoc("tdf106843.docx");
1133 SwDoc* pDoc = getSwDoc();
1135 // try to turn off red-lining
1136 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1138 // but the protection doesn't allow it
1139 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1140 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1143 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageComment)
1145 // Load a document with an as-char image in it.
1146 createSwDoc("image-comment.odt");
1147 SwDoc* pDoc = getSwDoc();
1148 SwView* pView = pDoc->GetDocShell()->GetView();
1150 // Test document has "before<image>after", remove the content before the image.
1151 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1152 pWrtShell->SttEndDoc(/*bStart=*/true);
1153 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 6, /*bBasicCall=*/false);
1154 pWrtShell->Delete();
1156 // Select the image.
1157 selectShape(1);
1159 // Insert a comment while the image is selected.
1160 pView->GetViewFrame().GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON);
1162 // Verify that the comment is around the image.
1163 // Without the accompanying fix in place, this test would have failed, as FN_POSTIT was disabled
1164 // in the frame shell.
1165 // Then this test would have failed, as in case the as-char anchored image was at the start of
1166 // the paragraph, the comment of the image covered the character after the image, not the image.
1167 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1168 CPPUNIT_ASSERT_EQUAL(OUString("Annotation"),
1169 getProperty<OUString>(getRun(xPara, 1), "TextPortionType"));
1170 CPPUNIT_ASSERT_EQUAL(OUString("Frame"),
1171 getProperty<OUString>(getRun(xPara, 2), "TextPortionType"));
1172 CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"),
1173 getProperty<OUString>(getRun(xPara, 3), "TextPortionType"));
1174 CPPUNIT_ASSERT_EQUAL(OUString("Text"),
1175 getProperty<OUString>(getRun(xPara, 4), "TextPortionType"));
1177 // Insert content to the comment, and select the image again.
1178 SfxStringItem aItem(FN_INSERT_STRING, "x");
1179 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
1180 { &aItem });
1181 selectShape(1);
1183 #if !defined(MACOSX)
1184 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1185 // Calc the left edge of the as-char frame.
1186 SwRootFrame* pLayout = pWrtShell->GetLayout();
1187 SwFrame* pPage = pLayout->GetLower();
1188 SwFrame* pBody = pPage->GetLower();
1189 SwFrame* pTextFrame = pBody->GetLower();
1190 CPPUNIT_ASSERT(pTextFrame->GetDrawObjs());
1191 const SwSortedObjs& rAnchored = *pTextFrame->GetDrawObjs();
1192 CPPUNIT_ASSERT_GREATER(static_cast<size_t>(0), rAnchored.size());
1193 SwAnchoredObject* pObject = rAnchored[0];
1194 tools::Long nFrameLeft = pObject->GetObjRect().Left();
1195 tools::Long nFrameTop = pObject->GetObjRect().Top();
1197 // Make sure that the anchor points to the bottom left corner of the image.
1198 // Without the accompanying fix in place, this test would have failed with:
1199 // - Expected less or equal than: 1418
1200 // - Actual: 2442
1201 // The anchor pointed to the bottom right corner, so as-char and at-char was inconsistent.
1202 Scheduler::ProcessEventsToIdle();
1203 SwPostItMgr* pPostItMgr = pView->GetPostItMgr();
1204 for (const auto& pItem : *pPostItMgr)
1206 const SwRect& rAnchor = pItem->mpPostIt->GetAnchorRect();
1207 CPPUNIT_ASSERT_EQUAL(nFrameLeft, rAnchor.Left());
1210 // Test the comment anchor we expose via the LOK API.
1211 // Without the accompanying fix in place, this test would have failed with:
1212 // - Expected: 1418, 1418, 0, 0
1213 // - Actual : 1418, 1418, 1024, 1024
1214 // I.e. the anchor position had a non-empty size, which meant different rendering via tiled
1215 // rendering and on the desktop.
1216 tools::JsonWriter aJsonWriter;
1217 pTextDoc->getPostIts(aJsonWriter);
1218 OString pChar = aJsonWriter.finishAndGetAsOString();
1219 std::stringstream aStream((std::string(pChar)));
1220 boost::property_tree::ptree aTree;
1221 boost::property_tree::read_json(aStream, aTree);
1222 for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("comments"))
1224 const boost::property_tree::ptree& rComment = rValue.second;
1225 OString aAnchorPos(rComment.get<std::string>("anchorPos"));
1226 OString aExpected
1227 = OString::number(nFrameLeft) + ", " + OString::number(nFrameTop) + ", 0, 0";
1228 CPPUNIT_ASSERT_EQUAL(aExpected, aAnchorPos);
1231 #endif
1233 // Now delete the image.
1234 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1235 // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual:
1236 // 1', i.e. the comment of the image was not deleted when the image was deleted.
1237 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
1238 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1241 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testImageCommentAtChar)
1243 // Load a document with an at-char image in it.
1244 createSwDoc("image-comment-at-char.odt");
1245 SwDoc* pDoc = getSwDoc();
1246 SwView* pView = pDoc->GetDocShell()->GetView();
1248 // Select the image.
1249 selectShape(1);
1251 // Insert a comment while the image is selected.
1252 pView->GetViewFrame().GetDispatcher()->Execute(FN_POSTIT, SfxCallMode::SYNCHRON);
1254 // Verify that the comment is around the image.
1255 // Without the accompanying fix in place, this test would have failed, as the comment was
1256 // anchored at the end of the paragraph, it was not around the image.
1257 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1258 CPPUNIT_ASSERT_EQUAL(OUString("Text"),
1259 getProperty<OUString>(getRun(xPara, 1), "TextPortionType"));
1260 CPPUNIT_ASSERT_EQUAL(OUString("Annotation"),
1261 getProperty<OUString>(getRun(xPara, 2), "TextPortionType"));
1262 CPPUNIT_ASSERT_EQUAL(OUString("Frame"),
1263 getProperty<OUString>(getRun(xPara, 3), "TextPortionType"));
1264 CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"),
1265 getProperty<OUString>(getRun(xPara, 4), "TextPortionType"));
1266 CPPUNIT_ASSERT_EQUAL(OUString("Text"),
1267 getProperty<OUString>(getRun(xPara, 5), "TextPortionType"));
1269 // Insert content to the comment, and select the image again.
1270 SfxStringItem aItem(FN_INSERT_STRING, "x");
1271 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_STRING, SfxCallMode::SYNCHRON,
1272 { &aItem });
1273 selectShape(1);
1274 // Now delete the image.
1275 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1276 // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual:
1277 // 1', i.e. the comment of the image was not deleted when the image was deleted.
1278 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
1279 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1281 // Undo the deletion and move the image down, so the anchor changes.
1282 pView->GetViewFrame().GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
1283 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
1284 pDoc->getIDocumentMarkAccess()->getAnnotationMarksCount());
1285 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1286 Point aNewAnchor = pWrtShell->GetFlyRect().TopLeft();
1287 aNewAnchor.Move(0, 600);
1288 pWrtShell->SetFlyPos(aNewAnchor);
1290 // Get the image anchor doc model position.
1291 SwFlyFrame* pFly = pWrtShell->GetCurrFlyFrame(false);
1292 CPPUNIT_ASSERT(pFly);
1293 SwFrameFormat& rFlyFormat = pFly->GetFrameFormat();
1294 const SwPosition* pImageAnchor = rFlyFormat.GetAnchor().GetContentAnchor();
1295 CPPUNIT_ASSERT(pImageAnchor);
1297 // Get the annotation mark doc model start.
1298 auto it = pDoc->getIDocumentMarkAccess()->getAnnotationMarksBegin();
1299 CPPUNIT_ASSERT(it != pDoc->getIDocumentMarkAccess()->getAnnotationMarksEnd());
1300 const sw::mark::IMark* pMark = *it;
1301 const SwPosition& rAnnotationMarkStart = pMark->GetMarkPos();
1303 // Without the accompanying fix in place, this test would have failed with:
1304 // - Expected: SwPosition (node 14, offset 15)
1305 // - Actual : SwPosition (node 12, offset 3)
1306 // This means moving the image anchor did not move the comment anchor / annotation mark, so the
1307 // image and its comment got out of sync.
1308 CPPUNIT_ASSERT_EQUAL(*pImageAnchor, rAnnotationMarkStart);
1311 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageDeletion)
1313 // load a document with an image anchored to paragraph in it
1314 createSwDoc("image.odt");
1315 SwDoc* pDoc = getSwDoc();
1316 SwView* pView = pDoc->GetDocShell()->GetView();
1318 // select the image
1319 selectShape(1);
1321 // turn on red-lining and show changes
1322 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1324 rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert);
1325 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1326 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1327 CPPUNIT_ASSERT_MESSAGE(
1328 "redlines should be visible",
1329 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1331 // now delete the image with track changes
1332 pView->GetViewFrame().GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
1334 const SwRedlineTable& rTable = rIDRA.GetRedlineTable();
1335 // this was 0 (missing recording of deletion of images)
1336 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
1338 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
1339 // tdf#142701 this was AS_CHARACTER (convert AT_PARA to AT_CHAR to keep the layout)
1340 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
1341 getProperty<text::TextContentAnchorType>(xShape, "AnchorType"));
1344 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTrackImageInsertion)
1346 createSwDoc();
1347 SwDoc* pDoc = getSwDoc();
1349 // turn on red-lining and show changes
1350 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
1352 rIDRA.SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete | RedlineFlags::ShowInsert);
1353 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1354 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1355 CPPUNIT_ASSERT_MESSAGE(
1356 "redlines should be visible",
1357 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1359 // Insert an image with change tracking
1360 uno::Sequence<beans::PropertyValue> aArgs = {
1361 comphelper::makePropertyValue("FileName", createFileURL(u"ole2.png")),
1363 dispatchCommand(mxComponent, ".uno:InsertGraphic", aArgs);
1365 const SwRedlineTable& rTable = rIDRA.GetRedlineTable();
1366 // this was 0 (missing recording of insertion of images)
1367 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size());
1370 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120338)
1372 createSwDoc("tdf120338.docx");
1374 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1375 getProperty<sal_Int32>(getParagraph(2), "ParaAdjust")); // right
1376 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1377 getProperty<sal_Int32>(getParagraph(3), "ParaAdjust")); // right
1378 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1379 getProperty<sal_Int32>(getParagraph(4), "ParaAdjust")); // left
1380 CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
1381 getProperty<sal_Int32>(getParagraph(5), "ParaAdjust")); // right
1383 CPPUNIT_ASSERT_EQUAL(OUString(""),
1384 getProperty<OUString>(getParagraph(7), "NumberingStyleName"));
1386 CPPUNIT_ASSERT_EQUAL(OUString("WWNum2"),
1387 getProperty<OUString>(getParagraph(8), "NumberingStyleName"));
1389 CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"),
1390 getProperty<OUString>(getParagraph(10), "ParaStyleName"));
1391 CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"),
1392 getProperty<OUString>(getParagraph(11), "ParaStyleName"));
1394 // reject tracked paragraph adjustments
1395 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
1397 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1398 getProperty<sal_Int32>(getParagraph(2), "ParaAdjust")); // left
1399 CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
1400 getProperty<sal_Int32>(getParagraph(3), "ParaAdjust")); // center
1401 CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
1402 getProperty<sal_Int32>(getParagraph(4), "ParaAdjust")); // center
1403 CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
1404 getProperty<sal_Int32>(getParagraph(5), "ParaAdjust")); // left
1406 // tdf#126245 revert numbering changes
1407 CPPUNIT_ASSERT_EQUAL(OUString("WWNum2"),
1408 getProperty<OUString>(getParagraph(7), "NumberingStyleName"));
1410 CPPUNIT_ASSERT_EQUAL(OUString(""),
1411 getProperty<OUString>(getParagraph(8), "NumberingStyleName"));
1413 // tdf#126243 revert paragraph styles
1414 CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
1415 getProperty<OUString>(getParagraph(10), "ParaStyleName"));
1416 CPPUNIT_ASSERT_EQUAL(OUString("Heading 3"),
1417 getProperty<OUString>(getParagraph(11), "ParaStyleName"));
1420 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf120338_multiple_paragraph_join)
1422 createSwDoc("redline-para-join.docx");
1424 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1425 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
1426 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1427 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
1428 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1429 getProperty<OUString>(getParagraph(3), "ParaStyleName"));
1431 // reject tracked paragraph styles
1432 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
1434 CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
1435 getProperty<OUString>(getParagraph(1), "ParaStyleName"));
1436 CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"),
1437 getProperty<OUString>(getParagraph(2), "ParaStyleName"));
1438 CPPUNIT_ASSERT_EQUAL(OUString("Heading 3"),
1439 getProperty<OUString>(getParagraph(3), "ParaStyleName"));
1442 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testShapePageMove)
1444 // Load a document with 2 pages, shape on the first page.
1445 createSwDoc("shape-page-move.odt");
1446 SwDoc* pDoc = getSwDoc();
1447 SwView* pView = pDoc->GetDocShell()->GetView();
1448 // Make sure that the 2nd page is below the 1st one.
1449 pView->SetViewLayout(/*nColumns=*/1, /*bBookMode=*/false);
1450 calcLayout();
1452 // Select the shape.
1453 selectShape(1);
1455 // Move the shape down to the 2nd page.
1456 SfxInt32Item aXItem(SID_ATTR_TRANSFORM_POS_X, 4000);
1457 SfxInt32Item aYItem(SID_ATTR_TRANSFORM_POS_Y, 12000);
1458 pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_ATTR_TRANSFORM, SfxCallMode::SYNCHRON,
1459 { &aXItem, &aYItem });
1461 // Check if the shape anchor was moved to the 2nd page as well.
1462 auto pShapeFormats = pDoc->GetSpzFrameFormats();
1463 CPPUNIT_ASSERT(!pShapeFormats->empty());
1464 auto it = pShapeFormats->begin();
1465 auto pShapeFormat = *it;
1466 const SwPosition* pAnchor = pShapeFormat->GetAnchor().GetContentAnchor();
1467 CPPUNIT_ASSERT(pAnchor);
1469 // Find out the node index of the 1st para on the 2nd page.
1470 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1471 SwFrame* pFirstPage = pLayout->Lower();
1472 SwFrame* pSecondPage = pFirstPage->GetNext();
1473 CPPUNIT_ASSERT(pSecondPage->IsLayoutFrame());
1474 SwFrame* pBodyFrame = static_cast<SwLayoutFrame*>(pSecondPage)->GetLower();
1475 CPPUNIT_ASSERT(pBodyFrame->IsLayoutFrame());
1476 SwFrame* pTextFrame = static_cast<SwLayoutFrame*>(pBodyFrame)->GetLower();
1477 CPPUNIT_ASSERT(pTextFrame->IsTextFrame());
1478 SwNodeOffset nNodeIndex = static_cast<SwTextFrame*>(pTextFrame)->GetTextNodeFirst()->GetIndex();
1480 // Without the accompanying fix in place, this test would have failed with "Expected: 13;
1481 // Actual: 12", i.e. the shape was anchored to the last paragraph of the 1st page, not to a
1482 // paragraph on the 2nd page.
1483 CPPUNIT_ASSERT_EQUAL(nNodeIndex, pAnchor->GetNodeIndex());
1486 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldInsertion)
1488 createSwDoc();
1489 SwDoc* pDoc = getSwDoc();
1490 CPPUNIT_ASSERT(pDoc);
1491 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1492 CPPUNIT_ASSERT(pMarkAccess);
1493 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1495 // Insert a date form field
1496 dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
1497 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1499 // Check whether the fieldmark is created
1500 auto aIter = pMarkAccess->getAllMarksBegin();
1501 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1502 ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
1503 CPPUNIT_ASSERT(pFieldmark);
1504 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
1506 // The date form field has the placeholder text in it
1507 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1508 sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
1509 CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), xPara->getString());
1511 // Undo insertion
1512 dispatchCommand(mxComponent, ".uno:Undo", {});
1513 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1515 // Redo insertion
1516 dispatchCommand(mxComponent, ".uno:Redo", {});
1517 aIter = pMarkAccess->getAllMarksBegin();
1518 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1519 pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
1520 CPPUNIT_ASSERT(pFieldmark);
1521 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
1524 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldContentOperations)
1526 createSwDoc();
1527 SwDoc* pDoc = getSwDoc();
1528 CPPUNIT_ASSERT(pDoc);
1529 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1530 CPPUNIT_ASSERT(pMarkAccess);
1531 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1533 // Insert a date form field
1534 dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
1535 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1537 // Check whether the fieldmark is created
1538 auto aIter = pMarkAccess->getAllMarksBegin();
1539 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1540 ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
1541 CPPUNIT_ASSERT(pFieldmark);
1542 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
1544 // Check the default content added by insertion
1545 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1546 sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
1547 CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent());
1549 // Set content to empty string
1550 pFieldmark->ReplaceContent("");
1551 CPPUNIT_ASSERT_EQUAL(OUString(""), pFieldmark->GetContent());
1553 // Replace empty string with a valid content
1554 pFieldmark->ReplaceContent("2019-10-23");
1555 CPPUNIT_ASSERT_EQUAL(OUString("2019-10-23"), pFieldmark->GetContent());
1558 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateHandling)
1560 createSwDoc();
1561 SwDoc* pDoc = getSwDoc();
1562 CPPUNIT_ASSERT(pDoc);
1563 IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
1564 CPPUNIT_ASSERT(pMarkAccess);
1565 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
1567 // Insert a date form field
1568 dispatchCommand(mxComponent, ".uno:DatePickerFormField", {});
1569 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
1571 // Check whether the fieldmark is created
1572 auto aIter = pMarkAccess->getAllMarksBegin();
1573 CPPUNIT_ASSERT(aIter != pMarkAccess->getAllMarksEnd());
1574 ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
1575 CPPUNIT_ASSERT(pFieldmark);
1576 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
1578 // The default content is not a valid date
1579 uno::Reference<text::XTextRange> xPara = getParagraph(1);
1580 sal_Unicode vEnSpaces[5] = { 8194, 8194, 8194, 8194, 8194 };
1581 CPPUNIT_ASSERT_EQUAL(OUString(vEnSpaces, 5), pFieldmark->GetContent());
1582 std::pair<bool, double> aResult = pFieldmark->GetCurrentDate();
1583 CPPUNIT_ASSERT(!aResult.first);
1585 // Check empty string
1586 pFieldmark->ReplaceContent("");
1587 aResult = pFieldmark->GetCurrentDate();
1588 CPPUNIT_ASSERT(!aResult.first);
1590 // Check valid date
1591 // Set date format first
1592 sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldmark->GetParameters();
1593 (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= OUString("YYYY/MM/DD");
1594 (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= OUString("en-US");
1596 // Set date value and check whether the content is formatted correctly
1597 pFieldmark->SetCurrentDate(48000.0);
1598 aResult = pFieldmark->GetCurrentDate();
1599 CPPUNIT_ASSERT(aResult.first);
1600 CPPUNIT_ASSERT_EQUAL(48000.0, aResult.second);
1601 CPPUNIT_ASSERT_EQUAL(OUString("2031/06/01"), pFieldmark->GetContent());
1602 // Current date param contains date in a "standard format"
1603 OUString sCurrentDate;
1604 auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE);
1605 if (pResult != pParameters->end())
1607 pResult->second >>= sCurrentDate;
1609 CPPUNIT_ASSERT_EQUAL(OUString("2031-06-01"), sCurrentDate);
1612 #if !defined(_WIN32)
1613 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testDateFormFieldCurrentDateInvalidation)
1615 createSwDoc();
1616 SwDoc* pDoc = getSwDoc();
1617 CPPUNIT_ASSERT(pDoc);
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, ".uno:DatePickerFormField", {});
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::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
1630 CPPUNIT_ASSERT(pFieldmark);
1631 CPPUNIT_ASSERT_EQUAL(OUString(ODF_FORMDATE), pFieldmark->GetFieldname());
1633 // Set a date first
1634 sw::mark::IFieldmark::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(OUString("2031-06-01"), sCurrentDate);
1656 // Now change the content of the field
1657 pFieldmark->ReplaceContent("[select date]");
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(OUString(""), 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 SwDoc* pDoc = getSwDoc();
1681 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1683 selectShape(1);
1685 // Start editing the OLE object.
1686 pWrtShell->LaunchOLEObj();
1688 // Save the document without existing the OLE edit.
1689 uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
1690 xStorable->storeToURL(maTempFile.GetURL(), {});
1692 uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
1693 = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory),
1694 maTempFile.GetURL());
1695 // Without the accompanying fix in place, this test would have failed: the OLE object lost its
1696 // replacement on save if the edit was active while saving.
1697 CPPUNIT_ASSERT(xNameAccess->hasByName("ObjectReplacements/Object 1"));
1699 // Dispose the document while LOK is still active to avoid leaks.
1700 mxComponent->dispose();
1701 mxComponent.clear();
1702 comphelper::LibreOfficeKit::setActive(false);
1705 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf105330)
1707 createSwDoc("tdf105330.odt");
1708 SwDoc* pDoc = getSwDoc();
1710 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
1711 pWrtShell->Down(/*bSelect=*/false);
1712 SwView* pView = pDoc->GetDocShell()->GetView();
1713 SfxUInt16Item aRows(SID_ATTR_TABLE_ROW, 1);
1714 SfxUInt16Item aColumns(SID_ATTR_TABLE_COLUMN, 1);
1715 pView->GetViewFrame().GetDispatcher()->ExecuteList(FN_INSERT_TABLE, SfxCallMode::SYNCHRON,
1716 { &aRows, &aColumns });
1718 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
1719 rUndoManager.Undo();
1721 // Without the accompanying fix in place, height was only 1 twips (practically invisible).
1722 // Require at least 12pt height (font size under the cursor), in twips.
1723 CPPUNIT_ASSERT_GREATEREQUAL(
1724 static_cast<tools::Long>(240),
1725 pWrtShell->GetVisibleCursor()->GetTextCursor().GetSize().getHeight());
1728 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf118311)
1730 createSwDoc("tdf118311.fodt");
1732 // Jump to the first cell, selecting its content
1733 uno::Sequence<beans::PropertyValue> aSearch(comphelper::InitPropertySequence({
1734 { "SearchItem.SearchString", uno::Any(OUString("a")) },
1735 { "SearchItem.Backward", uno::Any(false) },
1736 }));
1737 dispatchCommand(mxComponent, ".uno:ExecuteSearch", aSearch);
1739 // .uno:Cut doesn't remove the table, only the selected content of the first cell
1740 dispatchCommand(mxComponent, ".uno:Cut", {});
1742 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1743 assertXPath(pXmlDoc, "//page[1]//body/tab");
1745 // .uno:SelectAll selects the whole table, and UNO command Cut cuts it
1746 dispatchCommand(mxComponent, ".uno:SelectAll", {});
1747 dispatchCommand(mxComponent, ".uno:Cut", {});
1749 discardDumpedLayout();
1750 pXmlDoc = parseLayoutDump();
1751 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1754 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletion)
1756 // load a 1-row table, and delete the row with enabled change tracking:
1757 // now the row is not deleted silently, but keeps the deleted cell contents,
1758 // and only accepting all of them will result the deletion of the table row.
1759 createSwDoc("tdf118311.fodt");
1760 SwDoc* pDoc = getSwDoc();
1762 // turn on red-lining and show changes
1763 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1764 | RedlineFlags::ShowInsert);
1765 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1766 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1767 CPPUNIT_ASSERT_MESSAGE(
1768 "redlines should be visible",
1769 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1771 // check table
1772 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1773 assertXPath(pXmlDoc, "//page[1]//body/tab");
1775 // delete table row with enabled change tracking
1776 // (HasTextChangesOnly property of the row will be false)
1777 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
1779 // This was deleted without change tracking
1780 discardDumpedLayout();
1781 pXmlDoc = parseLayoutDump();
1782 assertXPath(pXmlDoc, "//page[1]//body/tab");
1784 // accept the deletion of the content of the first cell
1785 SwEditShell* const pEditShell(pDoc->GetEditShell());
1786 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
1787 pEditShell->AcceptRedline(0);
1789 // table row was still not deleted
1790 discardDumpedLayout();
1791 pXmlDoc = parseLayoutDump();
1792 assertXPath(pXmlDoc, "//page[1]//body/tab");
1794 // accept last redline
1795 pEditShell->AcceptRedline(0);
1797 // table row (and the 1-row table) was deleted finally
1798 discardDumpedLayout();
1799 pXmlDoc = parseLayoutDump();
1800 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1802 // Undo, and repeat the previous test, but only with deletion of the text content of the cells
1803 // (HasTextChangesOnly property will be removed by Undo)
1805 dispatchCommand(mxComponent, ".uno:Undo", {});
1806 dispatchCommand(mxComponent, ".uno:Undo", {});
1807 dispatchCommand(mxComponent, ".uno:Undo", {});
1809 // table exists again
1810 discardDumpedLayout();
1811 pXmlDoc = parseLayoutDump();
1812 assertXPath(pXmlDoc, "//page[1]//body/tab");
1814 // delete table row with enabled change tracking
1815 dispatchCommand(mxComponent, ".uno:SelectRow", {});
1816 dispatchCommand(mxComponent, ".uno:Delete", {});
1818 // Table row still exists
1819 discardDumpedLayout();
1820 pXmlDoc = parseLayoutDump();
1821 assertXPath(pXmlDoc, "//page[1]//body/tab");
1823 // accept the deletion of the content of the first cell
1824 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
1825 pEditShell->AcceptRedline(0);
1827 // table row was still not deleted
1828 discardDumpedLayout();
1829 pXmlDoc = parseLayoutDump();
1830 assertXPath(pXmlDoc, "//page[1]//body/tab");
1832 // accept last redline
1833 pEditShell->AcceptRedline(0);
1835 // table row (and the 1-row table) still exists
1836 // (HasTextChangesOnly property wasn't set for table row deletion)
1837 discardDumpedLayout();
1838 pXmlDoc = parseLayoutDump();
1839 assertXPath(pXmlDoc, "//page[1]//body/tab");
1841 // Undo, and delete the row without change tracking
1843 dispatchCommand(mxComponent, ".uno:Undo", {});
1844 dispatchCommand(mxComponent, ".uno:Undo", {});
1845 dispatchCommand(mxComponent, ".uno:Undo", {});
1847 // table exists again
1848 discardDumpedLayout();
1849 pXmlDoc = parseLayoutDump();
1850 assertXPath(pXmlDoc, "//page[1]//body/tab");
1852 // disable change tracking
1853 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
1854 | RedlineFlags::ShowInsert);
1856 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1857 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1859 // delete table row without change tracking
1860 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
1862 // the table (row) was deleted
1863 discardDumpedLayout();
1864 pXmlDoc = parseLayoutDump();
1865 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1868 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150976)
1870 // load a 1-row table, and delete the row with track changes
1871 createSwDoc("select-row.fodt");
1872 SwDoc* pDoc = getSwDoc();
1874 // turn on red-lining and show changes
1875 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
1876 | RedlineFlags::ShowInsert);
1877 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1878 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1879 CPPUNIT_ASSERT_MESSAGE(
1880 "redlines should be visible",
1881 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1883 // check table
1884 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1885 assertXPath(pXmlDoc, "//page[1]//body/tab");
1886 // nested table in the last cell
1887 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1889 // delete table row with enabled change tracking
1890 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
1892 discardDumpedLayout();
1893 pXmlDoc = parseLayoutDump();
1894 assertXPath(pXmlDoc, "//page[1]//body/tab");
1896 // deleted text content
1897 SwEditShell* const pEditShell(pDoc->GetEditShell());
1898 // This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
1899 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
1901 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1902 SwFrame* pPage = pLayout->Lower();
1903 SwFrame* pBody = pPage->GetLower();
1904 SwFrame* pTable = pBody->GetLower();
1905 CPPUNIT_ASSERT(pTable->IsTabFrame());
1907 SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
1909 // This was false (not deleted row)
1910 CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
1912 // accept all tracked changes
1913 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
1915 discardDumpedLayout();
1916 pXmlDoc = parseLayoutDump();
1918 // tdf#151658 This was 1: not deleted table row (and table)
1919 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1922 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf151657)
1924 // load a 1-row table, and delete the row with hidden track changes
1925 createSwDoc("select-row.fodt");
1926 SwDoc* pDoc = getSwDoc();
1928 // turn on red-lining and hide changes
1929 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
1930 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1931 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1932 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
1933 !IDocumentRedlineAccess::IsShowChanges(
1934 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
1936 // check table
1937 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1938 assertXPath(pXmlDoc, "//page[1]//body/tab");
1939 // nested table in the last cell
1940 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1942 // delete table row with enabled change tracking
1943 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
1945 discardDumpedLayout();
1946 pXmlDoc = parseLayoutDump();
1947 assertXPath(pXmlDoc, "//page[1]//body/tab");
1949 // deleted text content
1950 SwEditShell* const pEditShell(pDoc->GetEditShell());
1951 // This was 1 before fixing tdf#151478 (testSelectRowWithNestedTable)
1952 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
1954 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
1955 SwFrame* pPage = pLayout->Lower();
1956 SwFrame* pBody = pPage->GetLower();
1957 SwFrame* pTable = pBody->GetLower();
1958 CPPUNIT_ASSERT(pTable->IsTabFrame());
1960 SwTabFrame* pTabFrame = static_cast<SwTabFrame*>(pTable);
1962 // This was false (not deleted row)
1963 CPPUNIT_ASSERT(pTabFrame->GetTable()->HasDeletedRowOrCell());
1965 // accept all tracked changes
1966 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
1968 discardDumpedLayout();
1969 pXmlDoc = parseLayoutDump();
1971 // tdf#151658 This was 1: not deleted table row (and table)
1972 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
1975 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testSelectRowWithNestedTable)
1977 // load a 1-row table, and select the row
1978 createSwDoc("select-row.fodt");
1980 // check table
1981 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1982 assertXPath(pXmlDoc, "//page[1]//body/tab");
1983 // nested table in the last cell
1984 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab");
1986 // select table row
1987 dispatchCommand(mxComponent, ".uno:EntireRow", {});
1988 // convert selected text content to uppercase
1989 dispatchCommand(mxComponent, ".uno:ChangeCaseToUpper", {});
1991 discardDumpedLayout();
1992 pXmlDoc = parseLayoutDump();
1993 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[1]/txt", "NESTED-A1");
1994 // This was "a1" (bad selection of the table row)
1995 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[1]/txt[1]", "A1");
1996 // This was "nested-b1" (bad selection of the table row)
1997 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row/cell[2]/tab/row/cell[2]/txt", "NESTED-B1");
2000 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_row)
2002 // load a 2-row table, and select row 2 by clicking before it
2003 createSwDoc("select-column.fodt");
2004 SwDoc* pDoc = getSwDoc();
2005 CPPUNIT_ASSERT(pDoc);
2006 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2007 CPPUNIT_ASSERT(pWrtShell);
2009 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
2010 SwFrame* pPage = pLayout->Lower();
2011 SwFrame* pBody = pPage->GetLower();
2012 SwFrame* pTable = pBody->GetLower()->GetNext();
2013 SwFrame* pRow2 = pTable->GetLower()->GetNext();
2014 const SwRect& rRow2Rect = pRow2->getFrameArea();
2015 Point ptRow(rRow2Rect.Left(), rRow2Rect.Top() + rRow2Rect.Height() / 2);
2017 pWrtShell->SelectTableRowCol(ptRow);
2019 // convert selected text content to uppercase
2020 dispatchCommand(mxComponent, ".uno:ChangeCaseToUpper", {});
2022 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2023 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", "a1");
2024 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", "b1");
2025 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
2026 "NESTED-A1");
2027 // This was "a2" (bad selection of the table row)
2028 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", "A2");
2029 // This was "nested-b1" (bad selection of the table row)
2030 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
2031 "NESTED-B1");
2034 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf47979_column)
2036 // load a 2-row table, and select column B by clicking before them
2037 createSwDoc("select-column.fodt");
2038 SwDoc* pDoc = getSwDoc();
2039 CPPUNIT_ASSERT(pDoc);
2040 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2041 CPPUNIT_ASSERT(pWrtShell);
2043 // select table column by using the middle point of the top border of column B
2044 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
2045 SwFrame* pPage = pLayout->Lower();
2046 SwFrame* pBody = pPage->GetLower();
2047 SwFrame* pTable = pBody->GetLower()->GetNext();
2048 SwFrame* pRow1 = pTable->GetLower();
2049 SwFrame* pCellB1 = pRow1->GetLower()->GetNext();
2050 const SwRect& rCellB1Rect = pCellB1->getFrameArea();
2051 Point ptColumn(rCellB1Rect.Left() + rCellB1Rect.Width() / 2, rCellB1Rect.Top() - 5);
2053 pWrtShell->SelectTableRowCol(ptColumn);
2055 // convert selected text content to uppercase
2056 dispatchCommand(mxComponent, ".uno:ChangeCaseToUpper", {});
2058 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2060 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[1]/txt[1]", "a1");
2061 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[1]/txt[1]", "a2");
2062 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[1]/txt",
2063 "NESTED-A1");
2064 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[2]/cell[2]/tab/row/cell[2]/txt",
2065 "NESTED-B1");
2066 // This was "b1" (bad selection of the table column)
2067 assertXPathContent(pXmlDoc, "//page[1]//body/tab/row[1]/cell[2]/txt[1]", "B1");
2070 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithExport)
2072 // load a 1-row table, and delete the row with enabled change tracking:
2073 // now the row is not deleted silently, but keeps the deleted cell contents,
2074 // and only accepting all of them will result the deletion of the table row.
2075 createSwDoc("tdf118311.fodt");
2076 SwDoc* pDoc = getSwDoc();
2078 // turn on red-lining and show changes
2079 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2080 | RedlineFlags::ShowInsert);
2081 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2082 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2083 CPPUNIT_ASSERT_MESSAGE(
2084 "redlines should be visible",
2085 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2087 // check table
2088 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2089 assertXPath(pXmlDoc, "//page[1]//body/tab");
2091 // delete table row with enabled change tracking
2092 // (HasTextChangesOnly property of the row will be false)
2093 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
2095 // Deleted text content with change tracking,
2096 // but not table deletion
2097 discardDumpedLayout();
2098 pXmlDoc = parseLayoutDump();
2099 assertXPath(pXmlDoc, "//page[1]//body/tab");
2101 // Save it and load it back.
2102 saveAndReload("writer8");
2103 pDoc = getSwDoc();
2105 // accept the deletion of the content of the first cell
2106 SwEditShell* const pEditShell(pDoc->GetEditShell());
2107 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
2108 pEditShell->AcceptRedline(0);
2110 // table row was still not deleted
2111 pXmlDoc = parseLayoutDump();
2112 assertXPath(pXmlDoc, "//page[1]//body/tab");
2114 // accept last redline
2115 pEditShell->AcceptRedline(0);
2117 // table row (and the 1-row table) was deleted finally
2118 // (working export/import of HasTextChangesOnly)
2119 discardDumpedLayout();
2120 pXmlDoc = parseLayoutDump();
2121 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
2124 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithDOCXExport)
2126 // load a 1-row table, and delete the row with enabled change tracking:
2127 // now the row is not deleted silently, but keeps the deleted cell contents,
2128 // and only accepting all of them will result the deletion of the table row.
2129 createSwDoc("tdf118311.fodt");
2130 SwDoc* pDoc = getSwDoc();
2132 // turn on red-lining and show changes
2133 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2134 | RedlineFlags::ShowInsert);
2135 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2136 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2137 CPPUNIT_ASSERT_MESSAGE(
2138 "redlines should be visible",
2139 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2141 // check table
2142 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2143 assertXPath(pXmlDoc, "//page[1]//body/tab");
2145 // delete table row with enabled change tracking
2146 // (HasTextChangesOnly property of the row will be false)
2147 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
2149 // Deleted text content with change tracking,
2150 // but not table deletion
2151 discardDumpedLayout();
2152 pXmlDoc = parseLayoutDump();
2153 assertXPath(pXmlDoc, "//page[1]//body/tab");
2155 // Save it to a DOCX and load it back.
2156 // Exporting change tracking of the row wasn't supported.
2157 // Also Manage Changes for the import.
2158 saveAndReload("Office Open XML Text");
2159 pDoc = getSwDoc();
2161 // accept the deletion of the content of the first cell
2162 SwEditShell* const pEditShell(pDoc->GetEditShell());
2163 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
2164 pEditShell->AcceptRedline(0);
2166 // table row was still not deleted
2167 pXmlDoc = parseLayoutDump();
2168 assertXPath(pXmlDoc, "//page[1]//body/tab");
2170 // accept last redline
2171 pEditShell->AcceptRedline(0);
2173 // table row (and the 1-row table) was deleted finally
2174 // (working export/import of HasTextChangesOnly)
2175 discardDumpedLayout();
2176 pXmlDoc = parseLayoutDump();
2177 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
2180 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableInsertion)
2182 // load a 3-row table inserted with change tracking by text to table conversion
2183 createSwDoc("TC-table-converttotable.docx");
2184 SwDoc* pDoc = getSwDoc();
2186 // check table count (1)
2187 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2188 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2189 uno::UNO_QUERY);
2190 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2192 // reject the text insertions of the table cells (also reject deletion of the tabulated
2193 // text source of the table, which was used by the tracked text to table conversion)
2194 SwEditShell* const pEditShell(pDoc->GetEditShell());
2195 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(10), pEditShell->GetRedlineCount());
2196 while (pEditShell->GetRedlineCount())
2197 pEditShell->RejectRedline(0);
2199 // rejecting all text insertions must undo the table insertion
2200 // This was 1 (remaining empty table after rejecting all table text insertions)
2201 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2204 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineDOCXTableMoveToFrame)
2206 // load a table with tracked drag & drop: Table1 is the moveFrom,
2207 // Table2 is the moveTo - and framed - table
2208 createSwDoc("TC-table-DnD-move.docx");
2209 SwDoc* pDoc = getSwDoc();
2211 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2212 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2213 uno::UNO_QUERY);
2214 uno::Reference<container::XNameAccess> xTableNames = xTextTablesSupplier->getTextTables();
2215 // check table count (2)
2216 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
2218 // accept tracked table moving, remaining table is Table2
2219 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2220 rIDRA.AcceptAllRedline(true);
2221 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2222 CPPUNIT_ASSERT(xTableNames->hasByName("Table2"));
2223 CPPUNIT_ASSERT(!xTableNames->hasByName("Table1"));
2225 // Undo and reject tracked table moving, remaining table is Table1
2226 dispatchCommand(mxComponent, ".uno:Undo", {});
2227 rIDRA.AcceptAllRedline(false);
2228 // This was 2 (not deleted Table2 – framed)
2229 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2230 CPPUNIT_ASSERT(xTableNames->hasByName("Table1"));
2231 CPPUNIT_ASSERT(!xTableNames->hasByName("Table2"));
2234 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143215)
2236 // load a table with tracked insertion of an empty row
2237 createSwDoc("TC-table-rowadd.docx");
2238 SwDoc* pDoc = getSwDoc();
2240 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2241 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2242 uno::UNO_QUERY);
2243 // check table count
2244 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2246 // check table row count
2247 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2248 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2250 // reject insertion of the empty table row
2251 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2252 rIDRA.AcceptAllRedline(false);
2253 // This was 4 (remained empty row)
2254 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2256 // Undo and accept insertion of the table row
2257 dispatchCommand(mxComponent, ".uno:Undo", {});
2258 rIDRA.AcceptAllRedline(true);
2259 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2261 // delete it with change tracking, and accept the deletion
2262 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
2263 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2264 rIDRA.AcceptAllRedline(true);
2265 // This was 4 (remained empty row)
2266 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2269 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666)
2271 // load a table with tracked insertion of an empty row
2272 createSwDoc("TC-table-rowadd.docx");
2273 SwDoc* pDoc = getSwDoc();
2275 // check table count
2276 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2277 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2278 uno::UNO_QUERY);
2279 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2281 // check table row count
2282 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2283 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2285 // select the second row (tracked table row insertion)
2286 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2287 pWrtShell->Down(/*bSelect=*/false);
2289 // delete it, and accept all tracked changes
2290 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
2291 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
2293 // This was 4 (it was not possible to delete only the tracked row insertions)
2294 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2296 // insert a new table row with track changes
2297 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
2298 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2300 // select and delete it
2301 pWrtShell->Down(/*bSelect=*/false);
2302 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
2303 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
2305 // This was 4 (it was not possible to delete own tracked row insertions)
2306 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2309 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150666_regression)
2311 // load a table with tracked insertion of an empty row
2312 createSwDoc("TC-table-rowadd.docx");
2313 SwDoc* pDoc = getSwDoc();
2315 // check table count
2316 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2317 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2318 uno::UNO_QUERY);
2319 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2321 // check table row count
2322 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2323 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
2325 // select the second row (tracked table row insertion)
2326 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2327 pWrtShell->Down(/*bSelect=*/false);
2329 // insert a new table row with track changes
2330 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
2331 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable->getRows()->getCount());
2333 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
2335 // This was 4 (the inserted table row wasn't tracked)
2336 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable->getRows()->getCount());
2339 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf144748)
2341 // load a table with an empty row, and an empty line before the table
2342 // (to allow the easy selection of the full text with the table)
2343 createSwDoc("tdf144748.fodt");
2344 SwDoc* pDoc = getSwDoc();
2346 // turn on red-lining and show changes
2347 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2348 | RedlineFlags::ShowInsert);
2349 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2350 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2351 CPPUNIT_ASSERT_MESSAGE(
2352 "redlines should be visible",
2353 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2355 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2356 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2357 uno::UNO_QUERY);
2358 // there is a table in the text
2359 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2361 // delete full text with the table and check Undo
2363 dispatchCommand(mxComponent, ".uno:SelectAll", {});
2364 dispatchCommand(mxComponent, ".uno:Delete", {});
2365 // this crashed LibreOffice
2366 dispatchCommand(mxComponent, ".uno:Undo", {});
2368 // redo and check redline usage
2370 dispatchCommand(mxComponent, ".uno:Redo", {});
2371 SwEditShell* const pEditShell(pDoc->GetEditShell());
2372 // This was 2 (bad extra redline for the empty row of the deleted table)
2373 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2375 // accept deletion of the text, including the table with the empty row
2377 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2378 rIDRA.AcceptAllRedline(true);
2380 // no table left in the text
2381 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2384 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180)
2386 // load a tracked table insertion (single redline)
2387 createSwDoc("tdf147180.fodt");
2388 SwDoc* pDoc = getSwDoc();
2390 // turn on red-lining and show changes
2391 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2392 | RedlineFlags::ShowInsert);
2393 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2394 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2395 CPPUNIT_ASSERT_MESSAGE(
2396 "redlines should be visible",
2397 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2399 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2400 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2401 uno::UNO_QUERY);
2402 // there is a table in the text
2403 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2405 // insert a character in the first cell with change tracking
2406 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2407 pWrtShell->Insert("x");
2409 // reject all the changes, including table insertion
2411 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2412 rIDRA.AcceptAllRedline(/*bAccept=*/false);
2414 // no table left in the text
2416 // This was 1 (lost tracking of the table after modifying its text content)
2417 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2420 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf147180_empty_rows)
2422 // load a tracked table insertion (single redline) with empty rows
2423 createSwDoc("tdf150824.fodt");
2424 SwDoc* pDoc = getSwDoc();
2426 // turn on red-lining and show changes
2427 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2428 | RedlineFlags::ShowInsert);
2429 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2430 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2431 CPPUNIT_ASSERT_MESSAGE(
2432 "redlines should be visible",
2433 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2435 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2436 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2437 uno::UNO_QUERY);
2438 // there is a table in the text
2439 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2441 // insert a character in the first cell with change tracking
2442 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2443 pWrtShell->Insert("x");
2445 // reject all the changes, including table insertion
2447 IDocumentRedlineAccess& rIDRA(pDoc->getIDocumentRedlineAccess());
2448 rIDRA.AcceptAllRedline(/*bAccept=*/false);
2450 // no table left in the text
2452 // This was 1 (lost tracking of the empty rows after modifying table text content)
2453 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xTables->getCount());
2456 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletion)
2458 // load a table, and delete the first column with enabled change tracking:
2459 // now the column is not deleted silently, but keeps the deleted cell content,
2460 // and only accepting it will result the deletion of the table column.
2461 createSwDoc("tdf118311.fodt");
2462 SwDoc* pDoc = getSwDoc();
2464 // turn on red-lining and show changes
2465 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2466 | RedlineFlags::ShowInsert);
2467 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2468 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2469 CPPUNIT_ASSERT_MESSAGE(
2470 "redlines should be visible",
2471 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2473 // check table
2474 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2475 assertXPath(pXmlDoc, "//page[1]//body/tab");
2476 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2478 // delete table column with enabled change tracking
2479 // (HasTextChangesOnly property of the cell will be false)
2480 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2482 discardDumpedLayout();
2483 pXmlDoc = parseLayoutDump();
2484 assertXPath(pXmlDoc, "//page[1]//body/tab");
2485 // This was 1 (deleted cell without change tracking)
2486 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2488 // accept the deletion
2489 SwEditShell* const pEditShell(pDoc->GetEditShell());
2490 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2491 pEditShell->AcceptRedline(0);
2493 discardDumpedLayout();
2494 pXmlDoc = parseLayoutDump();
2495 assertXPath(pXmlDoc, "//page[1]//body/tab");
2496 // deleted column
2497 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2499 // Undo, and repeat the previous test, but only with deletion of the text content of the cells
2500 // (HasTextChangesOnly property will be removed by Undo)
2502 dispatchCommand(mxComponent, ".uno:Undo", {});
2503 dispatchCommand(mxComponent, ".uno:Undo", {});
2505 // first column exists again
2506 discardDumpedLayout();
2507 pXmlDoc = parseLayoutDump();
2508 assertXPath(pXmlDoc, "//page[1]//body/tab");
2509 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2511 // delete table column with enabled change tracking
2512 dispatchCommand(mxComponent, ".uno:SelectColumn", {});
2513 dispatchCommand(mxComponent, ".uno:Delete", {});
2515 // Table column still exists
2516 discardDumpedLayout();
2517 pXmlDoc = parseLayoutDump();
2518 assertXPath(pXmlDoc, "//page[1]//body/tab");
2519 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2521 // accept the deletion of the content of the first cell
2522 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2523 pEditShell->AcceptRedline(0);
2525 // table column was still not deleted
2526 discardDumpedLayout();
2527 pXmlDoc = parseLayoutDump();
2528 assertXPath(pXmlDoc, "//page[1]//body/tab");
2529 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2531 // Undo, and delete the column without change tracking
2533 dispatchCommand(mxComponent, ".uno:Undo", {});
2534 dispatchCommand(mxComponent, ".uno:Undo", {});
2536 // table exists again
2537 discardDumpedLayout();
2538 pXmlDoc = parseLayoutDump();
2539 assertXPath(pXmlDoc, "//page[1]//body/tab");
2540 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2542 // disable change tracking
2543 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2544 | RedlineFlags::ShowInsert);
2546 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2547 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2549 // delete table column without change tracking
2550 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2552 // the table column was deleted
2553 discardDumpedLayout();
2554 pXmlDoc = parseLayoutDump();
2555 assertXPath(pXmlDoc, "//page[1]//body/tab");
2556 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2559 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156474)
2561 // load a table, and insert a column with change tracking
2562 createSwDoc("tdf118311.fodt");
2563 SwDoc* pDoc = getSwDoc();
2565 // turn on red-lining and show changes
2566 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2567 | RedlineFlags::ShowInsert);
2568 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2569 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2570 CPPUNIT_ASSERT_MESSAGE(
2571 "redlines should be visible",
2572 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2574 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
2575 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
2576 uno::UNO_QUERY);
2578 // there is a table in the text with two columns
2579 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
2580 uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
2581 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
2583 // insert table column with enabled change tracking
2584 // (HasTextChangesOnly property of the cell will be false)
2585 dispatchCommand(mxComponent, ".uno:InsertColumnsBefore", {});
2587 // 3 columns
2588 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2590 // accept tracked changes: remove HasTextChangesOnly = false of the inserted cells
2591 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
2593 // still 3 columns
2594 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2596 // delete the text content (dummy character of the previous text change) of the newly
2597 // inserted cell, and accept tracked changes
2598 SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2599 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2600 dispatchCommand(mxComponent, ".uno:SwBackspace", {});
2601 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
2603 // This was 2 columns (not removed HasTextChangesOnly = false resulted column deletion
2604 // instead of deleting only content of the cell)
2605 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTextTable->getColumns()->getCount());
2608 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, tdf156475)
2610 // load a table, and insert a row without change tracking,
2611 // and delete the first column with the empty cell in the second row with change tracking
2612 createSwDoc("tdf118311.fodt");
2613 SwDoc* pDoc = getSwDoc();
2615 // turn off red-lining and show changes
2616 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2617 | RedlineFlags::ShowInsert);
2618 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2619 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2621 CPPUNIT_ASSERT_MESSAGE(
2622 "redlines should be visible",
2623 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2625 // insert table row
2626 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
2628 // check table
2629 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2630 assertXPath(pXmlDoc, "//page[1]//body/tab");
2631 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
2632 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 2);
2633 assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 2);
2635 // turn on red-lining
2636 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2637 | RedlineFlags::ShowInsert);
2638 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2639 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2641 // delete table column with enabled change tracking
2642 // (HasTextChangesOnly property of the cell will be false)
2643 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2645 // go down to the empty cell
2646 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2647 pWrtShell->Down(/*bSelect=*/false);
2649 // Without the fix in place, this couldn't work
2650 dispatchCommand(mxComponent, ".uno:AcceptTrackedChange", {});
2652 discardDumpedLayout();
2653 pXmlDoc = parseLayoutDump();
2654 assertXPath(pXmlDoc, "//page[1]//body/tab");
2655 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 2);
2656 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 1);
2657 assertXPath(pXmlDoc, "//page[1]//body/tab/row[2]/cell", 1);
2659 // test Undo/Redo
2660 for (sal_Int32 i = 0; i < 4; ++i)
2662 dispatchCommand(mxComponent, ".uno:Undo", {});
2665 for (sal_Int32 i = 0; i < 4; ++i)
2667 dispatchCommand(mxComponent, ".uno:Redo", {});
2671 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155747)
2673 // load a table, and delete the first column with enabled change tracking:
2674 // now the column is not deleted silently, but keeps the deleted cell content,
2675 // and only accepting it will result the deletion of the table column.
2676 createSwDoc("tdf118311.fodt");
2677 SwDoc* pDoc = getSwDoc();
2679 // turn on red-lining and show changes
2680 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2681 | RedlineFlags::ShowInsert);
2682 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2683 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2684 CPPUNIT_ASSERT_MESSAGE(
2685 "redlines should be visible",
2686 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2688 // delete table column with enabled change tracking
2689 // (HasTextChangesOnly property of the cell will be false)
2690 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2692 // select table
2693 dispatchCommand(mxComponent, ".uno:SelectTable", {});
2695 // Without the fix in place, this test would have crashed here
2696 dispatchCommand(mxComponent, ".uno:AcceptTrackedChange", {});
2698 // check removed column
2699 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2700 assertXPath(pXmlDoc, "//page[1]//body/tab");
2701 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2704 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156544)
2706 // load a table, and insert a column without change tracking,
2707 // and delete the first column with the empty cell in the second row with change tracking
2708 createSwDoc("tdf118311.fodt");
2709 SwDoc* pDoc = getSwDoc();
2711 // turn off red-lining and show changes
2712 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowDelete
2713 | RedlineFlags::ShowInsert);
2714 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
2715 !pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2717 CPPUNIT_ASSERT_MESSAGE(
2718 "redlines should be visible",
2719 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2721 // insert table column without change tracking
2722 // (HasTextChangesOnly property of the cell will be false)
2723 dispatchCommand(mxComponent, ".uno:InsertColumnsBefore", {});
2725 // check table
2726 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2727 assertXPath(pXmlDoc, "//page[1]//body/tab");
2728 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2729 assertXPath(pXmlDoc, "//page[1]//body/tab/row[1]/cell", 3);
2731 // turn on red-lining
2732 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2733 | RedlineFlags::ShowInsert);
2734 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2735 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2737 // go to the empty column
2738 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
2739 pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2741 // delete table column with enabled change tracking
2742 // (HasTextChangesOnly property of the cell will be false)
2743 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2745 discardDumpedLayout();
2746 pXmlDoc = parseLayoutDump();
2747 assertXPath(pXmlDoc, "//page[1]//body/tab");
2748 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2750 // This was 2 (deleted column)
2751 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
2753 // accept the deletion of the empty column
2754 dispatchCommand(mxComponent, ".uno:AcceptTrackedChange", {});
2756 discardDumpedLayout();
2757 pXmlDoc = parseLayoutDump();
2758 assertXPath(pXmlDoc, "//page[1]//body/tab");
2759 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2760 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2762 // test Undo/Redo
2763 dispatchCommand(mxComponent, ".uno:Undo", {});
2765 discardDumpedLayout();
2766 pXmlDoc = parseLayoutDump();
2767 assertXPath(pXmlDoc, "//page[1]//body/tab");
2768 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2769 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
2771 dispatchCommand(mxComponent, ".uno:Redo", {});
2773 discardDumpedLayout();
2774 pXmlDoc = parseLayoutDump();
2775 assertXPath(pXmlDoc, "//page[1]//body/tab");
2776 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
2777 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2780 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf156487)
2782 // load a table, and delete a column in Hide Changes mode
2783 createSwDoc("tdf118311.fodt");
2784 SwDoc* pDoc = getSwDoc();
2786 // turn on red-lining and hide changes
2787 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
2788 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2789 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2791 CPPUNIT_ASSERT_MESSAGE("redlines shouldn't be visible",
2792 !IDocumentRedlineAccess::IsShowChanges(
2793 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2795 // delete table column with enabled change tracking
2796 // (HasTextChangesOnly property of the cell will be false)
2797 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2799 // Dump the rendering of the first page as an XML file.
2800 SwDocShell* pShell = pDoc->GetDocShell();
2801 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2802 MetafileXmlDump dumper;
2803 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2804 CPPUNIT_ASSERT(pXmlDoc);
2806 // This would be 2 without hiding the first cell
2807 assertXPath(pXmlDoc, "/metafile/push/push/push/textarray/text", 1);
2810 #ifndef DBG_UTIL
2811 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf149498)
2813 // load a table, and delete the first column with enabled change tracking:
2814 // now the column is not deleted silently, but keeps the deleted cell content,
2815 // and only accepting it will result the deletion of the table column.
2816 createSwDoc("tdf149498.docx");
2818 // select table, copy, paste and Undo
2819 dispatchCommand(mxComponent, ".uno:SelectAll", {});
2820 dispatchCommand(mxComponent, ".uno:Copy", {});
2821 dispatchCommand(mxComponent, ".uno:Paste", {});
2823 // this would crash due to bookmark over cell boundary
2824 dispatchCommand(mxComponent, ".uno:Undo", {});
2826 #endif
2828 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf150673_RedlineTableColumnDeletionWithExport)
2830 // load a table, and delete the first column with enabled change tracking:
2831 // now the column is not deleted silently, but keeps the deleted cell contents,
2832 // and only accepting all of them will result the deletion of the table column.
2833 createSwDoc("tdf118311.fodt");
2834 SwDoc* pDoc = getSwDoc();
2836 // turn on red-lining and show changes
2837 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2838 | RedlineFlags::ShowInsert);
2839 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2840 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2841 CPPUNIT_ASSERT_MESSAGE(
2842 "redlines should be visible",
2843 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2845 // check table
2846 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2847 assertXPath(pXmlDoc, "//page[1]//body/tab");
2849 // delete table column with enabled change tracking
2850 // (HasTextChangesOnly property of the cell will be false)
2851 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2853 // Deleted text content with change tracking,
2854 // but not table deletion
2855 discardDumpedLayout();
2856 pXmlDoc = parseLayoutDump();
2857 assertXPath(pXmlDoc, "//page[1]//body/tab");
2858 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2860 // Save it and load it back.
2861 saveAndReload("writer8");
2862 pDoc = getSwDoc();
2864 // accept the deletion of the content of the first cell
2865 SwEditShell* const pEditShell(pDoc->GetEditShell());
2866 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2867 pEditShell->AcceptRedline(0);
2869 // first table column was deleted finally
2870 // (working export/import of HasTextChangesOnly)
2871 discardDumpedLayout();
2872 pXmlDoc = parseLayoutDump();
2873 assertXPath(pXmlDoc, "//page[1]//body/tab");
2874 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2876 // check removing HasTextChangesOnly at acceptance of the deletion
2878 // Undo, and delete the column without change tracking
2879 dispatchCommand(mxComponent, ".uno:Undo", {});
2881 // table column exists again
2882 discardDumpedLayout();
2883 pXmlDoc = parseLayoutDump();
2884 assertXPath(pXmlDoc, "//page[1]//body/tab");
2885 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2887 // reject deletion, setting HasTextChangesOnly to TRUE
2888 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2889 pEditShell->RejectRedline(0);
2890 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
2892 // delete table column with enabled change tracking
2893 dispatchCommand(mxComponent, ".uno:SelectColumn", {});
2894 dispatchCommand(mxComponent, ".uno:Delete", {});
2896 // Table column still exists
2897 discardDumpedLayout();
2898 pXmlDoc = parseLayoutDump();
2899 assertXPath(pXmlDoc, "//page[1]//body/tab");
2900 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2902 // reject the deletion of the content of the first cell
2903 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2904 pEditShell->AcceptRedline(0);
2906 // table column is still not deleted
2907 discardDumpedLayout();
2908 pXmlDoc = parseLayoutDump();
2909 assertXPath(pXmlDoc, "//page[1]//body/tab");
2910 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2913 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableColumnDeletionWithDOCXExport)
2915 // load a 1-row table, and delete the first column with enabled change tracking:
2916 createSwDoc("tdf118311.fodt");
2917 SwDoc* pDoc = getSwDoc();
2919 // turn on red-lining and show changes
2920 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2921 | RedlineFlags::ShowInsert);
2922 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2923 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2924 CPPUNIT_ASSERT_MESSAGE(
2925 "redlines should be visible",
2926 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2928 // check table
2929 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2930 assertXPath(pXmlDoc, "//page[1]//body/tab");
2931 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2933 // delete first table column with enabled change tracking
2934 // (HasTextChangesOnly property of the cell will be false)
2935 dispatchCommand(mxComponent, ".uno:DeleteColumns", {});
2937 // Deleted text content with change tracking,
2938 // but not table deletion
2939 discardDumpedLayout();
2940 pXmlDoc = parseLayoutDump();
2941 assertXPath(pXmlDoc, "//page[1]//body/tab");
2942 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
2944 // Save it to a DOCX and load it back.
2945 // Exporting change tracking of the cell wasn't supported.
2946 // Also Manage Changes for the import.
2947 saveAndReload("Office Open XML Text");
2948 pDoc = getSwDoc();
2950 // accept the deletion of the content of the first cell
2951 SwEditShell* const pEditShell(pDoc->GetEditShell());
2952 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2953 pEditShell->AcceptRedline(0);
2955 // table column was deleted
2956 // (working export/import of HasTextChangesOnly of table cells)
2957 discardDumpedLayout();
2958 pXmlDoc = parseLayoutDump();
2959 assertXPath(pXmlDoc, "//page[1]//body/tab");
2960 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 1);
2963 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf155341_RedlineTableColumnInsertionWithExport)
2965 // load a table, and insert a new column with enabled change tracking
2966 createSwDoc("tdf118311.fodt");
2967 SwDoc* pDoc = getSwDoc();
2969 // turn on red-lining and show changes
2970 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
2971 | RedlineFlags::ShowInsert);
2972 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2973 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
2974 CPPUNIT_ASSERT_MESSAGE(
2975 "redlines should be visible",
2976 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
2978 // check table
2979 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2980 assertXPath(pXmlDoc, "//page[1]//body/tab");
2982 // insert table column with enabled change tracking
2983 // (HasTextChangesOnly property of the cell will be false)
2984 dispatchCommand(mxComponent, ".uno:InsertColumnsAfter", {});
2986 // text content with change tracking (dummy redline)
2987 discardDumpedLayout();
2988 pXmlDoc = parseLayoutDump();
2989 assertXPath(pXmlDoc, "//page[1]//body/tab");
2990 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 3);
2992 // Save it and load it back.
2993 saveAndReload("writer8");
2994 pDoc = getSwDoc();
2996 // reject the insertion of the hidden content of the cell
2997 SwEditShell* const pEditShell(pDoc->GetEditShell());
2998 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
2999 pEditShell->RejectRedline(0);
3001 // inserted table column was deleted
3002 // (working export/import of HasTextChangesOnly)
3003 discardDumpedLayout();
3004 pXmlDoc = parseLayoutDump();
3005 assertXPath(pXmlDoc, "//page[1]//body/tab");
3006 assertXPath(pXmlDoc, "//page[1]//body/tab/row/cell", 2);
3009 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128335)
3011 // Load the bugdoc, which has 3 textboxes.
3012 createSwDoc("tdf128335.odt");
3013 SwDoc* pDoc = getSwDoc();
3015 // Select the 3rd textbox.
3016 SwView* pView = pDoc->GetDocShell()->GetView();
3017 selectShape(1);
3018 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
3019 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3020 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3021 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3022 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3023 Scheduler::ProcessEventsToIdle();
3025 // Cut it.
3026 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3028 // Paste it: this makes the 3rd textbox anchored in the 2nd one.
3029 pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
3031 selectShape(1);
3033 // Cut them.
3034 // Without the accompanying fix in place, this test would have crashed as the textboxes were
3035 // deleted in an incorrect order.
3036 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3039 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowDeletionWithReject)
3041 // load a 1-row table, and delete the row with enabled change tracking:
3042 // now the row is not deleted silently, but keeps the deleted cell contents,
3043 // and only accepting all of them will result the deletion of the table row.
3044 createSwDoc("tdf118311.fodt");
3045 SwDoc* pDoc = getSwDoc();
3047 // turn on red-lining and show changes
3048 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3049 | RedlineFlags::ShowInsert);
3050 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3051 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3052 CPPUNIT_ASSERT_MESSAGE(
3053 "redlines should be visible",
3054 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3056 // check table
3057 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3058 assertXPath(pXmlDoc, "//page[1]//body/tab");
3060 // delete table row with enabled change tracking
3061 // (HasTextChangesOnly property of the row will be false)
3062 dispatchCommand(mxComponent, ".uno:DeleteRows", {});
3064 // Deleted text content with change tracking,
3065 // but not table deletion
3066 discardDumpedLayout();
3067 pXmlDoc = parseLayoutDump();
3068 assertXPath(pXmlDoc, "//page[1]//body/tab");
3070 // Save it and load it back.
3071 saveAndReload("writer8");
3072 pDoc = getSwDoc();
3074 // reject the deletion of the content of the first cell
3075 // HasTextChangesOnly property of the table row will be true
3076 SwEditShell* const pEditShell(pDoc->GetEditShell());
3077 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3078 pEditShell->RejectRedline(0);
3080 // Select and delete the content of the first cell
3081 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3082 dispatchCommand(mxComponent, ".uno:Delete", {});
3084 // table row was still not deleted
3085 pXmlDoc = parseLayoutDump();
3086 assertXPath(pXmlDoc, "//page[1]//body/tab");
3088 // accept all redlines
3089 while (pEditShell->GetRedlineCount())
3090 pEditShell->AcceptRedline(0);
3092 // This was table row deletion instead of remaining the empty row
3093 // (HasTextChangesOnly was false)
3094 discardDumpedLayout();
3095 pXmlDoc = parseLayoutDump();
3096 assertXPath(pXmlDoc, "//page[1]//body/tab");
3098 // restore HasTextChangesOnly = false
3099 dispatchCommand(mxComponent, ".uno:Undo", {});
3100 dispatchCommand(mxComponent, ".uno:Undo", {});
3101 dispatchCommand(mxComponent, ".uno:Undo", {});
3102 dispatchCommand(mxComponent, ".uno:Undo", {});
3103 dispatchCommand(mxComponent, ".uno:Undo", {});
3105 // accept all redlines
3106 while (pEditShell->GetRedlineCount())
3107 pEditShell->AcceptRedline(0);
3109 // table row (and the 1-row table) was deleted finally
3110 discardDumpedLayout();
3111 pXmlDoc = parseLayoutDump();
3112 assertXPath(pXmlDoc, "//page[1]//body/tab", 0);
3115 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testRedlineTableRowInsertionWithReject)
3117 // load a 1-row table, and insert a row with enabled change tracking
3118 createSwDoc("tdf118311.fodt");
3119 SwDoc* pDoc = getSwDoc();
3121 // turn on red-lining and show changes
3122 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3123 | RedlineFlags::ShowInsert);
3124 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3125 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3126 CPPUNIT_ASSERT_MESSAGE(
3127 "redlines should be visible",
3128 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3130 // check table and its single row
3131 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3132 assertXPath(pXmlDoc, "//page[1]//body/tab");
3133 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3135 // insert rows before and after with enabled change tracking
3136 // (HasTextChangesOnly property of the row will be false, and
3137 // add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
3138 dispatchCommand(mxComponent, ".uno:InsertRowsBefore", {});
3139 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
3141 SwEditShell* const pEditShell(pDoc->GetEditShell());
3142 // This was 0 (not tracked row insertion)
3143 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3145 discardDumpedLayout();
3146 pXmlDoc = parseLayoutDump();
3147 assertXPath(pXmlDoc, "//page[1]//body/tab");
3148 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3150 // reject redlines
3151 pEditShell->RejectRedline(0);
3152 pEditShell->RejectRedline(0);
3154 discardDumpedLayout();
3155 pXmlDoc = parseLayoutDump();
3156 assertXPath(pXmlDoc, "//page[1]//body/tab");
3157 // This was 3 (not rejected row insertion)
3158 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3161 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145089_RedlineTableRowInsertionDOCX)
3163 // load a 1-row table, and insert a row with enabled change tracking
3164 createSwDoc("tdf118311.fodt");
3165 SwDoc* pDoc = getSwDoc();
3167 // turn on red-lining and show changes
3168 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3169 | RedlineFlags::ShowInsert);
3170 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3171 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3172 CPPUNIT_ASSERT_MESSAGE(
3173 "redlines should be visible",
3174 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3176 // check table and its single row
3177 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3178 assertXPath(pXmlDoc, "//page[1]//body/tab");
3179 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3181 // insert rows before and after with enabled change tracking
3182 // (HasTextChangesOnly property of the row will be false, and
3183 // add dummy characters CH_TXT_TRACKED_DUMMY_CHAR)
3184 dispatchCommand(mxComponent, ".uno:InsertRowsBefore", {});
3185 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
3187 // save it to DOCX
3188 saveAndReload("Office Open XML Text");
3189 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
3190 SwViewShell* pViewShell
3191 = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
3192 pViewShell->Reformat();
3193 discardDumpedLayout();
3194 pXmlDoc = parseLayoutDump();
3196 assertXPath(pXmlDoc, "//page[1]//body/tab");
3197 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3199 // reject redlines
3200 SwDoc* pDOCXDoc(pTextDoc->GetDocShell()->GetDoc());
3201 SwEditShell* const pEditShell(pDOCXDoc->GetEditShell());
3202 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
3203 pEditShell->RejectRedline(0);
3204 pEditShell->RejectRedline(0);
3206 discardDumpedLayout();
3208 pXmlDoc = parseLayoutDump();
3209 assertXPath(pXmlDoc, "//page[1]//body/tab");
3211 // This was 3 (not rejected row insertion)
3212 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 1);
3215 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRow)
3217 // load a 1-row table
3218 createSwDoc("tdf118311.fodt");
3219 SwDoc* pDoc = getSwDoc();
3221 // turn on red-lining and show changes
3222 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3223 | RedlineFlags::ShowInsert);
3224 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3225 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3226 CPPUNIT_ASSERT_MESSAGE(
3227 "redlines should be visible",
3228 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3230 // check table count
3231 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3232 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3233 uno::UNO_QUERY);
3234 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3236 // check table row count
3237 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3238 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3240 // copy table row and paste it by Paste Special->Rows Above
3241 dispatchCommand(mxComponent, ".uno:SelectTable", {});
3242 dispatchCommand(mxComponent, ".uno:Copy", {});
3243 dispatchCommand(mxComponent, ".uno:Escape", {});
3244 dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
3246 // 2-row table
3247 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3249 // This was 2 (inserted as a nested table in the first cell of the new row)
3250 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3252 // Is it a tracked row insertion? Its rejection results the original 1-row table
3253 dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
3254 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3256 dispatchCommand(mxComponent, ".uno:Undo", {});
3257 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3259 dispatchCommand(mxComponent, ".uno:Redo", {});
3260 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3263 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testPasteTrackedTableRowInHideChangesMode)
3265 // load a 1-row table
3266 createSwDoc("tdf118311.fodt");
3267 SwDoc* pDoc = getSwDoc();
3269 // turn on red-lining and show changes
3270 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On);
3271 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3272 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3273 CPPUNIT_ASSERT_MESSAGE("redlines should be invisible",
3274 !IDocumentRedlineAccess::IsShowChanges(
3275 pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3277 // check table count
3278 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3279 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3280 uno::UNO_QUERY);
3281 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3283 // check table row count
3284 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3285 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3287 // copy table row and paste it by Paste Special->Rows Above
3288 dispatchCommand(mxComponent, ".uno:SelectTable", {});
3289 dispatchCommand(mxComponent, ".uno:Copy", {});
3290 dispatchCommand(mxComponent, ".uno:Escape", {});
3292 // This resulted freezing
3293 dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
3295 // 2-row table
3296 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3298 // This was 2 (inserted as a nested table in the first cell of the new row)
3299 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3301 dispatchCommand(mxComponent, ".uno:Undo", {});
3302 dispatchCommand(mxComponent, ".uno:Undo", {});
3303 dispatchCommand(mxComponent, ".uno:Undo", {}); // FIXME Why 3 Undos?
3304 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable->getRows()->getCount());
3306 dispatchCommand(mxComponent, ".uno:Redo", {});
3307 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable->getRows()->getCount());
3310 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf146966)
3312 // load a 4-row table, select more than 1 row and copy them
3313 // to check insertion of unnecessary empty rows
3314 createSwDoc("tdf144748.fodt");
3315 SwDoc* pDoc = getSwDoc();
3317 // check table row count
3318 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3319 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
3320 uno::UNO_QUERY);
3321 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
3322 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
3323 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
3325 // copy table row and paste it by Paste Special->Rows Above
3326 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
3327 pWrtShell->Down(/*bSelect=*/false);
3328 dispatchCommand(mxComponent, ".uno:SelectTable", {});
3329 dispatchCommand(mxComponent, ".uno:Copy", {});
3330 dispatchCommand(mxComponent, ".uno:Escape", {});
3331 dispatchCommand(mxComponent, ".uno:PasteRowsBefore", {});
3333 // This was 35 (extra empty rows)
3334 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
3336 dispatchCommand(mxComponent, ".uno:Undo", {});
3337 dispatchCommand(mxComponent, ".uno:Undo", {});
3338 dispatchCommand(mxComponent, ".uno:Undo", {}); // FIXME Why 3 Undos?
3339 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable->getRows()->getCount());
3341 dispatchCommand(mxComponent, ".uno:Redo", {});
3342 dispatchCommand(mxComponent, ".uno:Redo", {});
3343 CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xTable->getRows()->getCount());
3344 // dispatchCommand(mxComponent, ".uno:Redo", {}); // FIXME assert
3347 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145091)
3349 // load a deleted table, reject them, and delete only its text and export to DOCX
3350 createSwDoc("tdf145091.docx");
3351 SwDoc* pDoc = getSwDoc();
3353 // turn on red-lining and show changes
3354 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3355 | RedlineFlags::ShowInsert);
3356 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3357 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3358 CPPUNIT_ASSERT_MESSAGE(
3359 "redlines should be visible",
3360 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3362 // reject all redlines
3363 SwEditShell* const pEditShell(pDoc->GetEditShell());
3364 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
3365 while (pEditShell->GetRedlineCount() > 0)
3366 pEditShell->RejectRedline(0);
3367 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
3369 // delete only table text, but not table
3370 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3371 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3372 dispatchCommand(mxComponent, ".uno:Delete", {});
3373 CPPUNIT_ASSERT(pEditShell->GetRedlineCount() > 0);
3375 // save it to DOCX
3376 saveAndReload("Office Open XML Text");
3377 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
3378 SwViewShell* pViewShell
3379 = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
3380 pViewShell->Reformat();
3381 discardDumpedLayout();
3382 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3384 assertXPath(pXmlDoc, "//page[1]//body/tab");
3385 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3387 // accept all redlines
3388 dispatchCommand(mxComponent, ".uno:AcceptAllTrackedChanges", {});
3390 discardDumpedLayout();
3392 pXmlDoc = parseLayoutDump();
3393 // This was false (deleted table with accepting deletions)
3394 assertXPath(pXmlDoc, "//page[1]//body/tab");
3395 assertXPath(pXmlDoc, "//page[1]//body/tab/row", 3);
3398 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf128603)
3400 // Load the bugdoc, which has 3 textboxes.
3401 createSwDoc("tdf128603.odt");
3402 SwDoc* pDoc = getSwDoc();
3404 // Select the 3rd textbox.
3405 SwView* pView = pDoc->GetDocShell()->GetView();
3406 selectShape(1);
3407 SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
3408 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3409 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3410 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
3411 pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
3412 Scheduler::ProcessEventsToIdle();
3414 // Cut it.
3415 pView->GetViewFrame().GetDispatcher()->Execute(SID_CUT, SfxCallMode::SYNCHRON);
3417 // Paste it: this makes the 3rd textbox anchored in the 2nd one.
3418 pView->GetViewFrame().GetDispatcher()->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
3420 // Undo all of this.
3421 sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
3422 rUndoManager.Undo();
3423 rUndoManager.Undo();
3425 // Make sure the content indexes still match.
3426 const auto& rSpzFrameFormats = *pDoc->GetSpzFrameFormats();
3427 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), rSpzFrameFormats.size());
3428 const SwNodeIndex* pIndex4 = rSpzFrameFormats[4]->GetContent().GetContentIdx();
3429 CPPUNIT_ASSERT(pIndex4);
3430 const SwNodeIndex* pIndex5 = rSpzFrameFormats[5]->GetContent().GetContentIdx();
3431 CPPUNIT_ASSERT(pIndex5);
3432 // Without the accompanying fix in place, this test would have failed with:
3433 // - Expected: 11
3434 // - Actual : 14
3435 // i.e. the shape content index and the frame content index did not match after undo, even if
3436 // their "other text box format" pointers pointed to each other.
3437 CPPUNIT_ASSERT_EQUAL(pIndex4->GetIndex(), pIndex5->GetIndex());
3440 // only care that it doesn't assert/crash
3441 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testOfz18563)
3443 OUString sURL(m_directories.getURLFromSrc(u"/sw/qa/extras/uiwriter/data/ofz18563.docx"));
3444 SvFileStream aFileStream(sURL, StreamMode::READ);
3445 TestImportDOCX(aFileStream);
3448 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf143904)
3450 createSwDoc("tdf143904.odt");
3451 SwDoc* pDoc = getSwDoc();
3453 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
3454 CPPUNIT_ASSERT(pWrtShell);
3456 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3458 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
3459 pWrtShell->Down(false);
3460 pWrtShell->Insert("foo");
3462 SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3463 CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
3464 nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3465 SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3466 CPPUNIT_ASSERT_EQUAL(OUString("foo"), pTextNodeA2->GetText());
3467 CPPUNIT_ASSERT_EQUAL(false, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
3468 OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
3469 CPPUNIT_ASSERT_EQUAL(OUString("Liberation Serif"), sFontName);
3472 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf90069)
3474 createSwDoc("tdf90069.docx");
3475 SwDoc* pDoc = getSwDoc();
3477 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
3478 CPPUNIT_ASSERT(pWrtShell);
3480 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3482 dispatchCommand(mxComponent, ".uno:InsertRowsAfter", {});
3483 pWrtShell->Down(false);
3484 pWrtShell->Insert("foo");
3486 SwTextNode* pTextNodeA1 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3487 CPPUNIT_ASSERT(pTextNodeA1->GetText().startsWith("Insert"));
3488 nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3489 SwTextNode* pTextNodeA2 = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3490 CPPUNIT_ASSERT_EQUAL(OUString("foo"), pTextNodeA2->GetText());
3491 CPPUNIT_ASSERT_EQUAL(true, pTextNodeA2->GetSwAttrSet().HasItem(RES_CHRATR_FONT));
3492 OUString sFontName = pTextNodeA2->GetSwAttrSet().GetItem(RES_CHRATR_FONT)->GetFamilyName();
3493 CPPUNIT_ASSERT_EQUAL(OUString("Lohit Devanagari"), sFontName);
3496 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf109266)
3498 // transliteration with redlining
3499 createSwDoc("lorem.fodt");
3500 SwDoc* pDoc = getSwDoc();
3501 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
3502 CPPUNIT_ASSERT(pWrtShell);
3504 SwNodeOffset nIndex = pWrtShell->GetCursor()->GetPointNode().GetIndex();
3505 SwTextNode* pTextNode = static_cast<SwTextNode*>(pDoc->GetNodes()[nIndex]);
3507 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum..."), pTextNode->GetText());
3508 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum..."), pTextNode->GetRedlineText());
3510 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3511 dispatchCommand(mxComponent, ".uno:ChangeCaseToTitleCase", {});
3513 CPPUNIT_ASSERT_EQUAL(OUString("Lorem Ipsum..."), pTextNode->GetText());
3514 CPPUNIT_ASSERT_EQUAL(OUString("Lorem Ipsum..."), pTextNode->GetRedlineText());
3516 //turn on red-lining and show changes
3517 RedlineFlags const mode(pWrtShell->GetRedlineFlags() | RedlineFlags::On);
3518 CPPUNIT_ASSERT(mode & (RedlineFlags::ShowDelete | RedlineFlags::ShowInsert));
3519 pWrtShell->SetRedlineFlags(mode);
3520 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3521 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3522 CPPUNIT_ASSERT_MESSAGE(
3523 "redlines should be visible",
3524 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3526 dispatchCommand(mxComponent, ".uno:Undo", {});
3527 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3528 dispatchCommand(mxComponent, ".uno:ChangeCaseToTitleCase", {});
3530 // This was "Lorem Ipsum..." (missing redlining)
3531 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsumIpsum..."), pTextNode->GetText());
3532 CPPUNIT_ASSERT_EQUAL(OUString("Lorem Ipsum..."), pTextNode->GetRedlineText());
3534 dispatchCommand(mxComponent, ".uno:Undo", {});
3535 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3536 dispatchCommand(mxComponent, ".uno:ChangeCaseToUpper", {});
3538 // This was "LOREM IPSUM..." (missing redlining)
3539 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum...LOREM IPSUM..."), pTextNode->GetText());
3540 CPPUNIT_ASSERT_EQUAL(OUString("LOREM IPSUM..."), pTextNode->GetRedlineText());
3542 dispatchCommand(mxComponent, ".uno:Undo", {});
3543 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3544 dispatchCommand(mxComponent, ".uno:ChangeCaseToLower", {});
3546 // This was "lorem ipsum..." (missing redlining)
3547 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum...lorem ipsum..."), pTextNode->GetText());
3548 CPPUNIT_ASSERT_EQUAL(OUString("lorem ipsum..."), pTextNode->GetRedlineText());
3550 dispatchCommand(mxComponent, ".uno:Undo", {});
3551 dispatchCommand(mxComponent, ".uno:SelectAll", {});
3552 dispatchCommand(mxComponent, ".uno:ChangeCaseToToggleCase", {});
3554 // This was "lOREM IPSUM..." (missing redlining)
3555 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum...lOREM IPSUM..."), pTextNode->GetText());
3556 CPPUNIT_ASSERT_EQUAL(OUString("lOREM IPSUM..."), pTextNode->GetRedlineText());
3559 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf129655)
3561 createSwDoc("tdf129655-vtextbox.odt");
3562 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
3563 assertXPath(pXmlDoc, "//anchored/fly/txt[@WritingMode='Vertical']", 1);
3566 static uno::Reference<text::XTextRange> getAssociatedTextRange(uno::Any object)
3568 // possible cases:
3569 // 1. a container of other objects - e.g. selection of 0 to n text portions, or 1 to n drawing objects
3572 uno::Reference<container::XIndexAccess> xIndexAccess(object, uno::UNO_QUERY_THROW);
3573 if (xIndexAccess.is() && xIndexAccess->getCount() > 0)
3575 for (int i = 0; i < xIndexAccess->getCount(); ++i)
3577 uno::Reference<text::XTextRange> xRange
3578 = getAssociatedTextRange(xIndexAccess->getByIndex(i));
3579 if (xRange.is())
3580 return xRange;
3584 catch (const uno::Exception&)
3588 // 2. another TextContent, having an anchor we can use
3591 uno::Reference<text::XTextContent> xTextContent(object, uno::UNO_QUERY_THROW);
3592 if (xTextContent.is())
3594 uno::Reference<text::XTextRange> xRange = xTextContent->getAnchor();
3595 if (xRange.is())
3596 return xRange;
3599 catch (const uno::Exception&)
3603 // an object which supports XTextRange directly
3606 uno::Reference<text::XTextRange> xRange(object, uno::UNO_QUERY_THROW);
3607 if (xRange.is())
3608 return xRange;
3610 catch (const uno::Exception&)
3614 return nullptr;
3617 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf123218)
3619 struct ReverseXAxisOrientationDoughnutChart
3620 : public comphelper::ConfigurationProperty<ReverseXAxisOrientationDoughnutChart, bool>
3622 static OUString path()
3624 return "/org.openoffice.Office.Compatibility/View/ReverseXAxisOrientationDoughnutChart";
3626 ~ReverseXAxisOrientationDoughnutChart() = delete;
3629 struct ClockwisePieChartDirection
3630 : public comphelper::ConfigurationProperty<ClockwisePieChartDirection, bool>
3632 static OUString path()
3634 return "/org.openoffice.Office.Compatibility/View/ClockwisePieChartDirection";
3636 ~ClockwisePieChartDirection() = delete;
3638 auto batch = comphelper::ConfigurationChanges::create();
3640 ReverseXAxisOrientationDoughnutChart::set(false, batch);
3641 ClockwisePieChartDirection::set(true, batch);
3642 batch->commit();
3644 createSwDoc();
3646 // create an OLE shape in the document
3647 uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY_THROW);
3648 CPPUNIT_ASSERT(xMSF);
3649 uno::Reference<beans::XPropertySet> xShapeProps(
3650 xMSF->createInstance("com.sun.star.text.TextEmbeddedObject"), uno::UNO_QUERY);
3651 xShapeProps->setPropertyValue("CLSID",
3652 uno::Any(OUString("12dcae26-281f-416f-a234-c3086127382e")));
3653 uno::Reference<drawing::XShape> xShape(xShapeProps, uno::UNO_QUERY_THROW);
3654 xShape->setSize(awt::Size(16000, 9000));
3655 uno::Reference<text::XTextContent> chartTextContent(xShapeProps, uno::UNO_QUERY_THROW);
3656 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
3657 uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
3658 uno::UNO_QUERY_THROW);
3659 uno::Any aSelection = xSelSupplier->getSelection();
3660 uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
3661 CPPUNIT_ASSERT(xTextRange);
3662 xTextRange->getText()->insertTextContent(xTextRange, chartTextContent, false);
3664 // insert a doughnut chart
3665 uno::Reference<frame::XModel> xDocModel;
3666 xShapeProps->getPropertyValue("Model") >>= xDocModel;
3667 CPPUNIT_ASSERT(xDocModel);
3668 uno::Reference<chart::XChartDocument> xChartDoc(xDocModel, uno::UNO_QUERY_THROW);
3669 CPPUNIT_ASSERT(xChartDoc);
3670 uno::Reference<lang::XMultiServiceFactory> xChartMSF(xChartDoc, uno::UNO_QUERY_THROW);
3671 CPPUNIT_ASSERT(xChartMSF);
3672 uno::Reference<chart::XDiagram> xDiagram(
3673 xChartMSF->createInstance("com.sun.star.chart.DonutDiagram"), uno::UNO_QUERY);
3674 xChartDoc->setDiagram(xDiagram);
3676 // test primary X axis Orientation value
3677 uno::Reference<chart2::XChartDocument> xChartDoc2(xChartDoc, uno::UNO_QUERY_THROW);
3678 CPPUNIT_ASSERT(xChartDoc2);
3679 uno::Reference<chart2::XCoordinateSystemContainer> xCooSysContainer(
3680 xChartDoc2->getFirstDiagram(), uno::UNO_QUERY_THROW);
3681 uno::Sequence<uno::Reference<chart2::XCoordinateSystem>> xCooSysSequence
3682 = xCooSysContainer->getCoordinateSystems();
3683 uno::Reference<chart2::XCoordinateSystem> xCoord = xCooSysSequence[0];
3684 CPPUNIT_ASSERT(xCoord.is());
3685 uno::Reference<chart2::XAxis> xAxis = xCoord->getAxisByDimension(0, 0);
3686 CPPUNIT_ASSERT(xAxis.is());
3687 chart2::ScaleData aScaleData = xAxis->getScaleData();
3688 CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_MATHEMATICAL, aScaleData.Orientation);
3690 // tdf#108059 test primary Y axis Orientation value
3691 uno::Reference<chart2::XAxis> xYAxis = xCoord->getAxisByDimension(1, 0);
3692 CPPUNIT_ASSERT(xYAxis.is());
3693 aScaleData = xYAxis->getScaleData();
3694 CPPUNIT_ASSERT_EQUAL(chart2::AxisOrientation_REVERSE, aScaleData.Orientation);
3697 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf93747)
3699 createSwDoc();
3700 SwDoc* pDoc = getSwDoc();
3701 SwWrtShell* pWrtSh = pDoc->GetDocShell()->GetWrtShell();
3703 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
3704 { { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
3706 dispatchCommand(mxComponent, ".uno:InsertTable", aArgs);
3708 pWrtSh->Insert("Col1");
3710 // Move the cursor to B1
3711 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
3713 pWrtSh->Insert("Col2");
3715 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3716 uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
3717 uno::UNO_QUERY);
3718 uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
3719 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
3720 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
3721 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
3723 uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName("A1"), uno::UNO_QUERY);
3724 CPPUNIT_ASSERT_EQUAL(OUString("Col1"), xCellA1->getString());
3726 uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName("B1"), uno::UNO_QUERY);
3727 CPPUNIT_ASSERT_EQUAL(OUString("Col2"), xCellB1->getString());
3729 // Select backwards B1 and A1
3730 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
3732 // Just select the whole B1
3733 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3735 uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
3736 { "Style", uno::Any(OUString("Heading 1")) },
3737 { "FamilyName", uno::Any(OUString("ParagraphStyles")) },
3739 dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
3741 // Without the fix in place, this test would have failed with
3742 // - Expected: Table Contents
3743 // - Actual : Heading 1
3744 CPPUNIT_ASSERT_EQUAL(
3745 OUString("Table Contents"),
3746 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "ParaStyleName"));
3748 CPPUNIT_ASSERT_EQUAL(
3749 OUString("Heading 1"),
3750 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "ParaStyleName"));
3752 // Now select A1 again
3753 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3755 dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
3757 CPPUNIT_ASSERT_EQUAL(
3758 OUString("Heading 1"),
3759 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "ParaStyleName"));
3761 CPPUNIT_ASSERT_EQUAL(
3762 OUString("Heading 1"),
3763 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "ParaStyleName"));
3765 dispatchCommand(mxComponent, ".uno:Undo", {});
3767 CPPUNIT_ASSERT_EQUAL(
3768 OUString("Table Contents"),
3769 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "ParaStyleName"));
3771 CPPUNIT_ASSERT_EQUAL(
3772 OUString("Heading 1"),
3773 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "ParaStyleName"));
3775 dispatchCommand(mxComponent, ".uno:Undo", {});
3777 CPPUNIT_ASSERT_EQUAL(
3778 OUString("Table Contents"),
3779 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "ParaStyleName"));
3781 CPPUNIT_ASSERT_EQUAL(
3782 OUString("Table Contents"),
3783 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "ParaStyleName"));
3786 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf145151)
3788 createSwDoc();
3789 SwDoc* pDoc = getSwDoc();
3790 SwWrtShell* pWrtSh = pDoc->GetDocShell()->GetWrtShell();
3792 uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
3793 { { "Rows", uno::Any(sal_Int32(2)) }, { "Columns", uno::Any(sal_Int32(2)) } }));
3795 dispatchCommand(mxComponent, ".uno:InsertTable", aArgs);
3797 pWrtSh->Insert("Col1");
3799 // Move the cursor to B1
3800 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
3802 pWrtSh->Insert("Col2");
3804 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
3805 uno::Reference<container::XIndexAccess> xIndexAccess(xTextTablesSupplier->getTextTables(),
3806 uno::UNO_QUERY);
3807 uno::Reference<text::XTextTable> xTextTable(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
3808 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
3809 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getRows()->getCount());
3810 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTextTable->getColumns()->getCount());
3812 uno::Reference<text::XTextRange> xCellA1(xTextTable->getCellByName("A1"), uno::UNO_QUERY);
3813 CPPUNIT_ASSERT_EQUAL(OUString("Col1"), xCellA1->getString());
3815 uno::Reference<text::XTextRange> xCellB1(xTextTable->getCellByName("B1"), uno::UNO_QUERY);
3816 CPPUNIT_ASSERT_EQUAL(OUString("Col2"), xCellB1->getString());
3818 // Select backwards B1 and A1 (select "2loC<cell>" which ends up selecting both cells)
3819 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
3821 // Just select the whole B1
3822 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3824 dispatchCommand(mxComponent, ".uno:DefaultNumbering", {});
3826 // B1 should now have a numbering style, but A1 should not be affected.
3827 OUString sNumStyleB1
3828 = getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "NumberingStyleName");
3829 CPPUNIT_ASSERT(!sNumStyleB1.isEmpty());
3830 CPPUNIT_ASSERT_MESSAGE(
3831 "Only cell B1 was selected. A1 should not have any numbering.",
3832 getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "NumberingStyleName")
3833 .isEmpty());
3835 // Toggle it back off
3836 dispatchCommand(mxComponent, ".uno:DefaultNumbering", {});
3838 CPPUNIT_ASSERT_MESSAGE(
3839 "Cell B1 must be able to toggle numbering on and off.",
3840 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "NumberingStyleName")
3841 .isEmpty());
3843 // Now test removing numbering/bullets
3844 // Add A1 to the current B1 selection
3845 pWrtSh->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3847 // Toggle on bullet numbering
3848 dispatchCommand(mxComponent, ".uno:DefaultBullet", {});
3850 // sanity check - both cells have bullets turned on.
3851 OUString sNumStyleA1
3852 = getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "NumberingStyleName");
3853 CPPUNIT_ASSERT(!sNumStyleA1.isEmpty());
3854 CPPUNIT_ASSERT_EQUAL(
3855 sNumStyleA1,
3856 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "NumberingStyleName"));
3857 CPPUNIT_ASSERT(sNumStyleA1 != sNumStyleB1); // therefore B1 changed from numbering to bullets
3859 // Just select cell B1
3860 pWrtSh->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false);
3862 // Toggle off bullet numbering
3863 dispatchCommand(mxComponent, ".uno:DefaultBullet", {});
3865 // B1 should now have removed all numbering, while A1 should still have the bullet.
3866 CPPUNIT_ASSERT(
3867 getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "NumberingStyleName")
3868 .isEmpty());
3869 CPPUNIT_ASSERT_MESSAGE(
3870 "Only cell B1 was selected. A1 should still have bullets turned on.",
3871 !getProperty<OUString>(getParagraphOfText(1, xCellA1->getText()), "NumberingStyleName")
3872 .isEmpty());
3874 // Toggle it back on
3875 dispatchCommand(mxComponent, ".uno:DefaultBullet", {});
3877 CPPUNIT_ASSERT(
3878 !getProperty<OUString>(getParagraphOfText(1, xCellB1->getText()), "NumberingStyleName")
3879 .isEmpty());
3882 CPPUNIT_TEST_FIXTURE(SwUiWriterTest5, testTdf126735)
3884 createSwDoc("tdf39721.fodt");
3885 SwDoc* pDoc = getSwDoc();
3887 //turn on red-lining and show changes
3888 pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
3889 | RedlineFlags::ShowInsert);
3890 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
3891 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
3892 CPPUNIT_ASSERT_MESSAGE(
3893 "redlines should be visible",
3894 IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
3896 // check next selected tracked change
3897 dispatchCommand(mxComponent, ".uno:NextTrackedChange", {});
3898 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
3899 uno::Reference<view::XSelectionSupplier> xSelSupplier(xModel->getCurrentController(),
3900 uno::UNO_QUERY_THROW);
3901 uno::Any aSelection = xSelSupplier->getSelection();
3902 uno::Reference<text::XTextRange> xTextRange = getAssociatedTextRange(aSelection);
3903 CPPUNIT_ASSERT(xTextRange);
3904 CPPUNIT_ASSERT_EQUAL(OUString(" ipsu"), xTextRange->getString());
3906 // check next selected tracked change
3907 dispatchCommand(mxComponent, ".uno:NextTrackedChange", {});
3908 aSelection = xSelSupplier->getSelection();
3909 xTextRange = getAssociatedTextRange(aSelection);
3910 CPPUNIT_ASSERT(xTextRange);
3911 CPPUNIT_ASSERT_EQUAL(OUString("or "), xTextRange->getString());
3913 // check next selected tracked change at the end of the document:
3914 // select the first tracked change of the document
3915 dispatchCommand(mxComponent, ".uno:NextTrackedChange", {});
3916 aSelection = xSelSupplier->getSelection();
3917 xTextRange = getAssociatedTextRange(aSelection);
3918 CPPUNIT_ASSERT(xTextRange);
3919 // This was empty (collapsing at the end of the last tracked change)
3920 CPPUNIT_ASSERT_EQUAL(OUString(" ipsu"), xTextRange->getString());
3922 // check the previous tracked change at the start of the document:
3923 // select the last tracked change of the document
3924 dispatchCommand(mxComponent, ".uno:PreviousTrackedChange", {});
3925 aSelection = xSelSupplier->getSelection();
3926 xTextRange = getAssociatedTextRange(aSelection);
3927 CPPUNIT_ASSERT(xTextRange);
3928 // This was empty (collapsing at the start of the last tracked change)
3929 CPPUNIT_ASSERT_EQUAL(OUString("or "), xTextRange->getString());
3932 CPPUNIT_PLUGIN_IMPLEMENT();
3934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */