1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <com/sun/star/drawing/FillStyle.hpp>
11 #include <swmodeltestbase.hxx>
13 #include <itabenum.hxx>
17 #include <drawdoc.hxx>
19 #include <com/sun/star/text/XTextColumns.hpp>
21 #include <svx/svdpage.hxx>
22 #include <svx/svdview.hxx>
23 #include <svl/itemiter.hxx>
24 #include <vcl/filter/PDFiumLibrary.hxx>
27 #include <txatbase.hxx>
28 #include <IDocumentDrawModelAccess.hxx>
29 #include <IDocumentRedlineAccess.hxx>
30 #include <IDocumentLayoutAccess.hxx>
31 #include <UndoManager.hxx>
33 #include <svl/stritem.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/dispatch.hxx>
37 #include <tools/json_writer.hxx>
38 #include <tools/UnitConversion.hxx>
39 #include <boost/property_tree/json_parser.hpp>
41 #include <com/sun/star/text/XTextTable.hpp>
42 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
43 #include <com/sun/star/view/XSelectionSupplier.hpp>
44 #include <o3tl/cppunittraitshelper.hxx>
45 #include <swdtflvr.hxx>
46 #include <comphelper/propertysequence.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <comphelper/scopeguard.hxx>
50 #include <editeng/swafopt.hxx>
51 #include <editeng/unolingu.hxx>
52 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
53 #include <vcl/scheduler.hxx>
54 #include <config_fonts.h>
55 #include <test/htmltesttools.hxx>
56 #include <wrthtml.hxx>
58 #include <rootfrm.hxx>
59 #include <pagefrm.hxx>
60 #include <sortedobjs.hxx>
61 #include <flyfrms.hxx>
63 #include <unotxdoc.hxx>
65 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
66 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
67 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
68 #include <linguistic/misc.hxx>
70 #include <workctrl.hxx>
72 using namespace com::sun::star
;
73 using namespace com::sun::star::beans
;
74 using namespace com::sun::star::lang
;
75 using namespace com::sun::star::uno
;
76 using namespace com::sun::star::linguistic2
;
77 using namespace linguistic
;
81 sal_Int32
lcl_getAttributeIDFromHints(const SwpHints
& hints
)
83 for (size_t i
= 0; i
< hints
.Count(); ++i
)
85 const SwTextAttr
* hint
= hints
.Get(i
);
86 if (hint
->Which() == RES_TXTATR_AUTOFMT
)
88 const SwFormatAutoFormat
& rFmt
= hint
->GetAutoFormat();
89 SfxItemIter
aIter(*rFmt
.GetStyleHandle());
90 return aIter
.GetCurItem()->Which();
96 uno::Reference
<XLinguServiceManager2
> GetLngSvcMgr_Impl()
98 uno::Reference
<XComponentContext
> xContext(comphelper::getProcessComponentContext());
99 uno::Reference
<XLinguServiceManager2
> xRes
= LinguServiceManager::create(xContext
);
104 class SwUiWriterTest6
: public SwModelTestBase
, public HtmlTestTools
108 : SwModelTestBase(u
"/sw/qa/extras/uiwriter/data/"_ustr
)
113 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116640
)
117 uno::Sequence
<beans::PropertyValue
> aArgs(
118 comphelper::InitPropertySequence({ { "Columns", uno::Any(sal_Int32(2)) } }));
120 dispatchCommand(mxComponent
, u
".uno:InsertSection"_ustr
, aArgs
);
122 uno::Reference
<text::XTextSectionsSupplier
> xTextSectionsSupplier(mxComponent
, uno::UNO_QUERY
);
123 uno::Reference
<container::XIndexAccess
> xSections(xTextSectionsSupplier
->getTextSections(),
125 uno::Reference
<beans::XPropertySet
> xTextSection(xSections
->getByIndex(0), uno::UNO_QUERY
);
127 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
129 uno::Reference
<text::XTextColumns
> xTextColumns
130 = getProperty
<uno::Reference
<text::XTextColumns
>>(xTextSection
, u
"TextColumns"_ustr
);
131 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xTextColumns
->getColumnCount());
133 dispatchCommand(mxComponent
, u
".uno:Undo"_ustr
, {});
135 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
137 dispatchCommand(mxComponent
, u
".uno:Redo"_ustr
, {});
139 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSections
->getCount());
141 dispatchCommand(mxComponent
, u
".uno:Undo"_ustr
, {});
143 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xSections
->getCount());
146 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf108524
)
148 createSwDoc("tdf108524.odt");
149 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
150 // In total we expect two cells containing a section.
151 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
153 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
154 // This was 0, section wasn't split, instead it was only on the first page
155 // and it was cut off.
156 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
159 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testLinesInSectionInTable
)
161 // This is similar to testTdf108524(), but the page boundary now is not in
162 // the middle of a multi-line paragraph: the section only contains oneliner
163 // paragraphs instead.
164 createSwDoc("lines-in-section-in-table.odt");
165 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
166 // In total we expect two cells containing a section.
167 assertXPath(pXmlDoc
, "/root/page/body/tab/row/cell/section", 2);
169 assertXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell/section", 1);
170 // This was 0, section wasn't split, instead it was only on the first page
171 // and it was cut off.
172 assertXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell/section", 1);
175 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testLinesMoveBackwardsInSectionInTable
)
178 // Assert that paragraph "4" is on page 1 and "5" is on page 2.
179 createSwDoc("lines-in-section-in-table.odt");
180 SwDoc
* pDoc
= getSwDoc();
181 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
182 assertXPath(pXmlDoc
, "/root/page", 2);
183 SwNodeOffset
nPara4Node(
184 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
186 CPPUNIT_ASSERT_EQUAL(u
"4"_ustr
, pDoc
->GetNodes()[nPara4Node
]->GetTextNode()->GetText());
187 SwNodeOffset
nPara5Node(
188 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
190 CPPUNIT_ASSERT_EQUAL(u
"5"_ustr
, pDoc
->GetNodes()[nPara5Node
]->GetTextNode()->GetText());
192 // Remove paragraph "4".
193 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
194 while (pWrtShell
->GetCursor()->GetPointNode().GetIndex() < nPara4Node
)
195 pWrtShell
->Down(/*bSelect=*/false);
196 pWrtShell
->EndPara();
197 pWrtShell
->Up(/*bSelect=*/true);
198 pWrtShell
->DelLeft();
200 // Assert that paragraph "5" is now moved back to page 1 and is the last paragraph there.
201 pXmlDoc
= parseLayoutDump();
202 SwNodeOffset
nPage1LastNode(
203 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/section/txt[last()]", "txtNodeIndex")
205 // This was "3", paragraph "4" was deleted, but "5" was not moved backwards from page 2.
206 CPPUNIT_ASSERT_EQUAL(u
"5"_ustr
, pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
210 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInSection
)
213 // The document has a section, containing a table that spans over 2 pages.
214 createSwDoc("table-in-sect.odt");
215 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
216 // In total we expect 4 cells.
217 assertXPath(pXmlDoc
, "/root/page/body/section/tab/row/cell", 4);
219 // Assert that on both pages the section contains 2 cells.
220 assertXPath(pXmlDoc
, "/root/page[1]/body/section/tab/row/cell", 2);
221 assertXPath(pXmlDoc
, "/root/page[2]/body/section/tab/row/cell", 2);
225 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInNestedSection
)
228 // The document has a nested section, containing a table that spans over 2 pages.
229 // This crashed the layout.
230 createSwDoc("rhbz739252-3.odt");
231 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
232 // Make sure the table is inside a section and spans over 2 pages.
233 assertXPath(pXmlDoc
, "//page[1]//section/tab", 1);
234 assertXPath(pXmlDoc
, "//page[2]//section/tab", 1);
238 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112741
)
241 createSwDoc("tdf112741.fodt");
242 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
244 assertXPath(pXmlDoc
, "//page", 4);
245 assertXPath(pXmlDoc
, "//page[1]/body/tab/row/cell/tab/row/cell/section", 1);
246 assertXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row/cell/section", 1);
247 // This failed, 3rd page contained no sections.
248 assertXPath(pXmlDoc
, "//page[3]/body/tab/row/cell/tab/row/cell/section", 1);
249 assertXPath(pXmlDoc
, "//page[4]/body/tab/row/cell/tab/row/cell/section", 1);
253 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112860
)
256 // The document has a split section inside a nested table, and also a table
258 // This crashed the layout.
259 createSwDoc("tdf112860.fodt");
263 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113287
)
266 createSwDoc("tdf113287.fodt");
267 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
268 assertXPath(pXmlDoc
, "//page", 2);
270 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/infos/bounds", "top").toUInt32();
271 sal_uInt32 nSectionTop
272 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell[1]/section/infos/bounds", "top")
274 // Make sure section frame is inside the cell frame.
275 // Expected greater than 4593, was only 3714.
276 CPPUNIT_ASSERT_GREATER(nCellTop
, nSectionTop
);
280 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113445
)
283 // Force multiple-page view.
284 createSwDoc("tdf113445.fodt");
285 SwDocShell
* pDocShell
= getSwDocShell();
286 SwView
* pView
= pDocShell
->GetView();
287 pView
->SetViewLayout(/*nColumns=*/2, /*bBookMode=*/false);
290 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
291 assertXPath(pXmlDoc
, "//page", 2);
292 sal_uInt32 nPage1Left
= getXPath(pXmlDoc
, "//page[1]/infos/bounds", "left").toUInt32();
293 sal_uInt32 nPage2Left
= getXPath(pXmlDoc
, "//page[2]/infos/bounds", "left").toUInt32();
294 // Make sure that page 2 is on the right hand side of page 1, not below it.
295 CPPUNIT_ASSERT_GREATER(nPage1Left
, nPage2Left
);
297 // Insert a new paragraph at the start of the document.
298 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
299 pWrtShell
->StartOfSection();
300 pWrtShell
->SplitNode();
301 pXmlDoc
= parseLayoutDump();
303 // Make sure that Table2:C5 and Table2:D5 has its section frame inside the cell frame.
305 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/infos/bounds", "top")
307 sal_uInt32 nSection3Top
308 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[3]/section/infos/bounds",
311 CPPUNIT_ASSERT_GREATER(nCell3Top
, nSection3Top
);
313 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/infos/bounds", "top")
315 sal_uInt32 nSection4Top
316 = getXPath(pXmlDoc
, "//page[2]/body/tab/row/cell/tab/row[4]/cell[4]/section/infos/bounds",
319 CPPUNIT_ASSERT_GREATER(nCell4Top
, nSection4Top
);
320 // Also check if the two cells in the same row have the same top position.
321 // This was 4818, expected only 1672.
322 CPPUNIT_ASSERT_EQUAL(nCell3Top
, nCell4Top
);
326 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113686
)
329 createSwDoc("tdf113686.fodt");
330 SwDoc
* pDoc
= getSwDoc();
331 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
332 assertXPath(pXmlDoc
, "/root/page", 2);
333 SwNodeOffset
nPage1LastNode(
334 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/txt[last()]",
337 CPPUNIT_ASSERT_EQUAL(u
"Table2:A1-P10"_ustr
,
338 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
339 SwNodeOffset
nPage2FirstNode(
340 getXPath(pXmlDoc
, "/root/page[2]/body/tab/row/cell[1]/section/txt[1]", "txtNodeIndex")
342 CPPUNIT_ASSERT_EQUAL(u
"Table1:A1"_ustr
,
343 pDoc
->GetNodes()[nPage2FirstNode
]->GetTextNode()->GetText());
346 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
347 while (pWrtShell
->GetCursor()->Start()->GetNodeIndex() < nPage1LastNode
)
348 pWrtShell
->Down(/*bSelect=*/false);
349 pWrtShell
->EndPara();
350 for (int i
= 0; i
< 3; ++i
)
351 pWrtShell
->Up(/*bSelect=*/true);
352 pWrtShell
->DelLeft();
354 // Assert that the second page is removed.
355 pXmlDoc
= parseLayoutDump();
356 // This was still 2, content from 2nd page was not moved.
357 assertXPath(pXmlDoc
, "/root/page", 1);
361 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTableInSectionInTable
)
364 // The document has a table, containing a section, containing a nested
366 // This crashed the layout.
367 createSwDoc("i95698.odt");
371 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable
)
374 // The document has a nested table, containing a multi-line section at a
376 // This crashed the layout later in SwFrame::IsFootnoteAllowed().
377 createSwDoc("tdf112109.fodt");
381 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable2
)
384 createSwDoc("split-section-in-nested-table.fodt");
385 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
387 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
388 sal_uInt32 nSection1Follow
389 = getXPath(pXmlDoc
, "//page[1]//body/tab/row/cell/tab/row/cell/section", "follow")
391 // This failed, the section wasn't split inside a nested table.
393 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "id").toUInt32();
394 sal_uInt32 nSection2Precede
395 = getXPath(pXmlDoc
, "//page[2]//body/tab/row/cell/tab/row/cell/section", "precede")
398 // Make sure that the first's follow and the second's precede is correct.
399 CPPUNIT_ASSERT_EQUAL(nSection2
, nSection1Follow
);
400 CPPUNIT_ASSERT_EQUAL(nSection1
, nSection2Precede
);
404 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable3
)
407 createSwDoc("tdf113153.fodt");
409 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
410 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
412 uno::Reference
<container::XNamed
> xTable(xTables
->getByIndex(1), uno::UNO_QUERY
);
413 CPPUNIT_ASSERT_EQUAL(u
"Table16"_ustr
, xTable
->getName());
415 uno::Reference
<text::XTextTable
> xRowSupplier(xTable
, uno::UNO_QUERY
);
416 uno::Reference
<table::XTableRows
> xRows
= xRowSupplier
->getRows();
417 uno::Reference
<beans::XPropertySet
> xRow(xRows
->getByIndex(1), uno::UNO_QUERY
);
418 xRow
->setPropertyValue(u
"IsSplitAllowed"_ustr
, uno::Any(true));
419 // This never returned.
422 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
423 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
424 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
425 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
426 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
427 sal_uInt32 nTable2Follow
= getXPath(pXmlDoc
, "//page[2]//body/tab", "follow").toUInt32();
428 sal_uInt32 nTable3
= getXPath(pXmlDoc
, "//page[3]//body/tab", "id").toUInt32();
429 sal_uInt32 nTable3Precede
= getXPath(pXmlDoc
, "//page[3]//body/tab", "precede").toUInt32();
431 // Make sure the outer table frames are linked together properly.
432 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
433 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
434 CPPUNIT_ASSERT_EQUAL(nTable3
, nTable2Follow
);
435 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable3Precede
);
439 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSectionInTableInTable4
)
442 createSwDoc("tdf113520.fodt");
443 SwDoc
* pDoc
= getSwDoc();
444 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
445 assertXPath(pXmlDoc
, "/root/page", 3);
446 SwNodeOffset
nPage1LastNode(
447 getXPath(pXmlDoc
, "/root/page[1]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[last()]",
450 CPPUNIT_ASSERT_EQUAL(u
"Section1:P10"_ustr
,
451 pDoc
->GetNodes()[nPage1LastNode
]->GetTextNode()->GetText());
452 SwNodeOffset
nPage3FirstNode(
453 getXPath(pXmlDoc
, "/root/page[3]/body/tab/row/cell[1]/tab/row/cell[1]/section/txt[1]",
456 CPPUNIT_ASSERT_EQUAL(u
"Section1:P23"_ustr
,
457 pDoc
->GetNodes()[nPage3FirstNode
]->GetTextNode()->GetText());
460 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
461 while (pWrtShell
->GetCursor()->Start()->GetNodeIndex() < nPage1LastNode
)
462 pWrtShell
->Down(/*bSelect=*/false);
463 pWrtShell
->EndPara();
464 while (pWrtShell
->GetCursor()->End()->GetNodeIndex() < nPage3FirstNode
)
465 pWrtShell
->Down(/*bSelect=*/true);
466 pWrtShell
->EndPara(/*bSelect=*/true);
467 pWrtShell
->DelLeft();
469 // Assert that the page is removed.
470 pXmlDoc
= parseLayoutDump();
471 // This was 3, page 2 was emptied, but it wasn't removed.
472 assertXPath(pXmlDoc
, "/root/page", 2);
474 // Make sure the outer table frames are linked together properly.
475 sal_uInt32 nTable1
= getXPath(pXmlDoc
, "//page[1]//body/tab", "id").toUInt32();
476 sal_uInt32 nTable1Follow
= getXPath(pXmlDoc
, "//page[1]//body/tab", "follow").toUInt32();
477 sal_uInt32 nTable2
= getXPath(pXmlDoc
, "//page[2]//body/tab", "id").toUInt32();
478 sal_uInt32 nTable2Precede
= getXPath(pXmlDoc
, "//page[2]//body/tab", "precede").toUInt32();
479 CPPUNIT_ASSERT_EQUAL(nTable2
, nTable1Follow
);
480 CPPUNIT_ASSERT_EQUAL(nTable1
, nTable2Precede
);
484 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112160
)
487 // Assert that the A2 cell is on page 1.
488 createSwDoc("tdf112160.fodt");
489 SwDoc
* pDoc
= getSwDoc();
490 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
491 SwNodeOffset
nA2CellNode(getXPath(pXmlDoc
,
492 "/root/page[1]/body/tab/row[2]/cell[1]/section/txt[last()]",
495 CPPUNIT_ASSERT_EQUAL(u
"Table1.A2"_ustr
,
496 pDoc
->GetNodes()[nA2CellNode
]->GetTextNode()->GetText());
498 // Append a new paragraph to the end of the A2 cell.
499 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
500 while (pWrtShell
->GetCursor()->GetPointNode().GetIndex() < nA2CellNode
)
501 pWrtShell
->Down(/*bSelect=*/false);
502 pWrtShell
->EndPara();
503 pWrtShell
->SplitNode();
505 // Assert that after A2 got extended, D2 stays on page 1.
506 pXmlDoc
= parseLayoutDump();
507 sal_uInt32 nD2CellNode
508 = getXPath(pXmlDoc
, "/root/page[1]/body/tab/row[2]/cell[last()]/section/txt[last()]",
511 // This was Table1.C2, Table1.D2 was moved to the next page, unexpected.
512 CPPUNIT_ASSERT_EQUAL(u
"Table1.D2"_ustr
,
513 pDoc
->GetNodes()[SwNodeOffset(nD2CellNode
)]->GetTextNode()->GetText());
517 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf114536
)
519 // This crashed in SwTextFormatter::MergeCharacterBorder() due to a
521 createSwDoc("tdf114536.odt");
524 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testParagraphOfTextRange
)
526 createSwDoc("paragraph-of-text-range.odt");
529 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
530 pWrtShell
->Down(/*bSelect=*/false);
531 CPPUNIT_ASSERT(pWrtShell
->IsCursorInTable());
532 // Enter the section.
533 pWrtShell
->Down(/*bSelect=*/false);
534 CPPUNIT_ASSERT(pWrtShell
->IsDirectlyInSection());
536 // Assert that we get the right paragraph object.
537 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
538 uno::Reference
<text::XTextViewCursorSupplier
> xController(xModel
->getCurrentController(),
540 uno::Reference
<text::XTextRange
> xViewCursor
= xController
->getViewCursor();
541 // This failed as there were no TextParagraph property.
542 auto xParagraph
= getProperty
<uno::Reference
<text::XTextRange
>>(xViewCursor
->getStart(),
543 u
"TextParagraph"_ustr
);
544 CPPUNIT_ASSERT_EQUAL(u
"In section"_ustr
, xParagraph
->getString());
547 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfContents
)
549 createSwDoc("tdf99689.odt");
550 SwDoc
* pDoc
= getSwDoc();
551 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
552 pWrtShell
->GotoNextTOXBase();
553 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
554 pWrtShell
->UpdateTableOf(*pTOXBase
);
555 SwCursorShell
* pShell(pDoc
->GetEditShell());
556 CPPUNIT_ASSERT(pShell
);
557 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
558 SwNodeIndex
aIdx(*pTitleNode
);
560 SwNodes::GoNext(&aIdx
);
562 // skip the first header. No attributes there.
563 // next node should contain superscript
564 SwTextNode
* pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
565 CPPUNIT_ASSERT(pNext
->HasHints());
566 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
567 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
569 // next node should contain subscript
570 pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
571 CPPUNIT_ASSERT(pNext
->HasHints());
572 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
573 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
576 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfFigures
)
578 createSwDoc("tdf99689_figures.odt");
579 SwDoc
* pDoc
= getSwDoc();
580 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
581 pWrtShell
->GotoNextTOXBase();
582 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
583 pWrtShell
->UpdateTableOf(*pTOXBase
);
584 SwCursorShell
* pShell(pDoc
->GetEditShell());
585 CPPUNIT_ASSERT(pShell
);
586 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
587 SwNodeIndex
aIdx(*pTitleNode
);
590 // next node should contain subscript
591 SwTextNode
* pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
592 CPPUNIT_ASSERT(pNext
->HasHints());
593 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
594 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
596 // next node should contain superscript
597 pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
598 CPPUNIT_ASSERT(pNext
->HasHints());
599 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
600 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
603 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf99689TableOfTables
)
605 createSwDoc("tdf99689_tables.odt");
606 SwDoc
* pDoc
= getSwDoc();
607 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
608 pWrtShell
->GotoNextTOXBase();
609 const SwTOXBase
* pTOXBase
= pWrtShell
->GetCurTOX();
610 pWrtShell
->UpdateTableOf(*pTOXBase
);
611 SwCursorShell
* pShell(pDoc
->GetEditShell());
612 CPPUNIT_ASSERT(pShell
);
613 SwTextNode
* pTitleNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
614 SwNodeIndex
aIdx(*pTitleNode
);
617 // next node should contain superscript
618 SwTextNode
* pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
619 CPPUNIT_ASSERT(pNext
->HasHints());
620 sal_uInt16 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
621 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
623 // next node should contain subscript
624 pNext
= static_cast<SwTextNode
*>(SwNodes::GoNext(&aIdx
));
625 CPPUNIT_ASSERT(pNext
->HasHints());
626 nAttrType
= lcl_getAttributeIDFromHints(pNext
->GetSwpHints());
627 CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_CHRATR_ESCAPEMENT
), nAttrType
);
630 // tdf#112448: Fix: take correct line height
632 // When line metrics is not calculated we need to call CalcRealHeight()
633 // before usage of the Height() and GetRealHeight().
634 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf112448
)
636 createSwDoc("tdf112448.odt");
638 // check actual number of line breaks in the paragraph
639 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
640 assertXPath(pXmlDoc
, "/root/page/body/txt/SwParaPortion/SwLineLayout", 2);
643 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113790
)
645 createSwDoc("tdf113790.docx");
646 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
647 // Create the clipboard document.
649 aClipboard
.SetClipBoard(true);
651 // Go to fourth line - to "ABCD" bulleted list item
652 pWrtShell
->Down(/*bSelect=*/false, 4);
653 pWrtShell
->SelPara(nullptr);
654 CPPUNIT_ASSERT_EQUAL(u
"ABCD"_ustr
, pWrtShell
->GetSelText());
655 pWrtShell
->Copy(aClipboard
);
657 // Go down to next-to-last (empty) line above "Title3"
658 pWrtShell
->Down(/*bSelect=*/false, 4);
659 pWrtShell
->Paste(aClipboard
);
661 // Save it as DOCX & load it again
662 saveAndReload(u
"Office Open XML Text"_ustr
);
665 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157937
)
667 createSwDoc("tdf130088.docx");
668 SwDoc
* pDoc
= getSwDoc();
669 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
672 pWrtShell
->SelPara(nullptr);
675 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
676 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
677 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
680 CPPUNIT_ASSERT_MESSAGE(
681 "redlines should be visible",
682 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
684 // cycle case with change tracking
685 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
686 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
688 // This resulted freezing
689 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
692 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157988
)
694 createSwDoc("tdf130088.docx");
695 SwDoc
* pDoc
= getSwDoc();
697 // select the second word
698 dispatchCommand(mxComponent
, u
".uno:GoToNextWord"_ustr
, {});
699 dispatchCommand(mxComponent
, u
".uno:SelectWord"_ustr
, {});
702 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
703 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
704 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
707 CPPUNIT_ASSERT_MESSAGE(
708 "redlines should be visible",
709 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
711 // cycle case with change tracking
713 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
715 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
717 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
719 // This was false (missing revert of the tracked change)
720 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
722 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
724 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
726 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
728 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
730 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
732 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
734 // tdf#141198 cycle case without selection: the word under the cursor
736 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
738 dispatchCommand(mxComponent
, u
".uno:GoRight"_ustr
, {});
740 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
742 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
744 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
746 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodalesSodales"));
748 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
750 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt"));
753 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157667
)
755 createSwDoc("tdf130088.docx");
756 SwDoc
* pDoc
= getSwDoc();
757 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
759 // select the first three words
760 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/true, 25, /*bBasicCall=*/false);
763 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
764 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
765 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
768 CPPUNIT_ASSERT_MESSAGE(
769 "redlines should be visible",
770 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
772 // cycle case with change tracking
774 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
776 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
777 "Integer sodalesSodales tinciduntTincidunt tristique."));
779 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
781 // This was false (missing revert of the tracked change)
782 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
784 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
786 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
787 "Integer sodalesINTEGER SODALES tincidunt tristique."));
789 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
791 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
793 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
795 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
796 "Integer sodalesSodales tinciduntTincidunt tristique."));
798 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
800 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
803 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf158039
)
805 createSwDoc("tdf130088.docx");
806 SwDoc
* pDoc
= getSwDoc();
807 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
809 // select the first sentence
810 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/true, 26, /*bBasicCall=*/false);
813 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
814 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
815 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
818 CPPUNIT_ASSERT_MESSAGE(
819 "redlines should be visible",
820 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
822 // cycle case with change tracking
824 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
826 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
827 "Integer sodalesSodales tinciduntTincidunt tristique."));
829 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
831 // This was false (missing revert of the tracked change)
832 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
834 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
836 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
837 "Integer sodalesINTEGER SODALES tincidunt tristique."));
839 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
841 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
843 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith(
844 "Integer sodalesSodales tinciduntTincidunt tristique."));
846 dispatchCommand(mxComponent
, u
".uno:ChangeCaseRotateCase"_ustr
, {});
848 CPPUNIT_ASSERT(getParagraph(1)->getString().startsWith("Integer sodales tincidunt tristique."));
851 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf108048
)
855 uno::Sequence
<beans::PropertyValue
> aPropertyValues
= comphelper::InitPropertySequence({
856 { "Kind", uno::Any(sal_Int16(3)) },
857 { "TemplateName", uno::Any(u
"Default Page Style"_ustr
) },
858 { "PageNumber", uno::Any(sal_uInt16(6)) }, // Even number to avoid auto-inserted blank page
859 { "PageNumberFilled", uno::Any(true) },
861 dispatchCommand(mxComponent
, u
".uno:InsertBreak"_ustr
, aPropertyValues
);
862 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
863 CPPUNIT_ASSERT_EQUAL(2, getPages());
865 // The inserted page must have page number set to 6
866 uno::Reference
<text::XTextRange
> xPara
= getParagraph(2);
867 sal_uInt16 nPageNumber
= getProperty
<sal_uInt16
>(xPara
, u
"PageNumberOffset"_ustr
);
868 CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), nPageNumber
);
871 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf113481
)
873 createSwDoc("tdf113481-IVS.odt");
874 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
876 // One backspace should completely remove the CJK ideograph variation sequence
877 pWrtShell
->EndPara();
878 // Before: U+8FBA U+E0102. After: empty
879 pWrtShell
->DelLeft();
880 const uno::Reference
<text::XTextRange
> xPara1
= getParagraph(1);
881 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara1
->getString().getLength());
883 // Also variation sequence of weak characters that are treated as CJK script
884 pWrtShell
->Down(false);
885 pWrtShell
->EndPara();
886 // Before: U+4E2D U+2205 U+FE00. After: U+4E2D U+2205
887 pWrtShell
->DelLeft();
888 const uno::Reference
<text::XTextRange
> xPara2
= getParagraph(2);
889 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xPara2
->getString().getLength());
890 CPPUNIT_ASSERT_EQUAL(u
'\x4E2D', xPara2
->getString()[0]);
892 // Also variation sequence of other scripts
893 pWrtShell
->Down(false);
894 pWrtShell
->EndPara();
895 // Before: U+1820 U+180B. After: U+1820
896 pWrtShell
->DelLeft();
897 const uno::Reference
<text::XTextRange
> xPara3
= getParagraph(3);
898 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPara3
->getString().getLength());
901 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115013
)
903 static constexpr OUString
sColumnName(u
"Name with spaces, \"quotes\" and \\backslashes"_ustr
);
905 utl::TempFileNamed
aTempDir(nullptr, true);
906 aTempDir
.EnableKillingFile();
907 const OUString aWorkDir
= aTempDir
.GetURL();
909 //create new writer document
911 SwDoc
* pDoc
= getSwDoc();
914 // Load and register data source
916 = SwDBManager::LoadAndRegisterDataSource(createFileURL(u
"datasource.ods"), &aWorkDir
);
917 CPPUNIT_ASSERT(!sDataSource
.isEmpty());
919 // Insert a new field type for the mailmerge field
921 aDBData
.sDataSource
= sDataSource
;
922 aDBData
.sCommand
= "Sheet1";
923 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
924 CPPUNIT_ASSERT(pWrtShell
);
925 SwDBFieldType
* pFieldType
= static_cast<SwDBFieldType
*>(
926 pWrtShell
->InsertFieldType(SwDBFieldType(pDoc
, sColumnName
, aDBData
)));
927 CPPUNIT_ASSERT(pFieldType
);
929 // Insert the field into document
930 SwDBField
aField(pFieldType
);
931 pWrtShell
->InsertField2(aField
);
933 // Save it as DOCX & load it again
934 saveAndReload(u
"Office Open XML Text"_ustr
);
936 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
937 CPPUNIT_ASSERT(pWrtShell
);
938 SwCursorShell
* pShell(pDoc
->GetEditShell());
939 CPPUNIT_ASSERT(pShell
);
940 SwPaM
* pCursor
= pShell
->GetCursor();
941 CPPUNIT_ASSERT(pCursor
);
943 // Get the field at the beginning of the document
944 SwDBField
* pField
= dynamic_cast<SwDBField
*>(SwCursorShell::GetFieldAtCursor(pCursor
, true));
945 CPPUNIT_ASSERT(pField
);
946 OUString sColumn
= static_cast<SwDBFieldType
*>(pField
->GetTyp())->GetColumnName();
947 // The column name must come correct after round trip
948 CPPUNIT_ASSERT_EQUAL(sColumnName
, sColumn
);
951 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115065
)
953 // In the document, the tables have table style assigned
954 // Source table (first one) has two rows;
955 // destination (second one) has only one row
956 createSwDoc("tdf115065.odt");
957 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
958 CPPUNIT_ASSERT(pWrtShell
);
960 pWrtShell
->GotoTable(u
"Table2"_ustr
);
961 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
962 // Destination point is the middle of the first cell of second table
963 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
965 pWrtShell
->GotoTable(u
"Table1"_ustr
);
966 aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
967 // Source point is the middle of the first cell of first table
968 Point
ptFrom(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
970 pWrtShell
->SelTableCol();
971 // The copy operation (or closing document after that) segfaulted
972 pWrtShell
->Copy(*pWrtShell
, ptFrom
, ptTo
);
975 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf84806_MovingMultipleTableRows
)
977 // Moving of multiple table rows.
978 // Source table (first one) has two rows;
979 // destination (second one) has only one row
980 createSwDoc("tdf115065.odt");
981 SwDoc
* pDoc
= getSwDoc();
982 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
983 CPPUNIT_ASSERT(pWrtShell
);
985 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
986 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
988 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
989 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
990 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
991 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table2"_ustr
));
992 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
994 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName(u
"Table2"_ustr
),
996 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
997 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
1000 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1001 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1003 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1005 pWrtShell
->GotoTable(u
"Table2"_ustr
);
1006 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
1007 // Destination point is the middle of the first cell of second table
1008 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
1010 // Move rows of the first table into the second table
1011 pWrtShell
->GotoTable(u
"Table1"_ustr
);
1012 pWrtShell
->SelTable();
1013 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1014 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1016 // This was 2 tables
1017 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables
->getCount());
1018 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
1020 // Undo results 2 tables
1021 rUndoManager
.Undo();
1022 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
1024 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
1025 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName(u
"Table1"_ustr
),
1027 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName(u
"Table2"_ustr
),
1029 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
1030 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
1032 // FIXME assert with Redo()
1035 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf147181_TrackedMovingOfMultipleTableRows
)
1037 // Tracked moving of multiple table rows.
1038 // Source table (first one) has two rows;
1039 // destination (second one) has only one row
1040 createSwDoc("tdf115065.odt");
1041 SwDoc
* pDoc
= getSwDoc();
1042 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1043 CPPUNIT_ASSERT(pWrtShell
);
1045 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1046 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
1048 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
1049 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1050 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1051 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table2"_ustr
));
1052 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1054 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName(u
"Table2"_ustr
),
1056 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1057 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2
->getRows()->getCount());
1059 // FIXME: doesn't work with empty rows, yet
1060 pWrtShell
->Insert(u
"x"_ustr
);
1061 pWrtShell
->Down(false);
1062 pWrtShell
->Insert(u
"x"_ustr
);
1065 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
1066 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1067 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1070 CPPUNIT_ASSERT_MESSAGE(
1071 "redlines should be visible",
1072 IDocumentRedlineAccess::IsShowChanges(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
1074 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
1076 pWrtShell
->GotoTable(u
"Table2"_ustr
);
1077 SwRect aRect
= pWrtShell
->GetCurrFrame()->getFrameArea();
1078 // Destination point is the middle of the first cell of second table
1079 Point
ptTo(aRect
.Left() + aRect
.Width() / 2, aRect
.Top() + aRect
.Height() / 2);
1081 // Move rows of the first table into the second table
1082 pWrtShell
->GotoTable(u
"Table1"_ustr
);
1083 pWrtShell
->SelTable();
1084 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1085 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1087 // still 2 tables, but the second one has got 3 rows
1088 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables
->getCount());
1089 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1090 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
1092 // accept changes results 1 table (removing moved table)
1093 dispatchCommand(mxComponent
, u
".uno:AcceptAllTrackedChanges"_ustr
, {});
1094 uno::Reference
<container::XIndexAccess
> xTables2(xTablesSupplier
->getTextTables(),
1096 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables2
->getCount());
1097 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getRows()->getCount());
1099 // Undo results 2 tables
1100 rUndoManager
.Undo();
1101 rUndoManager
.Undo();
1102 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables2
->getCount());
1103 uno::Reference
<text::XTextTable
> xTable1b(xTableNames
->getByName(u
"Table1"_ustr
),
1105 uno::Reference
<text::XTextTable
> xTable2b(xTableNames
->getByName(u
"Table2"_ustr
),
1107 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
1108 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
1110 // reject changes results 2 table again, with the original row counts
1111 dispatchCommand(mxComponent
, u
".uno:RejectAllTrackedChanges"_ustr
, {});
1112 uno::Reference
<container::XIndexAccess
> xTables3(xTablesSupplier
->getTextTables(),
1114 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables3
->getCount());
1115 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1b
->getRows()->getCount());
1116 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable2b
->getRows()->getCount());
1119 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157492_TrackedMovingRow
)
1122 SwDoc
* pDoc
= getSwDoc();
1123 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1124 CPPUNIT_ASSERT(pWrtShell
);
1127 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1128 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1130 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1131 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1132 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1133 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1135 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1136 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1138 // fill table with data
1139 SwXTextDocument
* pTextDoc
= getSwTextDoc();
1140 for (int i
= 0; i
< 3; ++i
)
1142 pWrtShell
->Insert(u
"x"_ustr
);
1143 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RIGHT
);
1146 Scheduler::ProcessEventsToIdle();
1148 uno::Reference
<text::XTextRange
> xCellA1(xTable1
->getCellByName(u
"A1"_ustr
), uno::UNO_QUERY
);
1149 xCellA1
->setString(u
"A1"_ustr
);
1150 uno::Reference
<text::XTextRange
> xCellB1(xTable1
->getCellByName(u
"B1"_ustr
), uno::UNO_QUERY
);
1151 xCellB1
->setString(u
"B1"_ustr
);
1152 uno::Reference
<text::XTextRange
> xCellC1(xTable1
->getCellByName(u
"C1"_ustr
), uno::UNO_QUERY
);
1153 xCellC1
->setString(u
"C1"_ustr
);
1155 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1156 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[1]/txt", u
"A1");
1157 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[2]/txt", u
"B1");
1158 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[3]/txt", u
"C1");
1161 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
1162 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1163 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1165 // Move first column of the table before the third column by drag & drop
1166 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1167 SwFrame
* pPage
= pLayout
->Lower();
1168 SwFrame
* pBody
= pPage
->GetLower();
1169 SwFrame
* pTable
= pBody
->GetLower();
1170 SwFrame
* pRow1
= pTable
->GetLower();
1171 SwFrame
* pCellA1
= pRow1
->GetLower();
1172 SwFrame
* pRow3
= pRow1
->GetNext()->GetNext();
1173 SwFrame
* pCellA3
= pRow3
->GetLower();
1174 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1175 const SwRect
& rCellA3Rect
= pCellA3
->getFrameArea();
1176 Point
ptTo(rCellA3Rect
.Left() + rCellA3Rect
.Width() / 2,
1177 rCellA3Rect
.Top() + rCellA3Rect
.Height() / 2);
1178 // select first table row by using the middle point of the left border of row 1
1179 Point
ptRow(rCellA1Rect
.Left() - 5, rCellA1Rect
.Top() + rCellA1Rect
.Height() / 2);
1180 pWrtShell
->SelectTableRowCol(ptRow
);
1182 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1184 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1186 // reject changes results 4 rows again, not 5
1187 dispatchCommand(mxComponent
, u
".uno:RejectAllTrackedChanges"_ustr
, {});
1189 xTableNames
= xTablesSupplier
->getTextTables();
1190 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1191 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName(u
"Table1"_ustr
),
1193 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getColumns()->getCount());
1194 // This was 5 (moving row without change tracking)
1195 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2
->getRows()->getCount());
1198 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf154599_MovingColumn
)
1201 SwDoc
* pDoc
= getSwDoc();
1202 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1203 CPPUNIT_ASSERT(pWrtShell
);
1205 // Create a table with less columns than rows
1206 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1207 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1209 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1210 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1211 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1212 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1214 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1215 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1217 // without redlining
1218 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1219 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1221 // Move first column of the table before the third column by drag & drop
1223 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1224 SwFrame
* pPage
= pLayout
->Lower();
1225 SwFrame
* pBody
= pPage
->GetLower();
1226 SwFrame
* pTable
= pBody
->GetLower();
1227 SwFrame
* pRow1
= pTable
->GetLower();
1228 SwFrame
* pCellA1
= pRow1
->GetLower();
1229 SwFrame
* pCellC1
= pCellA1
->GetNext()->GetNext();
1230 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1231 const SwRect
& rCellC1Rect
= pCellC1
->getFrameArea();
1232 Point
ptTo(rCellC1Rect
.Left() + rCellC1Rect
.Width() / 2,
1233 rCellC1Rect
.Top() + rCellC1Rect
.Height() / 2);
1234 // select first table column by using the middle point of the top border of column A
1235 Point
ptColumn(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1236 pWrtShell
->SelectTableRowCol(ptColumn
);
1238 // This crashed here before the fix.
1239 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1241 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1243 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1244 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1247 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf155846_MovingColumn
)
1250 SwDoc
* pDoc
= getSwDoc();
1251 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1252 CPPUNIT_ASSERT(pWrtShell
);
1255 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1256 (void)&pWrtShell
->InsertTable(TableOpt
, 4, 3);
1258 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1259 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1260 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1261 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1263 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getRows()->getCount());
1264 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable1
->getColumns()->getCount());
1266 // fill table with data
1267 SwXTextDocument
* pTextDoc
= getSwTextDoc();
1268 for (int i
= 0; i
< 4; ++i
)
1270 pWrtShell
->Insert(u
"x"_ustr
);
1271 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_DOWN
);
1274 Scheduler::ProcessEventsToIdle();
1276 uno::Reference
<text::XTextRange
> xCellA1(xTable1
->getCellByName(u
"A1"_ustr
), uno::UNO_QUERY
);
1277 xCellA1
->setString(u
"A1"_ustr
);
1278 uno::Reference
<text::XTextRange
> xCellA2(xTable1
->getCellByName(u
"A2"_ustr
), uno::UNO_QUERY
);
1279 xCellA2
->setString(u
"A2"_ustr
);
1280 uno::Reference
<text::XTextRange
> xCellA3(xTable1
->getCellByName(u
"A3"_ustr
), uno::UNO_QUERY
);
1281 xCellA3
->setString(u
"A3"_ustr
);
1282 uno::Reference
<text::XTextRange
> xCellA4(xTable1
->getCellByName(u
"A4"_ustr
), uno::UNO_QUERY
);
1283 xCellA4
->setString(u
"A4"_ustr
);
1285 xmlDocUniquePtr pXmlDoc
= parseLayoutDump();
1286 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[1]/cell[1]/txt", u
"A1");
1287 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[2]/cell[1]/txt", u
"A2");
1288 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[3]/cell[1]/txt", u
"A3");
1289 assertXPathContent(pXmlDoc
, "/root/page/body/tab/row[4]/cell[1]/txt", u
"A4");
1292 dispatchCommand(mxComponent
, u
".uno:TrackChanges"_ustr
, {});
1293 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1294 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1296 // Move first column of the table before the third column by drag & drop
1297 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1298 SwFrame
* pPage
= pLayout
->Lower();
1299 SwFrame
* pBody
= pPage
->GetLower();
1300 SwFrame
* pTable
= pBody
->GetLower();
1301 SwFrame
* pRow1
= pTable
->GetLower();
1302 SwFrame
* pCellA1
= pRow1
->GetLower();
1303 SwFrame
* pCellC1
= pCellA1
->GetNext()->GetNext();
1304 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1305 const SwRect
& rCellC1Rect
= pCellC1
->getFrameArea();
1306 Point
ptTo(rCellC1Rect
.Left() + rCellC1Rect
.Width() / 2,
1307 rCellC1Rect
.Top() + rCellC1Rect
.Height() / 2);
1308 // select first table column by using the middle point of the top border of column A
1309 Point
ptColumn(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1310 pWrtShell
->SelectTableRowCol(ptColumn
);
1312 // This crashed here before the fix.
1313 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1315 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1317 // reject changes results 3 columns again, not 4
1318 dispatchCommand(mxComponent
, u
".uno:RejectAllTrackedChanges"_ustr
, {});
1320 xTableNames
= xTablesSupplier
->getTextTables();
1321 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1322 uno::Reference
<text::XTextTable
> xTable2(xTableNames
->getByName(u
"Table1"_ustr
),
1324 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable2
->getRows()->getCount());
1325 // This was 4 (moving column without change tracking)
1326 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable2
->getColumns()->getCount());
1329 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf154771_MovingMultipleColumns
)
1332 SwDoc
* pDoc
= getSwDoc();
1333 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1334 CPPUNIT_ASSERT(pWrtShell
);
1336 // Create a table with less columns than rows
1337 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1338 (void)&pWrtShell
->InsertTable(TableOpt
, 5, 4);
1340 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1341 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1342 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1343 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1345 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable1
->getRows()->getCount());
1346 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getColumns()->getCount());
1348 // without redlining
1349 CPPUNIT_ASSERT_MESSAGE("redlining should be off",
1350 !pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
1352 // Move first two columns of the table before column D by drag & drop
1354 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1355 SwFrame
* pPage
= pLayout
->Lower();
1356 SwFrame
* pBody
= pPage
->GetLower();
1357 SwFrame
* pTable
= pBody
->GetLower();
1358 SwFrame
* pRow1
= pTable
->GetLower();
1359 SwFrame
* pCellA1
= pRow1
->GetLower();
1360 SwFrame
* pCellB1
= pCellA1
->GetNext();
1361 SwFrame
* pCellD1
= pCellB1
->GetNext()->GetNext();
1362 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1363 const SwRect
& rCellB1Rect
= pCellB1
->getFrameArea();
1364 const SwRect
& rCellD1Rect
= pCellD1
->getFrameArea();
1365 Point
ptTo(rCellD1Rect
.Left() + rCellD1Rect
.Width() / 2,
1366 rCellD1Rect
.Top() + rCellD1Rect
.Height() / 2);
1367 // select first two table columns by using
1368 // the middle point of the top border of column A
1369 // and middle point of the top border of column B
1370 Point
ptColumnA(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() - 5);
1371 const Point
ptColumnB(rCellB1Rect
.Left() + rCellB1Rect
.Width() / 2, rCellB1Rect
.Top() - 5);
1372 pWrtShell
->SelectTableRowCol(ptColumnA
, &ptColumnB
);
1374 rtl::Reference
<SwTransferable
> xTransfer
= new SwTransferable(*pWrtShell
);
1375 xTransfer
->PrivateDrop(*pWrtShell
, ptTo
, /*bMove=*/true, /*bXSelection=*/true);
1377 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xTable1
->getRows()->getCount());
1378 // This was 5 before the fix (only the first selected column was moved, the
1379 // other ones were copied instead of moving)
1380 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable1
->getColumns()->getCount());
1383 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf44773
)
1385 // allow resizing table rows, if cursor outside the table
1387 SwDoc
* pDoc
= getSwDoc();
1388 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1389 CPPUNIT_ASSERT(pWrtShell
);
1391 // insert an empty paragraph
1392 pWrtShell
->SplitNode();
1395 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1396 (void)&pWrtShell
->InsertTable(TableOpt
, 2, 1);
1398 // the cursor is not inside the table
1399 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1401 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1402 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1403 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1404 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1406 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1407 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable1
->getColumns()->getCount());
1409 Scheduler::ProcessEventsToIdle();
1411 // set table row height by drag & drop
1412 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1414 SwFrame
* pPage
= pLayout
->Lower();
1415 SwFrame
* pBody
= pPage
->GetLower();
1416 SwFrame
* pTable
= pBody
->GetLower()->GetNext();
1417 SwFrame
* pRow1
= pTable
->GetLower();
1418 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1419 SwFrame
* pCellA1
= pRow1
->GetLower();
1420 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1421 auto nRowHeight
= rCellA1Rect
.Height();
1422 // select center of the bottom border of the first table cell
1423 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
);
1424 // double the row height
1425 Point
ptTo(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + 2 * nRowHeight
);
1426 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1427 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1428 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1430 rEditWin
.MouseButtonDown(aClickEvent
);
1431 Point aTo
= rEditWin
.LogicToPixel(ptTo
);
1432 MouseEvent
aMoveEvent(aTo
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1434 TrackingEvent
aTEvt(aMoveEvent
, TrackingEventFlags::Repeat
);
1435 // drag & drop of cell border inside the document (and outside the table)
1436 // still based on the ruler code, use that to simulate dragging
1437 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt
);
1438 TrackingEvent
aTEvt2(aMoveEvent
, TrackingEventFlags::End
);
1439 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt2
);
1440 Scheduler::ProcessEventsToIdle();
1441 rEditWin
.CaptureMouse();
1442 rEditWin
.ReleaseMouse();
1444 // this was 396 (not modified row height previously)
1445 CPPUNIT_ASSERT_GREATER(tools::Long(750), pCellA1
->getFrameArea().Height());
1448 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157833
)
1450 // allow resizing table rows & columns using a minimal hit area
1452 SwDoc
* pDoc
= getSwDoc();
1453 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1454 CPPUNIT_ASSERT(pWrtShell
);
1456 // insert an empty paragraph
1457 pWrtShell
->SplitNode();
1460 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1461 (void)&pWrtShell
->InsertTable(TableOpt
, 2, 1);
1463 // the cursor is not inside the table
1464 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1466 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1467 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1468 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1469 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1471 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1472 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable1
->getColumns()->getCount());
1474 Scheduler::ProcessEventsToIdle();
1476 // set table row height by drag & drop
1477 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1479 SwFrame
* pPage
= pLayout
->Lower();
1480 SwFrame
* pBody
= pPage
->GetLower();
1481 SwFrame
* pTable
= pBody
->GetLower()->GetNext();
1482 SwFrame
* pRow1
= pTable
->GetLower();
1483 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1484 SwFrame
* pCellA1
= pRow1
->GetLower();
1485 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1486 auto nRowHeight
= rCellA1Rect
.Height();
1487 // select center of the bottom border of the first table cell
1488 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
);
1489 // double the row height
1490 Point
ptTo(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + 2 * nRowHeight
);
1491 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1492 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1493 Point
aArea(aFrom
.X(), aFrom
.Y() + 2);
1494 MouseEvent
aClickEvent(aArea
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1496 rEditWin
.MouseButtonDown(aClickEvent
);
1497 Point aTo
= rEditWin
.LogicToPixel(ptTo
);
1498 MouseEvent
aMoveEvent(aTo
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1500 TrackingEvent
aTEvt(aMoveEvent
, TrackingEventFlags::Repeat
);
1501 // drag & drop of cell border inside the document (and outside the table)
1502 // still based on the ruler code, use that to simulate dragging
1503 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt
);
1504 TrackingEvent
aTEvt2(aMoveEvent
, TrackingEventFlags::End
);
1505 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt2
);
1506 Scheduler::ProcessEventsToIdle();
1507 rEditWin
.CaptureMouse();
1508 rEditWin
.ReleaseMouse();
1510 // this was 396 (not modified row height previously, when clicking only in a 2-pixel distance
1511 // from the center of the border)
1512 CPPUNIT_ASSERT_GREATER(tools::Long(750), pCellA1
->getFrameArea().Height());
1515 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf155692
)
1517 // allow resizing table rows & columns using a normal hit area
1519 SwDoc
* pDoc
= getSwDoc();
1520 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1521 CPPUNIT_ASSERT(pWrtShell
);
1523 // insert an empty paragraph
1524 pWrtShell
->SplitNode();
1527 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
1528 (void)&pWrtShell
->InsertTable(TableOpt
, 2, 1);
1530 // the cursor is not inside the table
1531 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1533 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
1534 uno::Reference
<container::XNameAccess
> xTableNames
= xTablesSupplier
->getTextTables();
1535 CPPUNIT_ASSERT(xTableNames
->hasByName(u
"Table1"_ustr
));
1536 uno::Reference
<text::XTextTable
> xTable1(xTableNames
->getByName(u
"Table1"_ustr
),
1538 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable1
->getRows()->getCount());
1539 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable1
->getColumns()->getCount());
1541 Scheduler::ProcessEventsToIdle();
1543 // set table row height by drag & drop
1544 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1546 SwFrame
* pPage
= pLayout
->Lower();
1547 SwFrame
* pBody
= pPage
->GetLower();
1548 SwFrame
* pTable
= pBody
->GetLower()->GetNext();
1549 SwFrame
* pRow1
= pTable
->GetLower();
1550 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1551 SwFrame
* pCellA1
= pRow1
->GetLower();
1552 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1553 auto nRowHeight
= rCellA1Rect
.Height();
1554 // select center of the bottom border of the first table cell
1555 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
);
1556 // double the row height
1557 Point
ptTo(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + 2 * nRowHeight
);
1558 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1559 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1560 Point
aArea(aFrom
.X(), aFrom
.Y() + 5);
1561 MouseEvent
aClickEvent(aArea
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1563 rEditWin
.MouseButtonDown(aClickEvent
);
1564 Point aTo
= rEditWin
.LogicToPixel(ptTo
);
1565 MouseEvent
aMoveEvent(aTo
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1567 TrackingEvent
aTEvt(aMoveEvent
, TrackingEventFlags::Repeat
);
1568 // drag & drop of cell border inside the document (and outside the table)
1569 // still based on the ruler code, use that to simulate dragging
1570 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt
);
1571 TrackingEvent
aTEvt2(aMoveEvent
, TrackingEventFlags::End
);
1572 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt2
);
1573 Scheduler::ProcessEventsToIdle();
1574 rEditWin
.CaptureMouse();
1575 rEditWin
.ReleaseMouse();
1577 // this was 396 (not modified row height previously, when clicking only in a 5-pixel distance
1578 // from the center of the border)
1579 CPPUNIT_ASSERT_GREATER(tools::Long(750), pCellA1
->getFrameArea().Height());
1582 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf160842
)
1584 createSwDoc("tdf160842.fodt");
1585 SwDoc
* pDoc
= getSwDoc();
1586 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1587 CPPUNIT_ASSERT(pWrtShell
);
1588 // the cursor is not in the table
1589 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1591 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1592 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1593 CPPUNIT_ASSERT(pPage
);
1594 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1595 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1596 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1597 CPPUNIT_ASSERT(pPageFly
);
1598 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1599 CPPUNIT_ASSERT(pTable
);
1600 auto pRow2
= pTable
->GetLower()->GetNext();
1601 CPPUNIT_ASSERT(pRow2
->IsRowFrame());
1602 auto pCellA2
= pRow2
->GetLower();
1603 CPPUNIT_ASSERT(pCellA2
);
1604 const SwRect
& rCellA2Rect
= pCellA2
->getFrameArea();
1605 auto nRowHeight
= rCellA2Rect
.Height();
1606 // select center of the bottom cell
1607 Point
ptFrom(rCellA2Rect
.Left() + rCellA2Rect
.Width() / 2, rCellA2Rect
.Top() + nRowHeight
/ 2);
1608 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1609 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1610 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1611 rEditWin
.MouseButtonDown(aClickEvent
);
1612 rEditWin
.MouseButtonUp(aClickEvent
);
1614 // the cursor is in the table
1615 CPPUNIT_ASSERT(pWrtShell
->IsCursorInTable());
1618 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf160836
)
1620 createSwDoc("tdf160842.fodt");
1621 SwDoc
* pDoc
= getSwDoc();
1622 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1623 CPPUNIT_ASSERT(pWrtShell
);
1625 // set table row height by drag & drop at images cropped by the fixed row height
1626 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1627 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1628 CPPUNIT_ASSERT(pPage
);
1629 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1630 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1631 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1632 CPPUNIT_ASSERT(pPageFly
);
1633 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1634 CPPUNIT_ASSERT(pTable
);
1635 auto pRow1
= pTable
->GetLower();
1636 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1637 auto pCellA1
= pRow1
->GetLower();
1638 CPPUNIT_ASSERT(pCellA1
);
1639 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1640 auto nRowHeight
= rCellA1Rect
.Height();
1641 // select center of the bottom border of the first table cell
1642 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
);
1643 // halve the row height
1644 Point
ptTo(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + 0.5 * nRowHeight
);
1645 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1646 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1647 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1649 rEditWin
.MouseButtonDown(aClickEvent
);
1650 Point aTo
= rEditWin
.LogicToPixel(ptTo
);
1651 MouseEvent
aMoveEvent(aTo
, 1, MouseEventModifiers::SIMPLECLICK
| MouseEventModifiers::SELECT
,
1653 TrackingEvent
aTEvt(aMoveEvent
, TrackingEventFlags::Repeat
);
1654 // drag & drop of cell border inside the document (and outside the table)
1655 // still based on the ruler code, use that to simulate dragging
1656 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt
);
1657 TrackingEvent
aTEvt2(aMoveEvent
, TrackingEventFlags::End
);
1658 getSwDocShell()->GetView()->GetVRuler().Tracking(aTEvt2
);
1659 Scheduler::ProcessEventsToIdle();
1660 rEditWin
.CaptureMouse();
1661 rEditWin
.ReleaseMouse();
1663 // this was 3910 (not modified row height previously)
1664 CPPUNIT_ASSERT_LESS(tools::Long(2000), pCellA1
->getFrameArea().Height());
1667 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf161261
)
1669 createSwDoc("tdf160842.fodt");
1670 SwDoc
* pDoc
= getSwDoc();
1671 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1672 CPPUNIT_ASSERT(pWrtShell
);
1673 // the cursor is not in the table
1674 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1676 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1677 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1678 CPPUNIT_ASSERT(pPage
);
1679 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1680 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1681 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1682 CPPUNIT_ASSERT(pPageFly
);
1683 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1684 CPPUNIT_ASSERT(pTable
);
1685 auto pRow1
= pTable
->GetLower();
1686 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1687 auto pCellA1
= pRow1
->GetLower();
1688 CPPUNIT_ASSERT(pCellA1
);
1689 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1690 auto nRowHeight
= rCellA1Rect
.Height();
1692 // select image by clicking on it at the center of the upper cell
1693 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
/ 2);
1694 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1695 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1696 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1697 rEditWin
.MouseButtonDown(aClickEvent
);
1698 rEditWin
.MouseButtonUp(aClickEvent
);
1700 // Then make sure that the image is selected:
1701 SelectionType eType
= pWrtShell
->GetSelectionType();
1702 CPPUNIT_ASSERT_EQUAL(SelectionType::Graphic
, eType
);
1704 uno::Reference
<drawing::XShape
> xShape
= getShape(2);
1705 CPPUNIT_ASSERT(xShape
.is());
1707 // zoom image by drag & drop using right bottom handle of the image
1708 const SwRect
& rSelRect
= pWrtShell
->GetAnyCurRect(CurRectType::Frame
);
1709 Point
ptFromHandle(rSelRect
.Right(), rSelRect
.Bottom());
1710 Point aFromHandle
= rEditWin
.LogicToPixel(ptFromHandle
);
1711 Point
ptTo(rSelRect
.Left() + rSelRect
.Width() * 1.5, rSelRect
.Top() + rSelRect
.Height() * 1.5);
1712 Point aTo
= rEditWin
.LogicToPixel(ptTo
);
1713 MouseEvent
aClickEvent2(aFromHandle
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1714 rEditWin
.MouseButtonDown(aClickEvent2
);
1715 MouseEvent
aClickEvent3(aTo
, 0, MouseEventModifiers::SIMPLEMOVE
, MOUSE_LEFT
);
1716 rEditWin
.MouseMove(aClickEvent3
);
1717 rEditWin
.MouseMove(aClickEvent3
);
1718 MouseEvent
aClickEvent4(aTo
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1719 rEditWin
.MouseButtonUp(aClickEvent4
);
1720 Scheduler::ProcessEventsToIdle();
1722 // Make sure image is greater than before, instead of minimizing it to the cell size
1723 // This was 8707 and 6509
1724 CPPUNIT_ASSERT_GREATER(sal_Int32(10000), xShape
->getSize().Width
);
1725 CPPUNIT_ASSERT_GREATER(sal_Int32(8000), xShape
->getSize().Height
);
1728 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf161332
)
1730 createSwDoc("tdf160842.fodt");
1731 SwDoc
* pDoc
= getSwDoc();
1732 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1733 CPPUNIT_ASSERT(pWrtShell
);
1734 // the cursor is not in the table
1735 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1737 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1738 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1739 CPPUNIT_ASSERT(pPage
);
1740 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1741 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1742 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1743 CPPUNIT_ASSERT(pPageFly
);
1744 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1745 CPPUNIT_ASSERT(pTable
);
1746 auto pRow1
= pTable
->GetLower();
1747 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1748 auto pCellA1
= pRow1
->GetLower();
1749 CPPUNIT_ASSERT(pCellA1
);
1750 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1751 auto nRowHeight
= rCellA1Rect
.Height();
1753 // select text frame by clicking on it at the right side of the upper cell
1754 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width(), rCellA1Rect
.Top() + nRowHeight
/ 2);
1755 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1756 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1757 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1758 rEditWin
.MouseButtonDown(aClickEvent
);
1759 rEditWin
.MouseButtonUp(aClickEvent
);
1761 // Then make sure that the text frame is selected:
1762 SelectionType eType
= pWrtShell
->GetSelectionType();
1763 // This was false (SelectionType::Graphic)
1764 CPPUNIT_ASSERT_EQUAL(SelectionType::Frame
, eType
);
1767 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
1769 // select text frame by clicking on it at the right side of the bottom cell
1770 auto pRow2
= pRow1
->GetNext();
1771 CPPUNIT_ASSERT(pRow2
->IsRowFrame());
1772 auto pCellA2
= pRow2
->GetLower();
1773 CPPUNIT_ASSERT(pCellA2
);
1774 const SwRect
& rCellA2Rect
= pCellA2
->getFrameArea();
1775 auto nRow2Height
= rCellA2Rect
.Height();
1776 Point
ptFrom2(rCellA2Rect
.Left() + rCellA2Rect
.Width(), rCellA2Rect
.Top() + nRow2Height
/ 2);
1777 Point aFrom2
= rEditWin
.LogicToPixel(ptFrom2
);
1778 MouseEvent
aClickEvent2(aFrom2
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1779 rEditWin
.MouseButtonDown(aClickEvent2
);
1780 rEditWin
.MouseButtonUp(aClickEvent2
);
1782 // Then make sure that the text frame is selected:
1783 SelectionType eType2
= pWrtShell
->GetSelectionType();
1784 // This was false (SelectionType::Graphic)
1785 CPPUNIT_ASSERT_EQUAL(SelectionType::Frame
, eType2
);
1788 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf161426
)
1790 createSwDoc("tdf161426.fodt");
1791 SwDoc
* pDoc
= getSwDoc();
1792 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1793 CPPUNIT_ASSERT(pWrtShell
);
1794 // the cursor is not in the table
1795 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1797 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1798 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1799 CPPUNIT_ASSERT(pPage
);
1800 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1801 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1802 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1803 CPPUNIT_ASSERT(pPageFly
);
1804 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1805 CPPUNIT_ASSERT(pTable
);
1806 auto pRow1
= pTable
->GetLower();
1807 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1808 auto pCellA1
= pRow1
->GetLower();
1809 CPPUNIT_ASSERT(pCellA1
);
1810 auto pCellB1
= pCellA1
->GetNext();
1811 const SwRect
& rCellB1Rect
= pCellB1
->getFrameArea();
1812 auto nRowHeight
= rCellB1Rect
.Height();
1814 // select text frame by clicking on it at the right side of the upper right cell
1815 Point
ptFrom(rCellB1Rect
.Left() + rCellB1Rect
.Width(), rCellB1Rect
.Top() + nRowHeight
/ 2);
1816 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1817 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1818 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1819 rEditWin
.MouseButtonDown(aClickEvent
);
1820 rEditWin
.MouseButtonUp(aClickEvent
);
1822 // Then make sure that the text frame is selected:
1823 SelectionType eType
= pWrtShell
->GetSelectionType();
1824 CPPUNIT_ASSERT_EQUAL(SelectionType::Frame
, eType
);
1827 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
1829 // select text frame by clicking on it at the right side of the bottom right cell
1830 auto pRow2
= pRow1
->GetNext();
1831 CPPUNIT_ASSERT(pRow2
->IsRowFrame());
1832 auto pCellA2
= pRow2
->GetLower();
1833 CPPUNIT_ASSERT(pCellA2
);
1834 auto pCellB2
= pCellA2
->GetNext();
1835 CPPUNIT_ASSERT(pCellB2
);
1836 const SwRect
& rCellB2Rect
= pCellB2
->getFrameArea();
1837 auto nRow2Height
= rCellB2Rect
.Height();
1838 Point
ptFrom2(rCellB2Rect
.Left() + rCellB2Rect
.Width(), rCellB2Rect
.Top() + nRow2Height
/ 2);
1839 Point aFrom2
= rEditWin
.LogicToPixel(ptFrom2
);
1840 MouseEvent
aClickEvent2(aFrom2
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1841 rEditWin
.MouseButtonDown(aClickEvent2
);
1842 rEditWin
.MouseButtonUp(aClickEvent2
);
1844 // Then make sure that the text frame is selected:
1845 SelectionType eType2
= pWrtShell
->GetSelectionType();
1846 CPPUNIT_ASSERT_EQUAL(SelectionType::Frame
, eType2
);
1849 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf161426_content
)
1851 createSwDoc("tdf161426.fodt");
1852 SwDoc
* pDoc
= getSwDoc();
1853 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1854 CPPUNIT_ASSERT(pWrtShell
);
1855 // the cursor is not in the table
1856 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1858 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1859 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1860 CPPUNIT_ASSERT(pPage
);
1861 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1862 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1863 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1864 CPPUNIT_ASSERT(pPageFly
);
1865 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1866 CPPUNIT_ASSERT(pTable
);
1867 auto pRow1
= pTable
->GetLower();
1868 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1869 auto pCellA1
= pRow1
->GetLower();
1870 CPPUNIT_ASSERT(pCellA1
);
1871 auto pCellB1
= pCellA1
->GetNext();
1872 const SwRect
& rCellB1Rect
= pCellB1
->getFrameArea();
1873 auto nRowHeight
= rCellB1Rect
.Height();
1875 // select content of the B1 by clicking on the center of it
1876 Point
ptFrom(rCellB1Rect
.Left() + rCellB1Rect
.Width() / 2, rCellB1Rect
.Top() + nRowHeight
/ 2);
1877 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1878 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1879 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1880 rEditWin
.MouseButtonDown(aClickEvent
);
1881 rEditWin
.MouseButtonUp(aClickEvent
);
1883 // Then make sure that the cursor in the table:
1884 SelectionType eType2
= pWrtShell
->GetSelectionType();
1886 bool bCursorInTable
= eType2
== (SelectionType::Text
| SelectionType::Table
);
1887 CPPUNIT_ASSERT(bCursorInTable
);
1889 // select content of the B2 by clicking on the center of it
1890 auto pRow2
= pRow1
->GetNext();
1891 CPPUNIT_ASSERT(pRow2
->IsRowFrame());
1892 auto pCellA2
= pRow2
->GetLower();
1893 CPPUNIT_ASSERT(pCellA2
);
1894 auto pCellB2
= pCellA2
->GetNext();
1895 CPPUNIT_ASSERT(pCellB2
);
1896 const SwRect
& rCellB2Rect
= pCellB2
->getFrameArea();
1897 auto nRow2Height
= rCellB2Rect
.Height();
1898 Point
ptFrom2(rCellB2Rect
.Left() + rCellB2Rect
.Width() / 2,
1899 rCellB2Rect
.Top() + nRow2Height
/ 2);
1900 Point aFrom2
= rEditWin
.LogicToPixel(ptFrom2
);
1901 MouseEvent
aClickEvent2(aFrom2
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1902 rEditWin
.MouseButtonDown(aClickEvent2
);
1903 rEditWin
.MouseButtonUp(aClickEvent2
);
1905 // Then make sure that the cursor in the table:
1906 SelectionType eType3
= pWrtShell
->GetSelectionType();
1908 bCursorInTable
= eType3
== (SelectionType::Text
| SelectionType::Table
);
1909 CPPUNIT_ASSERT(bCursorInTable
);
1911 // select content of the A2 by clicking on the center of it
1912 const SwRect
& rCellA2Rect
= pCellA2
->getFrameArea();
1913 Point
ptFrom3(rCellA2Rect
.Left() + rCellA2Rect
.Width() / 2,
1914 rCellA2Rect
.Top() + nRow2Height
/ 2);
1915 Point aFrom3
= rEditWin
.LogicToPixel(ptFrom3
);
1916 MouseEvent
aClickEvent3(aFrom3
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1917 rEditWin
.MouseButtonDown(aClickEvent3
);
1918 rEditWin
.MouseButtonUp(aClickEvent3
);
1920 // Then make sure that the cursor in the table:
1921 SelectionType eType4
= pWrtShell
->GetSelectionType();
1923 bCursorInTable
= eType4
== (SelectionType::Text
| SelectionType::Table
);
1924 CPPUNIT_ASSERT(bCursorInTable
);
1926 // select content of the A1 by clicking on the center of it
1927 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1928 auto nRow1Height
= rCellA1Rect
.Height();
1929 Point
ptFrom4(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2,
1930 rCellA1Rect
.Top() + nRow1Height
/ 2);
1931 Point aFrom4
= rEditWin
.LogicToPixel(ptFrom4
);
1932 MouseEvent
aClickEvent4(aFrom4
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1933 rEditWin
.MouseButtonDown(aClickEvent4
);
1934 rEditWin
.MouseButtonUp(aClickEvent4
);
1936 // Then make sure that the text frame is selected:
1937 SelectionType eType5
= pWrtShell
->GetSelectionType();
1938 CPPUNIT_ASSERT_EQUAL(SelectionType::Graphic
, eType5
);
1941 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf161360
)
1943 createSwDoc("tdf160842.fodt");
1944 SwDoc
* pDoc
= getSwDoc();
1945 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
1946 CPPUNIT_ASSERT(pWrtShell
);
1947 // the cursor is not in the table
1948 CPPUNIT_ASSERT(!pWrtShell
->IsCursorInTable());
1950 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
1951 auto pPage
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
1952 CPPUNIT_ASSERT(pPage
);
1953 const SwSortedObjs
& rPageObjs
= *pPage
->GetSortedObjs();
1954 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs
.size());
1955 auto pPageFly
= dynamic_cast<SwFlyAtContentFrame
*>(rPageObjs
[0]);
1956 CPPUNIT_ASSERT(pPageFly
);
1957 auto pTable
= dynamic_cast<SwTabFrame
*>(pPageFly
->GetLower());
1958 CPPUNIT_ASSERT(pTable
);
1959 auto pRow1
= pTable
->GetLower();
1960 CPPUNIT_ASSERT(pRow1
->IsRowFrame());
1961 auto pCellA1
= pRow1
->GetLower();
1962 CPPUNIT_ASSERT(pCellA1
);
1963 const SwRect
& rCellA1Rect
= pCellA1
->getFrameArea();
1964 auto nRowHeight
= rCellA1Rect
.Height();
1966 // select image by clicking on it at the center of the upper cell
1967 Point
ptFrom(rCellA1Rect
.Left() + rCellA1Rect
.Width() / 2, rCellA1Rect
.Top() + nRowHeight
/ 2);
1968 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
1969 Point aFrom
= rEditWin
.LogicToPixel(ptFrom
);
1970 MouseEvent
aClickEvent(aFrom
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
);
1971 rEditWin
.MouseButtonDown(aClickEvent
);
1972 rEditWin
.MouseButtonUp(aClickEvent
);
1974 // Then make sure that the image is selected:
1975 SelectionType eType
= pWrtShell
->GetSelectionType();
1976 CPPUNIT_ASSERT_EQUAL(SelectionType::Graphic
, eType
);
1978 // select the text frame instead of the image
1979 // by pressing Escape
1980 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
1982 // Then make sure that the cursor in the table:
1983 SelectionType eType2
= pWrtShell
->GetSelectionType();
1984 // This was false (only SelectionType::Text)
1985 bool bCursorInTable
= eType2
== (SelectionType::Text
| SelectionType::Table
);
1986 CPPUNIT_ASSERT(bCursorInTable
);
1988 // select the text frame by pressing Escape again
1989 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
1991 eType2
= pWrtShell
->GetSelectionType();
1992 CPPUNIT_ASSERT_EQUAL(SelectionType::Frame
, eType2
);
1994 // deselect the text frame by pressing Escape again
1995 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
1997 eType2
= pWrtShell
->GetSelectionType();
1998 // The text cursor is after the floating table
1999 CPPUNIT_ASSERT_EQUAL(SelectionType::Text
, eType2
);
2002 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157533
)
2004 // load a table with objects positioned at beginning of text lines
2005 createSwDoc("tdf157533.fodt");
2006 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2007 CPPUNIT_ASSERT(pWrtShell
);
2008 auto pShell
= getSwDocShell()->GetFEShell();
2009 CPPUNIT_ASSERT(pShell
);
2011 auto xModel
= mxComponent
.queryThrow
<frame::XModel
>();
2012 uno::Reference
<drawing::XShape
> xShape(getShapeByName(u
"Objet2"));
2013 uno::Reference
<view::XSelectionSupplier
> xCtrl(xModel
->getCurrentController(), uno::UNO_QUERY
);
2014 xCtrl
->select(uno::Any(xShape
));
2016 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
2018 // Then make sure that the cursor in the table:
2019 SelectionType eType2
= pWrtShell
->GetSelectionType();
2020 // This was false (only SelectionType::Text)
2021 bool bCursorInTable
= eType2
== (SelectionType::Text
| SelectionType::Table
);
2022 CPPUNIT_ASSERT(bCursorInTable
);
2024 SwTextNode
* pTextNode
= pWrtShell
->GetCursor()->GetPointNode().GetTextNode();
2025 // This was false (not in the same paragraph and cell)
2026 CPPUNIT_ASSERT(pTextNode
->GetText().indexOf("and the second formula") > -1);
2028 uno::Reference
<drawing::XShape
> xShape2(getShapeByName(u
"Objet11"));
2029 xCtrl
->select(uno::Any(xShape2
));
2031 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
2033 SwTextNode
* pTextNode2
= pWrtShell
->GetCursor()->GetPointNode().GetTextNode();
2034 // This was false (lost text cursor inside the frame of the formula)
2035 CPPUNIT_ASSERT(pTextNode2
->GetTableBox());
2036 SwTableNode
* pTableNode
= pWrtShell
->GetCursor()->GetPointNode().FindTableNode();
2037 SwTable
& rTable
= pTableNode
->GetTable();
2038 // cursor in the same cell
2039 bool bSameBox
= pTextNode2
->GetTableBox() == rTable
.GetTableBox(u
"A1"_ustr
);
2040 CPPUNIT_ASSERT(bSameBox
);
2042 uno::Reference
<drawing::XShape
> xShape3(getShapeByName(u
"Objet10"));
2043 xCtrl
->select(uno::Any(xShape3
));
2045 dispatchCommand(mxComponent
, u
".uno:Escape"_ustr
, {});
2047 SwTextNode
* pTextNode3
= pWrtShell
->GetCursor()->GetPointNode().GetTextNode();
2048 // This was false (lost text cursor inside the frame of the formula)
2049 CPPUNIT_ASSERT(pTextNode3
->GetTableBox());
2050 // cursor in the same cell
2051 bSameBox
= pTextNode3
->GetTableBox() == rTable
.GetTableBox(u
"B1"_ustr
);
2052 CPPUNIT_ASSERT(bSameBox
);
2055 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf115132
)
2058 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2059 CPPUNIT_ASSERT(pWrtShell
);
2061 std::vector
<OUString
> vTestTableNames
;
2063 // Create an empty paragraph that will separate first table from the rest
2064 pWrtShell
->SplitNode();
2065 pWrtShell
->StartOfSection();
2066 // Create a table at the start of document body
2067 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
2068 const SwTable
* pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
2069 const SwTableFormat
* pFormat
= pTable
->GetFrameFormat();
2070 CPPUNIT_ASSERT(pFormat
);
2071 vTestTableNames
.push_back(pFormat
->GetName());
2072 pWrtShell
->EndOfSection();
2073 // Create a table after a paragraph
2074 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
2075 pFormat
= pTable
->GetFrameFormat();
2076 CPPUNIT_ASSERT(pFormat
);
2077 vTestTableNames
.push_back(pFormat
->GetName());
2078 // Create a table immediately after the previous
2079 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
2080 pFormat
= pTable
->GetFrameFormat();
2081 CPPUNIT_ASSERT(pFormat
);
2082 vTestTableNames
.push_back(pFormat
->GetName());
2083 // Create a nested table in the middle of last row
2084 pWrtShell
->GotoTable(vTestTableNames
.back());
2085 for (int i
= 0; i
< 4; ++i
)
2086 pWrtShell
->GoNextCell(false);
2087 pTable
= &pWrtShell
->InsertTable(TableOpt
, 2, 3);
2088 pFormat
= pTable
->GetFrameFormat();
2089 CPPUNIT_ASSERT(pFormat
);
2090 vTestTableNames
.push_back(pFormat
->GetName());
2092 // Now check that in any cell in all tables we don't go out of a cell
2093 // using Delete or Backspace. We test cases when a table is the first node;
2094 // when we are in a first/middle/last cell in a row; when there's a paragraph
2095 // before/after this cell; when there's another table before/after this cell;
2097 for (const auto& rTableName
: vTestTableNames
)
2099 pWrtShell
->GotoTable(rTableName
);
2102 const SwStartNode
* pNd
= pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode();
2103 pWrtShell
->DelRight();
2104 CPPUNIT_ASSERT_EQUAL(pNd
,
2105 pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode());
2106 pWrtShell
->DelLeft();
2107 CPPUNIT_ASSERT_EQUAL(pNd
,
2108 pWrtShell
->GetCursor()->GetPointNode().FindTableBoxStartNode());
2109 } while (pWrtShell
->GoNextCell(false));
2113 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testXDrawPagesSupplier
)
2116 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
2117 CPPUNIT_ASSERT_MESSAGE("XDrawPagesSupplier interface is unavailable", xDrawPagesSupplier
.is());
2118 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
2119 CPPUNIT_ASSERT(xDrawPages
.is());
2120 CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be only a single DrawPage in Writer documents",
2121 sal_Int32(1), xDrawPages
->getCount());
2122 uno::Any aDrawPage
= xDrawPages
->getByIndex(0);
2123 uno::Reference
<drawing::XDrawPage
> xDrawPageFromXDrawPages(aDrawPage
, uno::UNO_QUERY
);
2124 CPPUNIT_ASSERT(xDrawPageFromXDrawPages
.is());
2126 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
2127 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
2128 CPPUNIT_ASSERT_EQUAL_MESSAGE(
2129 "The DrawPage accessed using XDrawPages must be the same as using XDrawPageSupplier",
2130 xDrawPage
.get(), xDrawPageFromXDrawPages
.get());
2133 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116403
)
2135 createSwDoc("tdf116403-considerborders.odt");
2136 // Check that before ToX update, the tab stop position is the old one
2137 uno::Reference
<text::XTextRange
> xParagraph
= getParagraph(2, u
"1\t1"_ustr
);
2138 auto aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, u
"ParaTabStops"_ustr
);
2139 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
2140 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(17000), aTabs
[0].Position
);
2142 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2143 const SwTOXBase
* pTOX
= pWrtShell
->GetTOX(0);
2144 CPPUNIT_ASSERT(pTOX
);
2145 pWrtShell
->UpdateTableOf(*pTOX
);
2147 xParagraph
= getParagraph(2, u
"1\t1"_ustr
);
2148 aTabs
= getProperty
<uno::Sequence
<style::TabStop
>>(xParagraph
, u
"ParaTabStops"_ustr
);
2149 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(1), aTabs
.getLength());
2150 // This was still 17000, refreshing ToX didn't take borders spacings and widths into account
2151 CPPUNIT_ASSERT_EQUAL_MESSAGE("Page borders must be considered for right-aligned tabstop",
2152 static_cast<sal_Int32
>(17000 - 2 * 500 - 2 * 1 - 1),
2156 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testHtmlCopyImages
)
2158 // Load a document with an image.
2159 createSwDoc("image.odt");
2160 SwDoc
* pDoc
= getSwDoc();
2162 // Trigger the copy part of HTML copy&paste.
2163 WriterRef xWrt
= new SwHTMLWriter(/*rBaseURL=*/OUString());
2164 CPPUNIT_ASSERT(xWrt
.is());
2166 xWrt
->m_bWriteClipboardDoc
= true;
2167 xWrt
->m_bWriteOnlyFirstTable
= false;
2168 xWrt
->SetShowProgress(false);
2170 SvFileStream
aStream(maTempFile
.GetURL(), StreamMode::WRITE
| StreamMode::TRUNC
);
2171 SwWriter
aWrt(aStream
, *pDoc
);
2174 htmlDocUniquePtr pHtmlDoc
= parseHtml(maTempFile
);
2175 CPPUNIT_ASSERT(pHtmlDoc
);
2177 // This failed, image was lost during HTML copy.
2178 OUString aImage
= getXPath(pHtmlDoc
, "/html/body/p/img", "src");
2179 // Also make sure that the image is not embedded (e.g. Word doesn't handle
2180 // embedded images).
2181 CPPUNIT_ASSERT(aImage
.startsWith("file:///"));
2184 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf116789
)
2186 createSwDoc("tdf116789.fodt");
2187 uno::Reference
<text::XBookmarksSupplier
> xBookmarksSupplier(mxComponent
, uno::UNO_QUERY
);
2188 uno::Reference
<text::XText
> xText1
;
2189 uno::Reference
<text::XText
> xText2
;
2191 uno::Reference
<text::XTextContent
> xBookmark(
2192 xBookmarksSupplier
->getBookmarks()->getByName(u
"Bookmark 1"_ustr
), uno::UNO_QUERY
);
2193 xText1
= xBookmark
->getAnchor()->getText();
2196 uno::Reference
<text::XTextContent
> xBookmark(
2197 xBookmarksSupplier
->getBookmarks()->getByName(u
"Bookmark 1"_ustr
), uno::UNO_QUERY
);
2198 xText2
= xBookmark
->getAnchor()->getText();
2200 // This failed, we got two different SwXCell for the same bookmark anchor text.
2201 CPPUNIT_ASSERT_EQUAL(xText1
, xText2
);
2204 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf91801
)
2206 // Tests calculation with several user field variables without prior user fields
2207 createSwDoc("tdf91801.fodt");
2208 uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(1), uno::UNO_QUERY
);
2209 uno::Reference
<table::XCell
> xCell(xTable
->getCellByName(u
"A1"_ustr
));
2210 CPPUNIT_ASSERT_EQUAL(555.0, xCell
->getValue());
2213 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf51223
)
2216 SwDoc
* pDoc
= getSwDoc();
2217 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2218 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
2219 SwNodeOffset nIndex
= pWrtShell
->GetCursor()->GetPointNode().GetIndex();
2220 pWrtShell
->Insert(u
"i"_ustr
);
2221 pWrtShell
->SplitNode(true);
2222 CPPUNIT_ASSERT_EQUAL(u
"I"_ustr
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
2223 rUndoManager
.Undo();
2224 CPPUNIT_ASSERT_EQUAL(u
"i"_ustr
, static_cast<SwTextNode
*>(pDoc
->GetNodes()[nIndex
])->GetText());
2227 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testFontEmbedding
)
2229 #if HAVE_MORE_FONTS && !defined(MACOSX)
2230 createSwDoc("testFontEmbedding.odt");
2232 OString
aContentBaseXpath("/office:document-content/office:font-face-decls"_ostr
);
2233 OString
aSettingsBaseXpath(
2234 "/office:document-settings/office:settings/config:config-item-set"_ostr
);
2236 xmlDocUniquePtr pXmlDoc
;
2238 // Get document settings
2239 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY_THROW
);
2240 uno::Reference
<beans::XPropertySet
> xProps(
2241 xFactory
->createInstance(u
"com.sun.star.document.Settings"_ustr
), uno::UNO_QUERY_THROW
);
2243 // Check font embedding state
2244 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue(u
"EmbedFonts"_ustr
).get
<bool>());
2245 CPPUNIT_ASSERT_EQUAL(false, xProps
->getPropertyValue(u
"EmbedOnlyUsedFonts"_ustr
).get
<bool>());
2246 // Font scripts should be enabled by default, however this has no effect unless "EmbedOnlyUsedFonts" is enabled
2247 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue(u
"EmbedLatinScriptFonts"_ustr
).get
<bool>());
2248 CPPUNIT_ASSERT_EQUAL(true, xProps
->getPropertyValue(u
"EmbedAsianScriptFonts"_ustr
).get
<bool>());
2249 CPPUNIT_ASSERT_EQUAL(true,
2250 xProps
->getPropertyValue(u
"EmbedComplexScriptFonts"_ustr
).get
<bool>());
2252 // CASE 1 - no font embedding enabled
2254 // Save the document
2255 save(u
"writer8"_ustr
);
2256 CPPUNIT_ASSERT(maTempFile
.IsValid());
2258 // Check setting - No font embedding should be enabled
2259 pXmlDoc
= parseExport(u
"settings.xml"_ustr
);
2260 CPPUNIT_ASSERT(pXmlDoc
);
2262 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", u
"false");
2264 // Check content - No font-face-src nodes should be present
2265 pXmlDoc
= parseExport(u
"content.xml"_ustr
);
2266 CPPUNIT_ASSERT(pXmlDoc
);
2268 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
2269 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
2272 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
2273 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
2274 assertXPath(pXmlDoc
,
2276 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
2278 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
2279 assertXPath(pXmlDoc
,
2281 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
2283 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
2284 assertXPath(pXmlDoc
,
2286 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
2288 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
2289 assertXPath(pXmlDoc
,
2290 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 0);
2291 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
2292 assertXPath(pXmlDoc
,
2293 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
2295 // CASE 2 - font embedding enabled, but embed used fonts disabled
2297 // Enable font embedding, disable embedding used font only
2298 xProps
->setPropertyValue(u
"EmbedFonts"_ustr
, uno::Any(true));
2299 xProps
->setPropertyValue(u
"EmbedOnlyUsedFonts"_ustr
, uno::Any(false));
2301 // Save the document again
2302 save(u
"writer8"_ustr
);
2303 CPPUNIT_ASSERT(maTempFile
.IsValid());
2305 // Check setting - font embedding should be enabled + embed only used fonts and scripts
2306 pXmlDoc
= parseExport(u
"settings.xml"_ustr
);
2307 CPPUNIT_ASSERT(pXmlDoc
);
2309 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", u
"true");
2311 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
2314 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
2317 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
2320 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
2323 // Check content - font-face-src should be present only for "Liberation Sans" fonts
2325 pXmlDoc
= parseExport(u
"content.xml"_ustr
);
2326 CPPUNIT_ASSERT(pXmlDoc
);
2328 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
2329 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
2332 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 1);
2333 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
2334 assertXPath(pXmlDoc
,
2336 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
2338 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
2339 assertXPath(pXmlDoc
,
2341 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
2343 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
2344 assertXPath(pXmlDoc
,
2346 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
2348 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
2349 assertXPath(pXmlDoc
,
2350 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
2351 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
2352 assertXPath(pXmlDoc
,
2353 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 1);
2355 // CASE 3 - font embedding enabled, embed only used fonts enabled
2357 // Enable font embedding and setting to embed used fonts only
2358 xProps
->setPropertyValue(u
"EmbedFonts"_ustr
, uno::Any(true));
2359 xProps
->setPropertyValue(u
"EmbedOnlyUsedFonts"_ustr
, uno::Any(true));
2360 xProps
->setPropertyValue(u
"EmbedLatinScriptFonts"_ustr
, uno::Any(true));
2361 xProps
->setPropertyValue(u
"EmbedAsianScriptFonts"_ustr
, uno::Any(true));
2362 xProps
->setPropertyValue(u
"EmbedComplexScriptFonts"_ustr
, uno::Any(true));
2364 // Save the document again
2365 save(u
"writer8"_ustr
);
2366 CPPUNIT_ASSERT(maTempFile
.IsValid());
2368 // Check setting - font embedding should be enabled + embed only used fonts and scripts
2369 pXmlDoc
= parseExport(u
"settings.xml"_ustr
);
2370 CPPUNIT_ASSERT(pXmlDoc
);
2372 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedFonts']", u
"true");
2374 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedOnlyUsedFonts']",
2377 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedLatinScriptFonts']",
2380 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedAsianScriptFonts']",
2383 pXmlDoc
, aSettingsBaseXpath
+ "/config:config-item[@config:name='EmbedComplexScriptFonts']",
2386 // Check content - font-face-src should be present only for "Liberation Sans" fonts
2388 pXmlDoc
= parseExport(u
"content.xml"_ustr
);
2389 CPPUNIT_ASSERT(pXmlDoc
);
2391 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face", 6);
2392 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']");
2395 aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans']/svg:font-face-src", 0);
2396 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Sans1']");
2397 assertXPath(pXmlDoc
,
2399 + "/style:font-face[@style:name='Liberation Sans1']/svg:font-face-src",
2401 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif']");
2402 assertXPath(pXmlDoc
,
2404 + "/style:font-face[@style:name='Liberation Serif']/svg:font-face-src",
2406 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Liberation Serif1']");
2407 assertXPath(pXmlDoc
,
2409 + "/style:font-face[@style:name='Liberation Serif1']/svg:font-face-src",
2411 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']");
2412 assertXPath(pXmlDoc
,
2413 aContentBaseXpath
+ "/style:font-face[@style:name='Carlito']/svg:font-face-src", 1);
2414 assertXPath(pXmlDoc
, aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']");
2415 assertXPath(pXmlDoc
,
2416 aContentBaseXpath
+ "/style:font-face[@style:name='Caladea']/svg:font-face-src", 0);
2420 // Unit test for fix inconsistent bookmark behavior around at-char/as-char anchored frames
2422 // We have a placeholder character in the sw doc model for as-char anchored frames,
2423 // so it's possible to have a bookmark before/after the frame or a non-collapsed bookmark
2424 // which covers the frame. The same is not true for at-char anchored frames,
2425 // where the anchor points to a doc model position, but there is no placeholder character.
2426 // If a bookmark is created covering the start and end of the anchor of the frame,
2427 // internally we create a collapsed bookmark which has the same position as the anchor of the frame.
2428 // When this doc model is handled by SwXParagraph::createEnumeration(),
2429 // first the frame and then the bookmark is appended to the text portion enumeration,
2430 // so your bookmark around the frame is turned into a collapsed bookmark after the frame.
2431 // (The same happens when we roundtrip an ODT document representing this doc model.)
2433 // Fix the problem by inserting collapsed bookmarks with affected anchor positions
2434 // (same position is the anchor for an at-char frame) into the enumeration in two stages:
2435 // first the start of them before frames and then the end of them + other bookmarks.
2436 // This way UNO API users get their non-collapsed bookmarks around at-char anchored frames,
2437 // similar to as-char ones.
2438 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInconsistentBookmark
)
2440 // create test document with text and bookmark
2442 createSwDoc("testInconsistentBookmark.ott");
2443 SwDoc
* pDoc
= getSwDoc();
2444 IDocumentMarkAccess
& rIDMA(*pDoc
->getIDocumentMarkAccess());
2445 SwNodeIndex
aIdx(pDoc
->GetNodes().GetEndOfContent(), -1);
2446 SwCursor
aPaM(SwPosition(aIdx
), nullptr);
2448 aPaM
.MovePara(GoCurrPara
, fnParaStart
);
2449 aPaM
.MovePara(GoCurrPara
, fnParaEnd
);
2450 rIDMA
.makeMark(aPaM
, u
"Mark"_ustr
, IDocumentMarkAccess::MarkType::BOOKMARK
,
2451 ::sw::mark::InsertMode::New
);
2456 // save document and verify the bookmark scoup
2459 save(u
"writer8"_ustr
);
2461 // load only content.xml
2462 xmlDocUniquePtr pXmlDoc
= parseExport(u
"content.xml"_ustr
);
2463 static constexpr const char* aPath(
2464 "/office:document-content/office:body/office:text/text:p");
2466 const int pos1
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-start");
2467 const int pos2
= getXPathPosition(pXmlDoc
, aPath
, "control");
2468 const int pos3
= getXPathPosition(pXmlDoc
, aPath
, "bookmark-end");
2470 CPPUNIT_ASSERT_GREATER(pos1
, pos2
);
2471 CPPUNIT_ASSERT_GREATER(pos2
, pos3
);
2475 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testSpellOnlineParameter
)
2478 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2479 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
2480 bool bSet
= pOpt
->IsOnlineSpell();
2482 uno::Sequence
<beans::PropertyValue
> params
2483 = comphelper::InitPropertySequence({ { "Enable", uno::Any(!bSet
) } });
2484 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2485 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
2487 // set the same state as now and we don't expect any change (no-toggle)
2488 params
= comphelper::InitPropertySequence({ { "Enable", uno::Any(!bSet
) } });
2489 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2490 CPPUNIT_ASSERT_EQUAL(!bSet
, pOpt
->IsOnlineSpell());
2493 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf124603
)
2496 SwDoc
* pDoc
= getSwDoc();
2497 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2498 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
2499 uno::Sequence
<beans::PropertyValue
> params
2500 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
2501 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2503 // Automatic Spell Checking is enabled
2505 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
2507 // check available en_US dictionary and test spelling with it
2508 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
2509 uno::Reference
<XSpellChecker1
> xSpell
;
2510 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
2512 = LanguageTag::convertToLanguageType(lang::Locale(u
"en"_ustr
, u
"US"_ustr
, OUString()));
2513 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
2515 // Type a correct word
2517 emulateTyping(u
"the ");
2518 SwCursorShell
* pShell(pDoc
->GetEditShell());
2519 CPPUNIT_ASSERT(pShell
);
2520 SwTextNode
* pNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
2522 CPPUNIT_ASSERT_EQUAL(static_cast<SwWrongList
*>(nullptr), pNode
->GetWrong());
2524 // Create a bad word from the good: "the" -> "thex"
2526 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2527 emulateTyping(u
"x");
2528 // tdf#92036 pending spell checking
2529 bool bPending
= !pNode
->GetWrong() || !pNode
->GetWrong()->Count();
2530 CPPUNIT_ASSERT(bPending
);
2532 // Move right, leave the bad word - since the fix for tdf#136294, this triggers the check
2534 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2535 Scheduler::ProcessEventsToIdle();
2536 CPPUNIT_ASSERT(pNode
->GetWrong());
2537 // This was 0 (pending spell checking)
2538 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pNode
->GetWrong()->Count());
2542 #if !defined(MACOSX)
2543 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf45949
)
2546 SwDoc
* pDoc
= getSwDoc();
2547 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2548 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
2549 uno::Sequence
<beans::PropertyValue
> params
2550 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
2551 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2553 // Automatic Spell Checking is enabled
2554 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
2556 // check available en_US dictionary and test spelling with it
2557 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
2558 uno::Reference
<XSpellChecker1
> xSpell
;
2559 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
2561 = LanguageTag::convertToLanguageType(lang::Locale(u
"en"_ustr
, u
"US"_ustr
, OUString()));
2562 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
2564 emulateTyping(u
"baaad http://www.baaad.org baaad");
2565 SwCursorShell
* pShell(pDoc
->GetEditShell());
2566 CPPUNIT_ASSERT(pShell
);
2567 SwTextNode
* pNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
2569 // tdf#152492: Without the fix in place, this test would have failed with
2572 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pNode
->GetWrong()->Count());
2574 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 10, /*bBasicCall=*/false);
2575 emulateTyping(u
" ");
2577 CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), pNode
->GetWrong()->Count());
2579 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 6, /*bBasicCall=*/false);
2580 emulateTyping(u
" ");
2582 // Move down to trigger spell checking
2583 pWrtShell
->Down(/*bSelect=*/false, 1);
2584 Scheduler::ProcessEventsToIdle();
2586 // Without the fix in place, this test would have failed with
2589 CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pNode
->GetWrong()->Count());
2594 #if !defined(MACOSX)
2595 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf157442
)
2598 SwDoc
* pDoc
= getSwDoc();
2599 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2600 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
2601 uno::Sequence
<beans::PropertyValue
> params
2602 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
2603 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2605 // Automatic Spell Checking is enabled
2606 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
2608 // check available en_US dictionary and test spelling with it
2609 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
2610 uno::Reference
<XSpellChecker1
> xSpell
;
2611 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
2613 = LanguageTag::convertToLanguageType(lang::Locale(u
"en"_ustr
, u
"US"_ustr
, OUString()));
2614 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
2616 uno::Reference
<linguistic2::XLinguProperties
> xLinguProperties(
2617 LinguMgr::GetLinguPropertySet());
2619 // Spell with digits is disabled by default
2620 CPPUNIT_ASSERT_EQUAL(sal_False
, xLinguProperties
->getIsSpellWithDigits());
2622 emulateTyping(u
"ErrorError Treee2 ");
2623 SwCursorShell
* pShell(pDoc
->GetEditShell());
2624 CPPUNIT_ASSERT(pShell
);
2625 SwTextNode
* pNode
= pShell
->GetCursor()->GetPointNode().GetTextNode();
2627 // Without the fix in place, this test would have crashed because GetWrong() returns nullptr
2628 CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pNode
->GetWrong()->Count());
2633 #if !defined(MACOSX)
2634 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf65535
)
2636 createSwDoc("tdf65535.fodt");
2637 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2638 const SwViewOption
* pOpt
= pWrtShell
->GetViewOptions();
2639 uno::Sequence
<beans::PropertyValue
> params
2640 = comphelper::InitPropertySequence({ { "Enable", uno::Any(true) } });
2641 dispatchCommand(mxComponent
, u
".uno:SpellOnline"_ustr
, params
);
2643 // Automatic Spell Checking is enabled
2645 CPPUNIT_ASSERT(pOpt
->IsOnlineSpell());
2647 // check available en_US dictionary and test spelling with it
2648 uno::Reference
<XLinguServiceManager2
> xLngSvcMgr(GetLngSvcMgr_Impl());
2649 uno::Reference
<XSpellChecker1
> xSpell
;
2650 xSpell
.set(xLngSvcMgr
->getSpellChecker(), UNO_QUERY
);
2652 = LanguageTag::convertToLanguageType(lang::Locale(u
"en"_ustr
, u
"US"_ustr
, OUString()));
2653 if (xSpell
.is() && xSpell
->hasLanguage(static_cast<sal_uInt16
>(eLang
)))
2655 // trigger online spell checking by (a few) spaces to be sure to get it
2657 emulateTyping(u
" ");
2659 // FIXME: inserting a space before the bad word removes the red underline
2660 // Insert a second space to get the red underline (back)
2662 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 1, /*bBasicCall=*/false);
2663 emulateTyping(u
" ");
2665 // Select the bad word (right to left, as during right click)
2667 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/false, 5, /*bBasicCall=*/false);
2668 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/true, 4, /*bBasicCall=*/false);
2670 // choose the word "Baaed" from the spelling suggestions of the context menu
2672 SfxViewShell
* pViewShell
= SfxViewShell::Current();
2673 CPPUNIT_ASSERT(pViewShell
);
2675 static constexpr OUStringLiteral
sApplyRule(u
"Spelling_Baaed");
2676 SfxStringItem
aApplyItem(FN_PARAM_1
, sApplyRule
);
2677 pViewShell
->GetViewFrame().GetDispatcher()->ExecuteList(
2678 SID_SPELLCHECK_APPLY_SUGGESTION
, SfxCallMode::SYNCHRON
, { &aApplyItem
});
2681 // check the replacement in the text
2683 CPPUNIT_ASSERT_EQUAL(u
" Baaed"_ustr
, getParagraph(1)->getString());
2686 // check the remaining comment
2688 tools::JsonWriter aJsonWriter
;
2689 SwXTextDocument
* pTextDoc
= getSwTextDoc();
2690 pTextDoc
->getPostIts(aJsonWriter
);
2691 OString pChar
= aJsonWriter
.finishAndGetAsOString();
2692 std::stringstream
aStream((std::string(pChar
)));
2693 boost::property_tree::ptree aTree
;
2694 boost::property_tree::read_json(aStream
, aTree
);
2695 OString sCommentText
;
2696 for (const boost::property_tree::ptree::value_type
& rValue
: aTree
.get_child("comments"))
2698 const boost::property_tree::ptree
& rComment
= rValue
.second
;
2699 sCommentText
= OString(rComment
.get
<std::string
>("html"));
2701 // This was false (lost comment with spelling replacement)
2702 CPPUNIT_ASSERT_EQUAL("<div>with comment</div>"_ostr
, sCommentText
);
2706 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testRedlineAutoCorrect
)
2708 createSwDoc("redline-autocorrect.fodt");
2709 SwDoc
* pDoc
= getSwDoc();
2711 dispatchCommand(mxComponent
, u
".uno:GoToEndOfDoc"_ustr
, {});
2713 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2714 CPPUNIT_ASSERT(pWrtShell
);
2716 // show tracked deletion with enabled change tracking
2717 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
2718 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
2719 pWrtShell
->SetRedlineFlags(nMode
);
2720 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
2722 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
2723 pDoc
->getIDocumentRedlineAccess().IsRedlineOn());
2725 emulateTyping(u
" ");
2727 // tdf#83419 This was "Ts " removing the deletion of "t" silently by sentence capitalization
2728 OUString
sReplaced(u
"ts "_ustr
);
2729 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2731 // hide delete redlines
2732 pWrtShell
->SetRedlineFlags(nMode
& ~RedlineFlags::ShowDelete
);
2734 // repeat it with not visible redlining
2735 dispatchCommand(mxComponent
, u
".uno:Undo"_ustr
, {});
2737 emulateTyping(u
" ");
2740 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2742 // show delete redlines
2743 pWrtShell
->SetRedlineFlags(nMode
);
2745 // This still keep the tracked deletion, capitalize only the visible text "s"
2746 // with tracked deletion of the original character
2748 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2750 // repeat it with visible redlining and word auto replacement of "tset"
2751 dispatchCommand(mxComponent
, u
".uno:Undo"_ustr
, {});
2752 dispatchCommand(mxComponent
, u
".uno:Undo"_ustr
, {});
2754 emulateTyping(u
"et ");
2755 // This was "Ttest" removing the tracked deletion silently.
2756 // Don't replace, if a redline starts or ends within the text.
2757 sReplaced
= "tset ";
2758 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2760 // Otherwise replace it
2761 emulateTyping(u
"tset ");
2762 sReplaced
= "tset test ";
2763 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2765 // Including capitalization
2766 emulateTyping(u
"end. word ");
2767 sReplaced
= "tset test end. Word ";
2768 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2770 // tracked deletions after the correction point doesn't affect autocorrect
2771 dispatchCommand(mxComponent
, u
".uno:GoToStartOfDoc"_ustr
, {});
2772 emulateTyping(u
"a ");
2773 sReplaced
= "A tset test end. Word ";
2774 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2777 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testRedlineAutoCorrect2
)
2779 createSwDoc("redline-autocorrect2.fodt");
2780 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2781 CPPUNIT_ASSERT(pWrtShell
);
2783 dispatchCommand(mxComponent
, u
".uno:GoToEndOfDoc"_ustr
, {});
2785 // show tracked deletion
2786 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
2787 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
2788 pWrtShell
->SetRedlineFlags(nMode
);
2789 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
2791 emulateTyping(u
"... ");
2793 // This was "LoremLorem,…," (duplicating the deleted comma, but without deletion)
2794 // Don't replace, if a redline starts or ends within the text.
2795 OUString sReplaced
= u
"Lorem,... "_ustr
;
2796 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2799 emulateTyping(u
"Lorem,... ");
2800 sReplaced
= u
"Lorem,... Lorem,… "_ustr
;
2801 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2804 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testEmojiAutoCorrect
)
2806 createSwDoc("redline-autocorrect3.fodt");
2807 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2808 CPPUNIT_ASSERT(pWrtShell
);
2810 // Emoji replacement (:snowman: -> ☃)
2812 // without change tracking
2813 CPPUNIT_ASSERT(!(pWrtShell
->GetRedlineFlags() & RedlineFlags::On
));
2814 emulateTyping(u
":snowman:");
2815 OUString sReplaced
= u
"☃Lorem,"_ustr
;
2816 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2818 // with change tracking (showing redlines)
2819 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
2820 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
2821 pWrtShell
->SetRedlineFlags(nMode
);
2822 CPPUNIT_ASSERT(nMode
& RedlineFlags::On
);
2823 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
2825 emulateTyping(u
":snowman:");
2826 sReplaced
= u
"☃☃Lorem,"_ustr
;
2828 // tdf#140674 This was ":snowman:" instead of autocorrect
2829 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2832 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf153423
)
2835 SvxSwAutoFormatFlags
flags(*SwEditShell::GetAutoFormatFlags());
2836 comphelper::ScopeGuard
const g([=]() { SwEditShell::SetAutoFormatFlags(&flags
); });
2837 flags
.bSetNumRule
= true;
2838 SwEditShell::SetAutoFormatFlags(&flags
);
2840 emulateTyping(u
"1. Item 1");
2842 SwXTextDocument
* pTextDoc
= getSwTextDoc();
2843 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
2844 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYUP
, 0, KEY_RETURN
);
2845 Scheduler::ProcessEventsToIdle();
2847 // Without the fix in place, this test would have failed with
2850 CPPUNIT_ASSERT_EQUAL(u
"1."_ustr
,
2851 getProperty
<OUString
>(getParagraph(1), u
"ListLabelString"_ustr
));
2854 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf133589
)
2856 // Hungarian test document with right-to-left paragraph setting
2857 createSwDoc("tdf133589.fodt");
2858 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2859 CPPUNIT_ASSERT(pWrtShell
);
2860 // translitere words to Old Hungarian
2861 emulateTyping(u
"székely ");
2862 OUString
sReplaced(u
"𐳥𐳋𐳓𐳉𐳗 "_ustr
);
2863 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2864 // disambiguate consonants: asszony -> asz|szony
2865 emulateTyping(u
"asszony ");
2866 sReplaced
+= u
"𐳀𐳥𐳥𐳛𐳚 ";
2867 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2868 // disambiguate consonants: kosszarv -> kos|szarv
2869 // (add explicit ZWSP temporarily for consonant disambiguation, because the requested
2870 // hu_HU hyphenation dictionary isn't installed on all testing platform)
2871 // pWrtShell->Insert(u"kosszarv");
2872 emulateTyping(u
"kos\u200Bszarv ");
2873 sReplaced
+= u
"𐳓𐳛𐳤𐳥𐳀𐳢𐳮 ";
2874 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2875 // transliterate numbers to Old Hungarian
2876 emulateTyping(u
"2020 ");
2877 sReplaced
+= u
"𐳺𐳺𐳿𐳼𐳼 ";
2878 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2880 // tdf#147546 transliterate punctuation marks
2883 emulateTyping(u
"Kérdőjel?");
2884 sReplaced
+= u
"𐲓𐳋𐳢𐳇𐳟𐳒𐳉𐳖";
2885 OUString
sReplaced2(sReplaced
+ "?");
2886 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2887 emulateTyping(u
" ");
2889 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2891 emulateTyping(u
"Vessző,");
2892 sReplaced
+= u
"𐲮𐳉𐳥𐳥𐳟";
2893 sReplaced2
= sReplaced
+ ",";
2894 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2895 emulateTyping(u
" ");
2897 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2899 emulateTyping(u
"pontosvessző;");
2900 sReplaced
+= u
"𐳠𐳛𐳙𐳦𐳛𐳤𐳮𐳉𐳥𐳥𐳟";
2901 sReplaced2
= sReplaced
+ ";";
2902 CPPUNIT_ASSERT_EQUAL(sReplaced2
, getParagraph(1)->getString());
2903 emulateTyping(u
" ");
2905 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2907 emulateTyping(u
"„idézőjel” ");
2908 sReplaced
+= u
"⹂𐳐𐳇𐳋𐳯𐳟𐳒𐳉𐳖‟ ";
2909 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2911 // tdf#148672 transliterate word with closing bracket
2912 emulateTyping(u
"word] ");
2913 sReplaced
+= u
"𐳮𐳛𐳢𐳇] "; // This was "word]" (no transliteration)
2914 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2916 // tdf#148672 transliterate words with parenthesis (libnumbertext 1.0.11)
2917 emulateTyping(u
"(word) ");
2918 sReplaced
+= u
"(𐳮𐳛𐳢𐳇) "; // This was "(word)" (no transliteration)
2919 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2921 emulateTyping(u
"(word ");
2922 sReplaced
+= u
"(𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2923 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2925 emulateTyping(u
"word) ");
2926 sReplaced
+= u
"𐳮𐳛𐳢𐳇) "; // This was "word)" (no transliteration)
2927 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2929 emulateTyping(u
"{word} ");
2930 sReplaced
+= u
"{𐳮𐳛𐳢𐳇} "; // This was "(word)" (no transliteration)
2931 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2933 emulateTyping(u
"{word ");
2934 sReplaced
+= u
"{𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2935 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2937 emulateTyping(u
"word} ");
2938 sReplaced
+= u
"𐳮𐳛𐳢𐳇} "; // This was "word)" (no transliteration)
2939 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2941 emulateTyping(u
"[word] ");
2942 sReplaced
+= u
"[𐳮𐳛𐳢𐳇] "; // This was "(word)" (no transliteration)
2943 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2945 emulateTyping(u
"[word ");
2946 sReplaced
+= u
"[𐳮𐳛𐳢𐳇 "; // This was "(word" (no transliteration)
2947 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
2950 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testAutoCorr
)
2953 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
2954 CPPUNIT_ASSERT(pWrtShell
);
2956 //Normal AutoCorrect
2957 emulateTyping(u
"tset ");
2958 CPPUNIT_ASSERT_EQUAL(u
"Test "_ustr
, getParagraph(1)->getString());
2960 //AutoCorrect with change style to bolt
2961 emulateTyping(u
"Bolt ");
2962 const uno::Reference
<text::XTextRange
> xRun
= getRun(getParagraph(1), 2);
2963 CPPUNIT_ASSERT_EQUAL(u
"Bolt"_ustr
, xRun
->getString());
2964 CPPUNIT_ASSERT_EQUAL(u
"Arial"_ustr
, getProperty
<OUString
>(xRun
, u
"CharFontName"_ustr
));
2966 //AutoCorrect inserts Table with 2 rows and 3 columns
2967 emulateTyping(u
"4xx ");
2968 const uno::Reference
<text::XTextTable
> xTable(getParagraphOrTable(2), uno::UNO_QUERY
);
2969 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTable
->getRows()->getCount());
2970 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable
->getColumns()->getCount());
2973 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf130274
)
2976 SwDoc
* pDoc
= getSwDoc();
2977 SwWrtShell
* const pWrtShell
= getSwDocShell()->GetWrtShell();
2978 CPPUNIT_ASSERT(pWrtShell
);
2980 CPPUNIT_ASSERT(!pWrtShell
->GetLayout()->IsHideRedlines());
2982 !IDocumentRedlineAccess::IsRedlineOn(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
2984 // "tset" may be replaced by the AutoCorrect in the test profile
2985 emulateTyping(u
"tset");
2986 // select from left to right
2987 pWrtShell
->Left(SwCursorSkipMode::Chars
, /*bSelect=*/false, 4, /*bBasicCall=*/false);
2988 pWrtShell
->Right(SwCursorSkipMode::Chars
, /*bSelect=*/true, 4, /*bBasicCall=*/false);
2990 pWrtShell
->SetRedlineFlags(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
2991 // this would crash in AutoCorrect
2992 emulateTyping(u
".");
2994 CPPUNIT_ASSERT(!pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty());
2997 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf83260
)
2999 createSwDoc("tdf83260-1.odt");
3000 SwDoc
* pDoc
= getSwDoc();
3001 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3002 CPPUNIT_ASSERT(pWrtShell
);
3004 // enabled but not shown
3005 CPPUNIT_ASSERT(pWrtShell
->GetLayout()->IsHideRedlines());
3007 CPPUNIT_ASSERT(IDocumentRedlineAccess::IsHideChanges(
3008 pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
3011 IDocumentRedlineAccess::IsRedlineOn(pDoc
->getIDocumentRedlineAccess().GetRedlineFlags()));
3012 CPPUNIT_ASSERT(!pDoc
->getIDocumentRedlineAccess().GetRedlineTable().empty());
3014 // the document contains redlines that are combined with CompressRedlines()
3015 // if that happens during AutoCorrect then indexes in Undo are off -> crash
3016 emulateTyping(u
"tset ");
3017 sw::UndoManager
& rUndoManager
= pDoc
->GetUndoManager();
3018 auto const nActions(rUndoManager
.GetUndoActionCount());
3019 for (auto i
= nActions
; 0 < i
; --i
)
3021 rUndoManager
.Undo();
3023 // check that every text node has a layout frame
3024 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
3026 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
3028 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
3031 for (auto i
= nActions
; 0 < i
; --i
)
3033 rUndoManager
.Redo();
3035 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
3037 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
3039 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
3042 for (auto i
= nActions
; 0 < i
; --i
)
3044 rUndoManager
.Undo();
3046 for (SwNodeOffset
i(0); i
< pDoc
->GetNodes().Count(); ++i
)
3048 if (SwTextNode
const* const pNode
= pDoc
->GetNodes()[i
]->GetTextNode())
3050 CPPUNIT_ASSERT(pNode
->getLayoutFrame(nullptr, nullptr, nullptr));
3055 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf139922
)
3059 SwXTextDocument
* pTextDoc
= getSwTextDoc();
3060 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
3061 Scheduler::ProcessEventsToIdle();
3063 emulateTyping(u
"this is a SEntence. this is a SEntence.");
3065 // Without the fix in place, this test would have failed with
3066 // - Expected: This is a Sentence. This is a Sentence.
3067 // - Actual : this is a Sentence. This is a Sentence.
3068 CPPUNIT_ASSERT_EQUAL(u
"This is a Sentence. This is a Sentence."_ustr
,
3069 getParagraph(2)->getString());
3072 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf143176
)
3074 // Hungarian test document with right-to-left paragraph setting
3075 createSwDoc("tdf143176.fodt");
3077 // transliterate the document to Old Hungarian (note: it only works
3078 // with right-to-left text direction and Default Paragraph Style)
3079 dispatchCommand(mxComponent
, u
".uno:AutoFormatApply"_ustr
, {});
3081 // This was the original "Lorem ipsum..."
3082 CPPUNIT_ASSERT_EQUAL(u
"𐲖𐳛𐳢𐳉𐳘 𐳐𐳠𐳤𐳪𐳘 𐳇𐳛𐳖𐳛𐳢 "
3084 getParagraph(1)->getString());
3085 CPPUNIT_ASSERT_EQUAL(u
"𐳄𐳛𐳙𐳤𐳉𐳄𐳦𐳉𐳦𐳪𐳢 "
3086 u
"𐳀𐳇𐳐𐳠𐳐𐳤𐳄𐳐𐳙𐳍 𐳉𐳖𐳐𐳦."_ustr
,
3087 getParagraph(2)->getString());
3090 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInsertLongDateFormat
)
3092 // only for Hungarian, yet
3093 createSwDoc("tdf133524.fodt");
3094 dispatchCommand(mxComponent
, u
".uno:InsertDateField"_ustr
, {});
3095 // Make sure that the document starts with a field now, and its expanded string value contains space
3096 const uno::Reference
<text::XTextRange
> xField
= getRun(getParagraph(1), 1);
3097 CPPUNIT_ASSERT_EQUAL(u
"TextField"_ustr
, getProperty
<OUString
>(xField
, u
"TextPortionType"_ustr
));
3098 // the date format was "YYYY-MM-DD", but now "YYYY. MMM DD."
3099 CPPUNIT_ASSERT(xField
->getString().indexOf(" ") > -1);
3102 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf129270
)
3104 createSwDoc("tdf129270.odt");
3105 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3106 CPPUNIT_ASSERT(pWrtShell
);
3108 // Go to document end
3109 pWrtShell
->SttEndDoc(/*bStt=*/false);
3112 SwXTextDocument
* pTextDoc
= getSwTextDoc();
3113 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_RETURN
);
3114 Scheduler::ProcessEventsToIdle();
3116 // Numbering for previous outline should remain the same "2"
3117 CPPUNIT_ASSERT_EQUAL(u
"2"_ustr
,
3118 getProperty
<OUString
>(getParagraph(4), u
"ListLabelString"_ustr
));
3120 // Numbering for newly created outline should be "2.1"
3121 CPPUNIT_ASSERT_EQUAL(u
"2.1"_ustr
,
3122 getProperty
<OUString
>(getParagraph(5), u
"ListLabelString"_ustr
));
3125 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testInsertPdf
)
3127 auto pPdfium
= vcl::pdf::PDFiumLibrary::get();
3135 // insert the PDF into the document
3136 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
3137 { { "FileName", uno::Any(createFileURL(u
"hello-world.pdf")) } }));
3138 dispatchCommand(mxComponent
, u
".uno:InsertGraphic"_ustr
, aArgs
);
3140 // Save and load cycle
3141 saveAndReload(u
"writer8"_ustr
);
3143 uno::Reference
<drawing::XShape
> xShape
= getShape(1);
3144 // Assert that we have a replacement graphics
3145 auto xReplacementGraphic
3146 = getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, u
"ReplacementGraphic"_ustr
);
3147 CPPUNIT_ASSERT(xReplacementGraphic
.is());
3149 auto xGraphic
= getProperty
<uno::Reference
<graphic::XGraphic
>>(xShape
, u
"Graphic"_ustr
);
3150 CPPUNIT_ASSERT(xGraphic
.is());
3151 // Assert that the graphic is a PDF
3152 CPPUNIT_ASSERT_EQUAL(u
"application/pdf"_ustr
,
3153 getProperty
<OUString
>(xGraphic
, u
"MimeType"_ustr
));
3156 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf143760WrapContourToOff
)
3158 // Actually, this is an ooxmlexport test. It is here because here is a ready environment
3159 // to change a shape by dispatchCommand.
3160 createSwDoc("tdf143760_ContourToWrapOff.docx");
3161 SwDoc
* pDoc
= getSwDoc();
3162 CPPUNIT_ASSERT_EQUAL(true, getProperty
<bool>(getShape(1), u
"SurroundContour"_ustr
));
3165 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3166 SdrPage
* pPage
= pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
3167 SdrObject
* pObject
= pPage
->GetObj(0);
3168 CPPUNIT_ASSERT(pObject
);
3169 SdrView
* pView
= pWrtShell
->GetDrawView();
3170 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
3173 dispatchCommand(mxComponent
, u
".uno:WrapOff"_ustr
, {});
3174 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), u
"SurroundContour"_ustr
));
3176 // Without fix this had failed, because the shape was written to file with contour.
3177 saveAndReload(u
"Office Open XML Text"_ustr
);
3178 CPPUNIT_ASSERT_EQUAL(false, getProperty
<bool>(getShape(1), u
"SurroundContour"_ustr
));
3181 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testHatchFill
)
3185 // Add a rectangle shape to the document.
3186 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
3187 uno::Reference
<drawing::XShape
> xShape(
3188 xFactory
->createInstance(u
"com.sun.star.drawing.RectangleShape"_ustr
), uno::UNO_QUERY
);
3189 xShape
->setSize(awt::Size(10000, 10000));
3190 xShape
->setPosition(awt::Point(1000, 1000));
3191 uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY
);
3192 xShapeProps
->setPropertyValue(u
"FillStyle"_ustr
, uno::Any(drawing::FillStyle_HATCH
));
3193 xShapeProps
->setPropertyValue(u
"FillHatchName"_ustr
, uno::Any(u
"Black 0 Degrees"_ustr
));
3194 xShapeProps
->setPropertyValue(u
"FillBackground"_ustr
, uno::Any(false));
3195 xShapeProps
->setPropertyValue(u
"FillTransparence"_ustr
, uno::Any(sal_Int32(30)));
3196 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
3197 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
3198 xDrawPage
->add(xShape
);
3200 // Save it as DOCX and load it again.
3201 saveAndReload(u
"Office Open XML Text"_ustr
);
3202 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3204 // tdf#127989 Without fix this had failed, because the background of the hatch was not set as 'no background'.
3205 CPPUNIT_ASSERT(!getProperty
<bool>(getShape(1), u
"FillBackground"_ustr
));
3207 // tdf#146822 Without fix this had failed, because the transparency value of the hatch was not exported.
3208 CPPUNIT_ASSERT_EQUAL(sal_Int32(30),
3209 getProperty
<sal_Int32
>(getShape(1), u
"FillTransparence"_ustr
));
3212 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testNestedGroupTextBoxCopyCrash
)
3214 createSwDoc("tdf149550.docx");
3216 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3218 dispatchCommand(mxComponent
, u
".uno:SelectAll"_ustr
, {});
3219 dispatchCommand(mxComponent
, u
".uno:Copy"_ustr
, {});
3220 // This crashed here before the fix.
3221 SwXTextDocument
* pTextDoc
= getSwTextDoc();
3222 pTextDoc
->postKeyEvent(LOK_KEYEVENT_KEYINPUT
, 0, KEY_ESCAPE
);
3223 Scheduler::ProcessEventsToIdle();
3224 dispatchCommand(mxComponent
, u
".uno:Paste"_ustr
, {});
3226 CPPUNIT_ASSERT_EQUAL(2, getShapes());
3228 auto pLayout
= parseLayoutDump();
3229 // There must be 2 textboxes!
3230 assertXPath(pLayout
, "/root/page/body/txt/anchored/fly[2]");
3233 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testCrashOnExit
)
3235 // Load the bugdoc with a table and a textbox shape inside.
3236 createSwDoc("tdf142715.odt");
3238 // Get the textbox selected
3239 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3242 auto xShape
= getShape(1);
3243 uno::Reference
<beans::XPropertySet
> xProperties(xShape
, uno::UNO_QUERY
);
3245 // Check if the textbox is selected
3246 CPPUNIT_ASSERT_EQUAL(true, xProperties
->getPropertyValue(u
"TextBox"_ustr
).get
<bool>());
3248 // Remove the textbox
3249 dispatchCommand(mxComponent
, u
".uno:RemoveTextBox"_ustr
, {});
3251 CPPUNIT_ASSERT_EQUAL(false, xProperties
->getPropertyValue(u
"TextBox"_ustr
).get
<bool>());
3253 // Readd the textbox (to run the textboxhelper::create() method)
3254 dispatchCommand(mxComponent
, u
".uno:AddTextBox"_ustr
, {});
3256 CPPUNIT_ASSERT_EQUAL(true, xProperties
->getPropertyValue(u
"TextBox"_ustr
).get
<bool>());
3259 // Before the fix this crashed here and could not reopen.
3260 saveAndReload(u
"writer8"_ustr
);
3263 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testCaptionShape
)
3267 // Add a caption shape to the document.
3268 uno::Reference
<css::lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
3269 uno::Reference
<drawing::XShape
> xShape(
3270 xFactory
->createInstance(u
"com.sun.star.drawing.CaptionShape"_ustr
), uno::UNO_QUERY
);
3271 xShape
->setSize(awt::Size(10000, 10000));
3272 xShape
->setPosition(awt::Point(1000, 1000));
3273 uno::Reference
<drawing::XDrawPageSupplier
> xDrawPageSupplier(mxComponent
, uno::UNO_QUERY
);
3274 uno::Reference
<drawing::XDrawPage
> xDrawPage
= xDrawPageSupplier
->getDrawPage();
3275 xDrawPage
->add(xShape
);
3277 // Save it as DOCX and load it again.
3278 saveAndReload(u
"Office Open XML Text"_ustr
);
3280 // Without fix in place, the shape was lost on export.
3281 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3284 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf151828_Comment2
)
3288 // Add a basic shape to the document.
3289 uno::Sequence
<beans::PropertyValue
> aArgs(
3290 comphelper::InitPropertySequence({ { "KeyModifier", uno::Any(KEY_MOD1
) } }));
3291 dispatchCommand(mxComponent
, u
".uno:BasicShapes"_ustr
, aArgs
);
3293 auto xBasicShape
= getShape(1);
3294 auto pObject
= SdrObject::getSdrObjectFromXShape(xBasicShape
);
3296 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3298 // rename the shape name
3299 pObject
->SetName(u
"Shape"_ustr
);
3302 dispatchCommand(mxComponent
, u
".uno:Cut"_ustr
, {});
3304 CPPUNIT_ASSERT_EQUAL(0, getShapes());
3306 dispatchCommand(mxComponent
, u
".uno:Paste"_ustr
, {});
3308 CPPUNIT_ASSERT_EQUAL(1, getShapes());
3310 // it is required to get the shape object again after paste
3311 xBasicShape
= getShape(1);
3312 pObject
= SdrObject::getSdrObjectFromXShape(xBasicShape
);
3314 // Without fix in place, the shape name was 'Shape 1' after paste.
3315 CPPUNIT_ASSERT_EQUAL(u
"Shape"_ustr
, pObject
->GetName());
3318 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf151828
)
3321 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3324 SwInsertTableOptions
TableOpt(SwInsertTableFlags::DefaultBorder
, 0);
3325 pWrtShell
->InsertTable(TableOpt
, 1, 1);
3327 // move cursor into the table
3328 CPPUNIT_ASSERT(pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
));
3330 SwFrameFormat
* pFormat
= pWrtShell
->GetTableFormat();
3331 CPPUNIT_ASSERT(pFormat
);
3333 // set name of table to 'MyTableName'
3334 pWrtShell
->SetTableName(*pFormat
, u
"MyTableName"_ustr
);
3336 // cut and paste the table
3337 dispatchCommand(mxComponent
, u
".uno:SelectTable"_ustr
, {});
3338 dispatchCommand(mxComponent
, u
".uno:Cut"_ustr
, {});
3339 dispatchCommand(mxComponent
, u
".uno:Paste"_ustr
, {});
3341 // move cursor into the pasted table
3342 CPPUNIT_ASSERT(pWrtShell
->MoveTable(GotoPrevTable
, fnTableStart
));
3344 pFormat
= pWrtShell
->GetTableFormat();
3345 CPPUNIT_ASSERT(pFormat
);
3347 // Before the fix the pasted table name was 'Table1'.
3348 CPPUNIT_ASSERT_EQUAL(u
"MyTableName"_ustr
, pFormat
->GetName());
3351 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf146178
)
3355 SwDoc
* pDoc
= getSwDoc();
3356 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3357 SwCursorShell
* pShell(pDoc
->GetEditShell());
3358 CPPUNIT_ASSERT(pShell
);
3359 SwPaM
* pCursor
= pShell
->GetCursor();
3361 // insert two fields
3362 dispatchCommand(mxComponent
, u
".uno:InsertTimeField"_ustr
, {});
3363 dispatchCommand(mxComponent
, u
".uno:InsertDateField"_ustr
, {});
3365 // navigate by field
3366 SwView::SetMoveType(NID_FIELD
);
3368 // set cursor to the start of the document
3369 pWrtShell
->SttEndDoc(false);
3370 // navigate to the previous field
3371 dispatchCommand(mxComponent
, u
".uno:ScrollToPrevious"_ustr
, {});
3372 // Before the fix the position would be 0, navigation did not wrap to end of document
3373 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pCursor
->GetPoint()->GetContentIndex());
3375 // set cursor to the end of the document
3376 pWrtShell
->SttEndDoc(false);
3377 // navigate to the next field
3378 dispatchCommand(mxComponent
, u
".uno:ScrollToNext"_ustr
, {});
3379 // Before the fix the position would be 1, navigation did not wrap to start of document
3380 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pCursor
->GetPoint()->GetContentIndex());
3383 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf106663HeaderTextFrameGoToNextPlacemarker
)
3385 createSwDoc("testTdf106663.odt");
3387 SwDoc
* pDoc
= getSwDoc();
3388 SwCursorShell
* pShell(pDoc
->GetEditShell());
3389 CPPUNIT_ASSERT(pShell
);
3390 SwPaM
* pCursor
= pShell
->GetCursor();
3391 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3393 // Move the cursor into the fly frame of the document's header
3394 pWrtShell
->GotoFly(u
"FrameInHeader"_ustr
, FLYCNTTYPE_FRM
, false);
3396 // Check that GoToNextPlacemarker highlights the first field instead of the second one
3397 dispatchCommand(mxComponent
, u
".uno:GoToNextPlacemarker"_ustr
, {});
3398 // Without the fix in place, this test would have failed with
3399 // - Expected: Heading
3400 // - Actual : Some other marker
3401 // i.e. the GoToNextPlacemarker command skipped the first field
3402 CPPUNIT_ASSERT(pCursor
->GetPoint()->GetNode().GetTextNode()->GetText().startsWith("Heading"));
3405 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6
, testTdf158454
)
3407 createSwDoc("tdf158454.odt");
3408 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
3409 CPPUNIT_ASSERT(pWrtShell
);
3411 // * without change tracking
3412 CPPUNIT_ASSERT(!(pWrtShell
->GetRedlineFlags() & RedlineFlags::On
));
3414 // Thai single autocorrect (อนุญาติ -> อนุญาต)
3415 emulateTyping(u
"อนุญาติ ");
3416 OUString sReplaced
= u
"อนุญาต (จบ)"_ustr
;
3417 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
3419 // Thai multiple autocorrects (กงศุลสังเกตุกระทันหัน -> กงสุลสังเกตกะทันหัน)
3420 emulateTyping(u
"กงศุลสังเกตุกระทันหัน ");
3421 sReplaced
= u
"อนุญาต กงสุลสังเกตกะทันหัน (จบ)"_ustr
;
3422 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
3424 // * with change tracking (showing redlines)
3425 RedlineFlags
const nMode(pWrtShell
->GetRedlineFlags() | RedlineFlags::On
);
3426 CPPUNIT_ASSERT(nMode
& (RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert
));
3427 pWrtShell
->SetRedlineFlags(nMode
);
3428 CPPUNIT_ASSERT(nMode
& RedlineFlags::On
);
3429 CPPUNIT_ASSERT(nMode
& RedlineFlags::ShowDelete
);
3431 // Thai single autocorrect (อนุญาติ -> อนุญาต)
3432 emulateTyping(u
"อนุญาติ ");
3433 sReplaced
= u
"อนุญาต กงสุลสังเกตกะทันหัน อนุญาต (จบ)"_ustr
;
3434 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
3436 // Thai multiple autocorrects (กงศุลสังเกตุกระทันหัน -> กงสุลสังเกตกะทันหัน)
3437 emulateTyping(u
"กงศุลสังเกตุกระทันหัน ");
3438 sReplaced
= u
"อนุญาต กงสุลสังเกตกะทันหัน อนุญาต กงสุลสังเกตกะทันหัน (จบ)"_ustr
;
3439 CPPUNIT_ASSERT_EQUAL(sReplaced
, getParagraph(1)->getString());
3442 CPPUNIT_PLUGIN_IMPLEMENT();
3444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */