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 <officecfg/Office/Common.hxx>
12 #include "sdmodeltestbase.hxx"
14 #include <com/sun/star/uno/Reference.hxx>
16 #include <com/sun/star/awt/Gradient.hpp>
17 #include <com/sun/star/drawing/FillStyle.hpp>
18 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
19 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
20 #include <com/sun/star/drawing/XDrawPages.hpp>
21 #include <com/sun/star/drawing/XDrawPage.hpp>
22 #include <com/sun/star/drawing/XShapes.hpp>
23 #include <com/sun/star/graphic/XGraphic.hpp>
24 #include <com/sun/star/container/XIndexAccess.hpp>
25 #include <com/sun/star/table/XTable.hpp>
26 #include <com/sun/star/table/XMergeableCellRange.hpp>
27 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
29 #include <DrawDocShell.hxx>
30 #include <drawdoc.hxx>
31 #include <vcl/scheduler.hxx>
32 #include <svx/sdr/table/tablecontroller.hxx>
33 #include <sfx2/request.hxx>
34 #include <svx/svdpagv.hxx>
35 #include <svx/svxids.hrc>
36 #include <editeng/eeitem.hxx>
37 #include <editeng/adjustitem.hxx>
38 #include <editeng/outlobj.hxx>
39 #include <editeng/editobj.hxx>
40 #include <comphelper/base64.hxx>
41 #include <docmodel/uno/UnoGradientTools.hxx>
42 #include <undo/undomanager.hxx>
43 #include <GraphicViewShell.hxx>
45 #include <LayerTabBar.hxx>
46 #include <vcl/event.hxx>
47 #include <vcl/keycodes.hxx>
48 #include <svx/svdoashp.hxx>
49 #include <tools/gen.hxx>
50 #include <svx/view3d.hxx>
51 #include <svx/scene3d.hxx>
52 #include <svx/sdmetitm.hxx>
53 #include <unomodel.hxx>
55 using namespace ::com::sun::star
;
57 /// Impress miscellaneous tests.
58 class SdMiscTest
: public SdModelTestBase
62 : SdModelTestBase(u
"/sd/qa/unit/data/"_ustr
)
67 void testTableObjectUndoTest();
68 void testFillGradient();
71 void testTdf101242_ODF_no_settings();
72 void testTdf101242_ODF_add_settings();
73 void testTdf101242_settings_keep();
74 void testTdf101242_settings_remove();
79 void testTextColumns();
80 void testTdf98839_ShearVFlipH();
83 void testTdf129898LayerDrawnInSlideshow();
87 void testEncodedTableStyles();
90 CPPUNIT_TEST_SUITE(SdMiscTest
);
91 CPPUNIT_TEST(testTdf99396
);
92 CPPUNIT_TEST(testTableObjectUndoTest
);
93 CPPUNIT_TEST(testFillGradient
);
94 CPPUNIT_TEST(testTdf44774
);
95 CPPUNIT_TEST(testTdf38225
);
96 CPPUNIT_TEST(testTdf101242_ODF_no_settings
);
97 CPPUNIT_TEST(testTdf101242_ODF_add_settings
);
98 CPPUNIT_TEST(testTdf101242_settings_keep
);
99 CPPUNIT_TEST(testTdf101242_settings_remove
);
100 CPPUNIT_TEST(testTdf119392
);
101 CPPUNIT_TEST(testTdf67248
);
102 CPPUNIT_TEST(testTdf119956
);
103 CPPUNIT_TEST(testTdf120527
);
104 CPPUNIT_TEST(testTextColumns
);
105 CPPUNIT_TEST(testTdf98839_ShearVFlipH
);
106 CPPUNIT_TEST(testTdf130988
);
107 CPPUNIT_TEST(testTdf131033
);
108 CPPUNIT_TEST(testTdf129898LayerDrawnInSlideshow
);
109 CPPUNIT_TEST(testTdf136956
);
110 CPPUNIT_TEST(testTdf39519
);
111 CPPUNIT_TEST(testTdf164284
);
112 CPPUNIT_TEST(testEncodedTableStyles
);
113 CPPUNIT_TEST(testTdf157117
);
114 CPPUNIT_TEST_SUITE_END();
117 void SdMiscTest::testTdf99396()
119 // Load the document and select the table.
120 createSdImpressDoc("tdf99396.odp");
122 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
123 CPPUNIT_ASSERT(pXImpressDocument
);
124 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
126 SdPage
* pPage
= pViewShell
->GetActualPage();
127 SdrObject
* pObject
= pPage
->GetObj(0);
128 SdrView
* pView
= pViewShell
->GetView();
129 pView
->MarkObj(pObject
, pView
->GetSdrPageView());
131 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
132 // Make sure that the undo stack is empty.
133 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc
->GetUndoManager()->GetUndoActionCount());
135 // Set the vertical alignment of the cells to bottom.
136 sdr::table::SvxTableController
* pTableController
137 = dynamic_cast<sdr::table::SvxTableController
*>(pView
->getSelectionController().get());
138 CPPUNIT_ASSERT(pTableController
);
139 SfxRequest
aRequest(*pViewShell
->GetViewFrame(), SID_TABLE_VERT_BOTTOM
);
140 pTableController
->Execute(aRequest
);
141 // This was 0, it wasn't possible to undo a vertical alignment change.
142 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pDoc
->GetUndoManager()->GetUndoActionCount());
145 void SdMiscTest::testTableObjectUndoTest()
147 // See tdf#99396 for the issue
149 // Load the document and select the table.
150 createSdImpressDoc("tdf99396.odp");
151 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
152 CPPUNIT_ASSERT(pXImpressDocument
);
153 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
154 SdPage
* pPage
= pViewShell
->GetActualPage();
155 auto pTableObject
= dynamic_cast<sdr::table::SdrTableObj
*>(pPage
->GetObj(0));
156 CPPUNIT_ASSERT(pTableObject
);
157 SdrView
* pView
= pViewShell
->GetView();
158 pView
->MarkObj(pTableObject
, pView
->GetSdrPageView());
160 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
161 // Make sure that the undo stack is empty.
162 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc
->GetUndoManager()->GetUndoActionCount());
164 // Set horizontal and vertical adjustment during text edit.
165 pView
->SdrBeginTextEdit(pTableObject
);
166 CPPUNIT_ASSERT(pView
->GetTextEditObject());
168 SfxRequest
aRequest(*pViewShell
->GetViewFrame(), SID_ATTR_PARA_ADJUST_RIGHT
);
169 SfxItemSet
aEditAttr(pDoc
->GetPool());
170 pView
->GetAttributes(aEditAttr
);
171 SfxItemSet
aNewAttr(*(aEditAttr
.GetPool()), aEditAttr
.GetRanges());
172 aNewAttr
.Put(SvxAdjustItem(SvxAdjust::Right
, EE_PARA_JUST
));
173 aRequest
.Done(aNewAttr
);
174 const SfxItemSet
* pArgs
= aRequest
.GetArgs();
175 pView
->SetAttributes(*pArgs
);
177 const auto& pLocalUndoManager
= pView
->getViewLocalUndoManager();
178 CPPUNIT_ASSERT_EQUAL(size_t(1), pLocalUndoManager
->GetUndoActionCount());
179 CPPUNIT_ASSERT_EQUAL(u
"Apply attributes"_ustr
, pLocalUndoManager
->GetUndoActionComment());
181 auto pTableController
182 = dynamic_cast<sdr::table::SvxTableController
*>(pView
->getSelectionController().get());
183 CPPUNIT_ASSERT(pTableController
);
184 SfxRequest
aRequest(*pViewShell
->GetViewFrame(), SID_TABLE_VERT_BOTTOM
);
185 pTableController
->Execute(aRequest
);
187 // Global change "Format cell" is applied only - Change the vertical alignment to "Bottom"
188 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc
->GetUndoManager()->GetUndoActionCount());
189 CPPUNIT_ASSERT_EQUAL(u
"Format cell"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment());
191 pView
->SdrEndTextEdit();
193 // End of text edit, so the text edit action is added to the undo stack
194 CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc
->GetUndoManager()->GetUndoActionCount());
195 CPPUNIT_ASSERT_EQUAL(u
"Edit text of Table"_ustr
,
196 pDoc
->GetUndoManager()->GetUndoActionComment(0));
197 CPPUNIT_ASSERT_EQUAL(u
"Format cell"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment(1));
199 // Check that the result is what we expect.
201 uno::Reference
<table::XTable
> xTable
= pTableObject
->getTable();
202 uno::Reference
<beans::XPropertySet
> xCell(xTable
->getCellByPosition(0, 0), uno::UNO_QUERY
);
203 drawing::TextVerticalAdjust eAdjust
= xCell
->getPropertyValue(u
"TextVerticalAdjust"_ustr
)
204 .get
<drawing::TextVerticalAdjust
>();
205 CPPUNIT_ASSERT_EQUAL(int(drawing::TextVerticalAdjust_BOTTOM
), static_cast<int>(eAdjust
));
208 const EditTextObject
& rEdit
209 = pTableObject
->getText(0)->GetOutlinerParaObject()->GetTextObject();
210 const SfxItemSet
& rParaAttribs
= rEdit
.GetParaAttribs(0);
211 auto pAdjust
= rParaAttribs
.GetItem(EE_PARA_JUST
);
212 CPPUNIT_ASSERT_EQUAL(SvxAdjust::Right
, pAdjust
->GetAdjust());
216 pXImpressDocument
->GetDocShell()->GetUndoManager()->Undo();
218 // Undoing the last action - one left
219 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc
->GetUndoManager()->GetUndoActionCount());
220 CPPUNIT_ASSERT_EQUAL(u
"Format cell"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment(0));
222 // Check again that the result is what we expect.
224 uno::Reference
<table::XTable
> xTable
= pTableObject
->getTable();
225 uno::Reference
<beans::XPropertySet
> xCell(xTable
->getCellByPosition(0, 0), uno::UNO_QUERY
);
226 drawing::TextVerticalAdjust eAdjust
= xCell
->getPropertyValue(u
"TextVerticalAdjust"_ustr
)
227 .get
<drawing::TextVerticalAdjust
>();
228 // This failed: Undo() did not change it from drawing::TextVerticalAdjust_BOTTOM.
229 CPPUNIT_ASSERT_EQUAL(int(drawing::TextVerticalAdjust_TOP
), static_cast<int>(eAdjust
));
232 const EditTextObject
& rEdit
233 = pTableObject
->getText(0)->GetOutlinerParaObject()->GetTextObject();
234 const SfxItemSet
& rParaAttribs
= rEdit
.GetParaAttribs(0);
235 auto pAdjust
= rParaAttribs
.GetItem(EE_PARA_JUST
);
236 CPPUNIT_ASSERT_EQUAL(SvxAdjust::Center
, pAdjust
->GetAdjust());
239 Scheduler::ProcessEventsToIdle();
240 CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc
->GetUndoManager()->GetUndoActionCount());
241 CPPUNIT_ASSERT_EQUAL(u
"Format cell"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment(0));
244 * now test tdf#103950 - Undo does not revert bundled font size changes for table cells
246 pTableObject
= dynamic_cast<sdr::table::SdrTableObj
*>(pPage
->GetObj(0));
247 pView
->MarkObj(pTableObject
, pView
->GetSdrPageView()); // select table
249 SfxRequest
aRequest(*pViewShell
->GetViewFrame(), SID_GROW_FONT_SIZE
);
250 static_cast<sd::DrawViewShell
*>(pViewShell
)->ExecChar(aRequest
);
252 Scheduler::ProcessEventsToIdle();
253 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc
->GetUndoManager()->GetUndoActionCount());
254 CPPUNIT_ASSERT_EQUAL(u
"Apply attributes to Table"_ustr
,
255 pDoc
->GetUndoManager()->GetUndoActionComment(0));
256 CPPUNIT_ASSERT_EQUAL(u
"Grow font size"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment(1));
257 CPPUNIT_ASSERT_EQUAL(u
"Format cell"_ustr
, pDoc
->GetUndoManager()->GetUndoActionComment(2));
260 void SdMiscTest::testFillGradient()
262 createSdImpressDoc();
263 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
264 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
265 // Insert a new page.
266 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPages
->insertNewByIndex(0),
268 uno::Reference
<drawing::XShapes
> xShapes(xDrawPage
, uno::UNO_QUERY_THROW
);
269 // Create a rectangle
270 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
271 CPPUNIT_ASSERT(xFactory
.is());
272 uno::Reference
<drawing::XShape
> xShape1(
273 xFactory
->createInstance(u
"com.sun.star.drawing.RectangleShape"_ustr
),
274 uno::UNO_QUERY_THROW
);
275 uno::Reference
<beans::XPropertySet
> xPropSet(xShape1
, uno::UNO_QUERY_THROW
);
276 // Set FillStyle and FillGradient
277 awt::Gradient aGradient
;
278 aGradient
.StartColor
= sal_Int32(COL_LIGHTRED
);
279 aGradient
.EndColor
= sal_Int32(COL_LIGHTGREEN
);
280 xPropSet
->setPropertyValue(u
"FillStyle"_ustr
, uno::Any(drawing::FillStyle_GRADIENT
));
281 xPropSet
->setPropertyValue(u
"FillGradient"_ustr
, uno::Any(aGradient
));
282 // Add the rectangle to the page.
283 xShapes
->add(xShape1
);
285 // Retrieve the shape and check FillStyle and FillGradient
286 uno::Reference
<container::XIndexAccess
> xIndexAccess(xDrawPage
, uno::UNO_QUERY_THROW
);
287 uno::Reference
<beans::XPropertySet
> xPropSet2(xIndexAccess
->getByIndex(0),
288 uno::UNO_QUERY_THROW
);
289 drawing::FillStyle eFillStyle
;
290 awt::Gradient2 aGradient2
;
291 CPPUNIT_ASSERT(xPropSet2
->getPropertyValue(u
"FillStyle"_ustr
) >>= eFillStyle
);
292 CPPUNIT_ASSERT_EQUAL(int(drawing::FillStyle_GRADIENT
), static_cast<int>(eFillStyle
));
293 CPPUNIT_ASSERT(xPropSet2
->getPropertyValue(u
"FillGradient"_ustr
) >>= aGradient2
);
295 // MCGR: Use the completely imported gradient to check for correctness
296 const basegfx::BColorStops aColorStops
297 = model::gradient::getColorStopsFromUno(aGradient2
.ColorStops
);
299 CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops
.size());
300 CPPUNIT_ASSERT_EQUAL(0.0, aColorStops
[0].getStopOffset());
301 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, Color(aColorStops
[0].getStopColor()));
302 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops
[1].getStopOffset(), 1.0));
303 CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN
, Color(aColorStops
[1].getStopColor()));
306 void SdMiscTest::testTdf44774()
309 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
310 CPPUNIT_ASSERT(pXImpressDocument
);
311 sd::DrawDocShell
* pDocShell
= pXImpressDocument
->GetDocShell();
313 SfxStyleSheetBasePool
* pSSPool
= pDocShell
->GetStyleSheetPool();
315 // Create a new style with an empty name, like what happens in UI when creating a new style
316 SfxStyleSheetBase
& rStyleA
317 = pSSPool
->Make(u
""_ustr
, SfxStyleFamily::Para
, SfxStyleSearchBits::UserDefined
);
318 // Assign a new name, which does not yet set its ApiName
319 rStyleA
.SetName(u
"StyleA"_ustr
);
320 // Create another style
321 SfxStyleSheetBase
& rStyleB
322 = pSSPool
->Make(u
"StyleB"_ustr
, SfxStyleFamily::Para
, SfxStyleSearchBits::UserDefined
);
323 // ... and set its parent to the first one
324 rStyleB
.SetParent(u
"StyleA"_ustr
);
326 // Now save the file and reload
327 saveAndReload(u
"draw8"_ustr
);
328 pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
329 CPPUNIT_ASSERT(pXImpressDocument
);
330 pDocShell
= pXImpressDocument
->GetDocShell();
331 pSSPool
= pDocShell
->GetStyleSheetPool();
333 SfxStyleSheetBase
* pStyle
= pSSPool
->Find(u
"StyleB"_ustr
, SfxStyleFamily::Para
);
334 CPPUNIT_ASSERT(pStyle
);
335 // The parent set in StyleB used to reset, because parent style's msApiName was empty
336 CPPUNIT_ASSERT_EQUAL(u
"StyleA"_ustr
, pStyle
->GetParent());
339 void SdMiscTest::testTdf38225()
341 createSdImpressDoc();
342 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
343 CPPUNIT_ASSERT(pXImpressDocument
);
344 sd::DrawDocShell
* pDocShell
= pXImpressDocument
->GetDocShell();
346 SfxStyleSheetBasePool
* pSSPool
= pDocShell
->GetStyleSheetPool();
348 // Create a new style with a name
349 pSSPool
->Make(u
"StyleWithName1"_ustr
, SfxStyleFamily::Para
, SfxStyleSearchBits::UserDefined
);
351 // Now save the file and reload
352 saveAndReload(u
"draw8"_ustr
);
353 pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
354 CPPUNIT_ASSERT(pXImpressDocument
);
355 pDocShell
= pXImpressDocument
->GetDocShell();
356 pSSPool
= pDocShell
->GetStyleSheetPool();
358 SfxStyleSheetBase
* pStyle
= pSSPool
->Find(u
"StyleWithName1"_ustr
, SfxStyleFamily::Para
);
359 CPPUNIT_ASSERT(pStyle
);
362 CPPUNIT_ASSERT(pStyle
->SetName(u
"StyleWithName2"_ustr
));
364 // Save the file and reload again
365 saveAndReload(u
"draw8"_ustr
);
366 pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
367 CPPUNIT_ASSERT(pXImpressDocument
);
368 pDocShell
= pXImpressDocument
->GetDocShell();
369 pSSPool
= pDocShell
->GetStyleSheetPool();
371 // The problem was that the style kept the old name upon reloading
372 pStyle
= pSSPool
->Find(u
"StyleWithName1"_ustr
, SfxStyleFamily::Para
);
373 CPPUNIT_ASSERT(!pStyle
);
374 pStyle
= pSSPool
->Find(u
"StyleWithName2"_ustr
, SfxStyleFamily::Para
);
375 CPPUNIT_ASSERT(pStyle
);
378 void SdMiscTest::testTdf120527()
380 createSdImpressDoc();
382 // Load a bitmap into the bitmap table.
383 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
384 CPPUNIT_ASSERT(xFactory
.is());
385 uno::Reference
<container::XNameContainer
> xBitmaps(
386 xFactory
->createInstance(u
"com.sun.star.drawing.BitmapTable"_ustr
), uno::UNO_QUERY
);
387 CPPUNIT_ASSERT(xBitmaps
.is());
388 OUString aGraphicURL
= createFileURL(u
"tdf120527.jpg");
389 xBitmaps
->insertByName(u
"test"_ustr
, uno::Any(aGraphicURL
));
392 uno::Reference
<drawing::XShape
> xShape(
393 xFactory
->createInstance(u
"com.sun.star.drawing.GraphicObjectShape"_ustr
), uno::UNO_QUERY
);
394 CPPUNIT_ASSERT(xShape
.is());
395 uno::Reference
<beans::XPropertySet
> xShapeProperySet(xShape
, uno::UNO_QUERY
);
396 CPPUNIT_ASSERT(xShapeProperySet
.is());
397 xShapeProperySet
->setPropertyValue(u
"GraphicURL"_ustr
, xBitmaps
->getByName(u
"test"_ustr
));
400 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
401 CPPUNIT_ASSERT(xDrawPagesSupplier
.is());
402 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
403 CPPUNIT_ASSERT(xDrawPages
.is());
404 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPages
->getByIndex(0), uno::UNO_QUERY
);
405 CPPUNIT_ASSERT(xDrawPage
.is());
406 // This failed with a lang.IllegalArgumentException.
407 xDrawPage
->add(xShape
);
409 // Verify that the graphic was actually consumed.
410 uno::Reference
<graphic::XGraphic
> xGraphic
;
411 xShapeProperySet
->getPropertyValue(u
"Graphic"_ustr
) >>= xGraphic
;
412 CPPUNIT_ASSERT(xGraphic
.is());
415 // Testing document model part of editengine-columns
416 void SdMiscTest::testTextColumns()
418 createSdImpressDoc();
419 uno::Reference
<drawing::XDrawPagesSupplier
> xDrawPagesSupplier(mxComponent
, uno::UNO_QUERY
);
420 uno::Reference
<drawing::XDrawPages
> xDrawPages
= xDrawPagesSupplier
->getDrawPages();
421 // Insert a new page.
422 uno::Reference
<drawing::XDrawPage
> xDrawPage(xDrawPages
->insertNewByIndex(0),
424 uno::Reference
<drawing::XShapes
> xShapes(xDrawPage
, uno::UNO_QUERY_THROW
);
427 // Create a text shape
428 uno::Reference
<lang::XMultiServiceFactory
> xFactory(mxComponent
, uno::UNO_QUERY
);
429 CPPUNIT_ASSERT(xFactory
.is());
430 uno::Reference
<drawing::XShape
> xShape(
431 xFactory
->createInstance(u
"com.sun.star.drawing.TextShape"_ustr
), uno::UNO_QUERY_THROW
);
432 uno::Reference
<beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY_THROW
);
434 // Add the shape to the page.
435 xShapes
->add(xShape
);
438 auto pTextObj
= DynCastSdrTextObj(SdrObject::getSdrObjectFromXShape(xShape
));
439 CPPUNIT_ASSERT(pTextObj
);
440 pTextObj
->SetMergedItem(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER
, 2));
441 pTextObj
->SetMergedItem(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING
, 1000));
445 // Retrieve the shape and check columns
446 uno::Reference
<container::XIndexAccess
> xIndexAccess(xDrawPage
, uno::UNO_QUERY_THROW
);
447 uno::Reference
<drawing::XShape
> xShape(xIndexAccess
->getByIndex(0), uno::UNO_QUERY_THROW
);
449 auto pTextObj
= DynCastSdrTextObj(SdrObject::getSdrObjectFromXShape(xShape
));
450 CPPUNIT_ASSERT(pTextObj
);
452 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), pTextObj
->GetTextColumnsNumber());
453 CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), pTextObj
->GetTextColumnsSpacing());
457 /// Draw miscellaneous tests.
459 // Since LO 6.2 the visible/printable/locked information for layers is always
460 // written as ODF attributes draw:display and draw:protected. It is only read from
461 // there, if the config items VisibleLayers, PrintableLayers and LockedLayers do
462 // not exist. The user option WriteLayerStateAsConfigItem can be set to 'true' to
463 // write these config items in addition to the ODF attributes for to produce
464 // documents for older LO versions or Apache OpenOffice. With value 'false' no
465 // config items are written. The 'testTdf101242_xyz' tests combine source
466 // files with and without config items with option values 'true' and 'false'.
468 void SdMiscTest::testTdf101242_ODF_add_settings()
470 // Loads a document, which has the visible/printable/locked information for layers
471 // only in the ODF attributes draw:display and draw:protected. The resaved document
472 // should still have the ODF attributes and in addition the config items in settings.xml.
473 // "Load" is needed for to handle layers, simple "loadURL" does not work.
474 createSdDrawDoc("tdf101242_ODF.odg");
476 // Saving including items in settings.xml
477 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
478 comphelper::ConfigurationChanges::create());
479 officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, pBatch
);
483 // Verify, that the saved document still has the ODF attributes
484 xmlDocUniquePtr pXmlDoc
= parseExport(u
"styles.xml"_ustr
);
485 CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc
);
486 static constexpr OString
sPathStart(
487 "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr
);
489 sPathStart
+ "[@draw:name='backgroundobjects' and @draw:protected='true']");
490 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='controls' and @draw:display='screen']");
491 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='measurelines' and @draw:display='printer']");
493 // Verify, that the saved document has got the items in settings.xml
494 xmlDocUniquePtr pXmlDoc2
= parseExport(u
"settings.xml"_ustr
);
495 CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2
);
496 static constexpr OString
sPathStart2("/office:document-settings/office:settings/"
497 "config:config-item-set[@config:name='ooo:view-settings']/"
498 "config:config-item-map-indexed[@config:name='Views']/"
499 "config:config-item-map-entry"_ostr
);
500 // Value is a bitfield with first Byte in order '* * * measurelines controls backgroundobjects background layout'
501 // The first three bits depend on initialization and may change. The values in file are Base64 encoded.
503 uno::Sequence
<sal_Int8
> aDecodedSeq
;
504 sBase64
= getXPathContent(pXmlDoc2
,
505 sPathStart2
+ "/config:config-item[@config:name='VisibleLayers']");
506 CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64
.isEmpty());
507 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
508 CPPUNIT_ASSERT_EQUAL(0x0F, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
510 sBase64
= getXPathContent(pXmlDoc2
,
511 sPathStart2
+ "/config:config-item[@config:name='PrintableLayers']");
512 CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64
.isEmpty());
513 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
514 CPPUNIT_ASSERT_EQUAL(0x17, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
516 sBase64
= getXPathContent(pXmlDoc2
,
517 sPathStart2
+ "/config:config-item[@config:name='LockedLayers']");
518 CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64
.isEmpty());
519 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
520 CPPUNIT_ASSERT_EQUAL(0x04, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
523 void SdMiscTest::testTdf101242_ODF_no_settings()
525 // Loads a document, which has the visible/printable/locked information for layers
526 // only in the ODF attributes draw:display and draw:protected. The resave document
527 // should have only the ODF attributes and no config items in settings.xml.
528 createSdDrawDoc("tdf101242_ODF.odg");
530 // Saving without items in settings.xml
531 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
532 comphelper::ConfigurationChanges::create());
533 officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(false, pBatch
);
537 // Verify, that the saved document still has the ODF attributes
538 xmlDocUniquePtr pXmlDoc
= parseExport(u
"styles.xml"_ustr
);
539 CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc
);
540 static constexpr OString
sPathStart(
541 "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr
);
543 sPathStart
+ "[@draw:name='backgroundobjects' and @draw:protected='true']");
544 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='controls' and @draw:display='screen']");
545 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='measurelines' and @draw:display='printer']");
547 // Verify, that the saved document has no layer items in settings.xml
548 xmlDocUniquePtr pXmlDoc2
= parseExport(u
"settings.xml"_ustr
);
549 CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2
);
550 static constexpr OString
sPathStart2("/office:document-settings/office:settings/"
551 "config:config-item-set[@config:name='ooo:view-settings']/"
552 "config:config-item-map-indexed[@config:name='Views']/"
553 "config:config-item-map-entry"_ostr
);
554 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='VisibleLayers']", 0);
555 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='PrintableLayers']", 0);
556 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='LockedLayers']", 0);
559 void SdMiscTest::testTdf101242_settings_keep()
561 // Loads a document, which has the visible/printable/locked information for layers
562 // only in the config items in settings.xml. That is the case for all old documents.
563 // The resaved document should have the ODF attributes draw:display and draw:protected
564 // and should still have these config items in settings.xml.
565 createSdDrawDoc("tdf101242_settings.odg");
567 // Saving including items in settings.xml
568 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
569 comphelper::ConfigurationChanges::create());
570 officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, pBatch
);
574 // Verify, that the saved document has the ODF attributes
575 xmlDocUniquePtr pXmlDoc
= parseExport(u
"styles.xml"_ustr
);
576 CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc
);
577 static constexpr OString
sPathStart(
578 "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr
);
580 sPathStart
+ "[@draw:name='backgroundobjects' and @draw:protected='true']");
581 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='controls' and @draw:display='screen']");
582 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='measurelines' and @draw:display='printer']");
584 // Verify, that the saved document still has the items in settings.xml
585 xmlDocUniquePtr pXmlDoc2
= parseExport(u
"settings.xml"_ustr
);
586 CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2
);
587 static constexpr OString
sPathStart2("/office:document-settings/office:settings/"
588 "config:config-item-set[@config:name='ooo:view-settings']/"
589 "config:config-item-map-indexed[@config:name='Views']/"
590 "config:config-item-map-entry"_ostr
);
591 // Value is a bitfield with first Byte in order '* * * measurelines controls backgroundobjects background layout'
592 // The first three bits depend on initialization and may change. The values in file are Base64 encoded.
594 uno::Sequence
<sal_Int8
> aDecodedSeq
;
595 sBase64
= getXPathContent(pXmlDoc2
,
596 sPathStart2
+ "/config:config-item[@config:name='VisibleLayers']");
597 CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64
.isEmpty());
598 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
599 CPPUNIT_ASSERT_EQUAL(0x0F, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
601 sBase64
= getXPathContent(pXmlDoc2
,
602 sPathStart2
+ "/config:config-item[@config:name='PrintableLayers']");
603 CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64
.isEmpty());
604 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
605 CPPUNIT_ASSERT_EQUAL(0x17, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
607 sBase64
= getXPathContent(pXmlDoc2
,
608 sPathStart2
+ "/config:config-item[@config:name='LockedLayers']");
609 CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64
.isEmpty());
610 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
611 CPPUNIT_ASSERT_EQUAL(0x04, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0x1F);
614 void SdMiscTest::testTdf101242_settings_remove()
616 // Loads a document, which has the visible/printable/locked information for layers
617 // only in the config items in settings.xml. That is the case for all old documents.
618 // The resaved document should have only the ODF attributes draw:display and draw:protected
619 // and should have no config items in settings.xml.
620 createSdDrawDoc("tdf101242_settings.odg");
622 // Saving without config items in settings.xml
623 std::shared_ptr
<comphelper::ConfigurationChanges
> pBatch(
624 comphelper::ConfigurationChanges::create());
625 officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(false, pBatch
);
629 // Verify, that the saved document has the ODF attributes
630 xmlDocUniquePtr pXmlDoc
= parseExport(u
"styles.xml"_ustr
);
631 CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc
);
632 static constexpr OString
sPathStart(
633 "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr
);
635 sPathStart
+ "[@draw:name='backgroundobjects' and @draw:protected='true']");
636 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='controls' and @draw:display='screen']");
637 assertXPath(pXmlDoc
, sPathStart
+ "[@draw:name='measurelines' and @draw:display='printer']");
639 // Verify, that the saved document has no layer items in settings.xml
640 xmlDocUniquePtr pXmlDoc2
= parseExport(u
"settings.xml"_ustr
);
641 CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2
);
642 static constexpr OString
sPathStart2("/office:document-settings/office:settings/"
643 "config:config-item-set[@config:name='ooo:view-settings']/"
644 "config:config-item-map-indexed[@config:name='Views']/"
645 "config:config-item-map-entry"_ostr
);
646 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='VisibleLayers']", 0);
647 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='PrintableLayers']", 0);
648 assertXPath(pXmlDoc2
, sPathStart2
+ "/config:config-item[@config:name='LockedLayers']", 0);
651 void SdMiscTest::testTdf119392()
653 // Loads a document which has two user layers "V--" and "V-L". Inserts a new layer "-P-" between them.
654 // Checks, that the bitfields in the saved file have the bits in the correct order, in case
655 // option WriteLayerAsConfigItem is true and the config items are written.
656 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(
657 comphelper::ConfigurationChanges::create());
658 officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, batch
);
661 createSdDrawDoc("tdf119392_InsertLayer.odg");
662 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
663 CPPUNIT_ASSERT(pXImpressDocument
);
664 // Insert layer "-P-", not visible, printable, not locked
665 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
666 SdrView
* pView
= pViewShell
->GetView();
667 pView
->InsertNewLayer(u
"-P-"_ustr
, 6); // 0..4 standard layer, 5 layer "V--"
668 SdrPageView
* pPageView
= pView
->GetSdrPageView();
669 pPageView
->SetLayerVisible(u
"-P-"_ustr
, false);
670 pPageView
->SetLayerPrintable(u
"-P-"_ustr
, true);
671 pPageView
->SetLayerLocked(u
"-P-"_ustr
, false);
674 // Verify correct bit order in bitfield in the config items in settings.xml
675 xmlDocUniquePtr pXmlDoc
= parseExport(u
"settings.xml"_ustr
);
676 CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc
);
677 static constexpr OString
sPathStart("/office:document-settings/office:settings/"
678 "config:config-item-set[@config:name='ooo:view-settings']/"
679 "config:config-item-map-indexed[@config:name='Views']/"
680 "config:config-item-map-entry"_ostr
);
681 // First Byte is in order 'V-L -P- V-- measurelines controls backgroundobjects background layout'
682 // Bits need to be: visible=10111111=0xbf=191 printable=01011111=0x5f=95 locked=10000000=0x80=128
683 // The values in file are Base64 encoded.
685 uno::Sequence
<sal_Int8
> aDecodedSeq
;
686 sBase64
= getXPathContent(pXmlDoc
,
687 sPathStart
+ "/config:config-item[@config:name='VisibleLayers']");
688 CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64
.isEmpty());
689 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
690 CPPUNIT_ASSERT_EQUAL(0xbF,
691 static_cast<sal_uInt8
>(aDecodedSeq
[0])
692 & 0xff); // & 0xff forces unambiguous types for CPPUNIT_ASSERT_EQUAL
694 sBase64
= getXPathContent(pXmlDoc
,
695 sPathStart
+ "/config:config-item[@config:name='PrintableLayers']");
696 CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64
.isEmpty());
697 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
698 CPPUNIT_ASSERT_EQUAL(0x5f, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0xff);
701 = getXPathContent(pXmlDoc
, sPathStart
+ "/config:config-item[@config:name='LockedLayers']");
702 CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64
.isEmpty());
703 comphelper::Base64::decode(aDecodedSeq
, sBase64
);
704 CPPUNIT_ASSERT_EQUAL(0x80, static_cast<sal_uInt8
>(aDecodedSeq
[0]) & 0xff);
707 void SdMiscTest::testTdf67248()
709 // The document tdf67248.odg has been created with a German UI. It has a user layer named "Background".
710 // On opening the user layer must still exists. The error was, that it was merged into the standard
711 // layer "background".
712 createSdDrawDoc("tdf67248.odg");
713 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
714 CPPUNIT_ASSERT(pXImpressDocument
);
715 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
716 SdrLayerAdmin
& rLayerAdmin
= pDoc
->GetLayerAdmin();
717 CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), rLayerAdmin
.GetLayerCount());
720 void SdMiscTest::testTdf119956()
722 createSdDrawDoc("tdf119956.odg");
723 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
724 CPPUNIT_ASSERT(pXImpressDocument
);
725 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
727 sd::GraphicViewShell
* pGraphicViewShell
= static_cast<sd::GraphicViewShell
*>(pViewShell
);
728 CPPUNIT_ASSERT(pGraphicViewShell
);
729 sd::LayerTabBar
* pLayerTabBar
= pGraphicViewShell
->GetLayerTabControl();
730 CPPUNIT_ASSERT(pLayerTabBar
);
731 pLayerTabBar
->StateChanged(StateChangedType::InitShow
);
733 // Alt+Click sets a tab in edit mode, so that you can rename it.
734 // The error was, that Alt+Click on a tab, which was not the current tab, did not set the clicked tab
735 // as current tab. As a result, the entered text was applied to the wrong tab.
737 // The test document has the layer tabs "layout", "controls", "measurelines" and "Layer4" in this order
738 // The "pagePos" is 0, 1, 2, 3
739 // Make sure, that tab "layout" is the current tab.
740 MouseEvent aSyntheticMouseEvent
;
741 if (pLayerTabBar
->GetCurPagePos() != 0)
743 sal_uInt16
nIdOfTabPos0(pLayerTabBar
->GetPageId(0));
744 tools::Rectangle
aTabPos0Rect(pLayerTabBar
->GetPageRect(nIdOfTabPos0
));
746 = MouseEvent(aTabPos0Rect
.Center(), 1, MouseEventModifiers::SYNTHETIC
, MOUSE_LEFT
, 0);
747 pLayerTabBar
->MouseButtonDown(aSyntheticMouseEvent
);
749 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pLayerTabBar
->GetCurPagePos());
751 // Alt+Click on tab "Layer4"
752 sal_uInt16
nIdOfTabPos3(pLayerTabBar
->GetPageId(3));
753 tools::Rectangle
aTabPos3Rect(pLayerTabBar
->GetPageRect(nIdOfTabPos3
));
754 aSyntheticMouseEvent
= MouseEvent(aTabPos3Rect
.Center(), 1, MouseEventModifiers::SYNTHETIC
,
755 MOUSE_LEFT
, KEY_MOD2
);
756 pLayerTabBar
->MouseButtonDown(aSyntheticMouseEvent
);
758 // Make sure, tab 3 is current tab now.
759 CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pLayerTabBar
->GetCurPagePos());
762 void SdMiscTest::testTdf98839_ShearVFlipH()
764 // Loads a document with a sheared shape and mirrors it
765 createSdDrawDoc("tdf98839_ShearVFlipH.odg");
766 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
767 CPPUNIT_ASSERT(pXImpressDocument
);
768 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
769 SdPage
* pPage
= pViewShell
->GetActualPage();
770 SdrObjCustomShape
* pShape
= static_cast<SdrObjCustomShape
*>(pPage
->GetObj(0));
771 pShape
->Mirror(Point(4000, 2000), Point(4000, 10000));
773 // Save and examine attribute draw:transform
775 xmlDocUniquePtr pXmlDoc
= parseExport(u
"content.xml"_ustr
);
776 CPPUNIT_ASSERT_MESSAGE("Failed to get 'content.xml'", pXmlDoc
);
777 static constexpr OString
sPathStart(
778 "/office:document-content/office:body/office:drawing/draw:page"_ostr
);
779 assertXPath(pXmlDoc
, sPathStart
);
780 const OUString sTransform
= getXPath(pXmlDoc
, sPathStart
+ "/draw:custom-shape", "transform");
782 // Error was, that the shear angle had a wrong sign.
783 CPPUNIT_ASSERT_MESSAGE("expected: draw:transform='skewX (-0.64350...)",
784 sTransform
.startsWith("skewX (-"));
787 void SdMiscTest::testTdf130988()
789 createSdDrawDoc("tdf130988_3D_create_lathe.odg");
790 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
791 CPPUNIT_ASSERT(pXImpressDocument
);
793 //emulate command .uno:ConvertInto3DLathe
794 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
795 E3dView
* pView
= pViewShell
->GetView();
796 pView
->MarkNextObj();
797 pView
->ConvertMarkedObjTo3D(false, basegfx::B2DPoint(8000.0, -3000.0),
798 basegfx::B2DPoint(3000.0, -8000.0));
800 = dynamic_cast<E3dScene
*>(pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj());
801 CPPUNIT_ASSERT(pObj
);
803 // Error was, that the created 3D object had a wrong path. Instead examining
804 // the path directly, I use the scene distance, because that is easier. The
805 // scene distance is calculated from the object while creating.
806 const double fDistance
= pObj
->GetDistance();
807 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("D3DSceneDistance", 7071.0, fDistance
, 0.5);
810 void SdMiscTest::testTdf131033()
812 createSdDrawDoc("tdf131033_3D_SceneSizeIn2d.odg");
813 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
814 CPPUNIT_ASSERT(pXImpressDocument
);
816 // The document contains a polygon, so that emulate command .uno:ConvertInto3DLathe
817 // by direct call of ConvertMarkedObjTo3D works.
818 // It produces a rotation around a vertical axis, which is far away from the
820 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
821 E3dView
* pView
= pViewShell
->GetView();
822 pView
->MarkNextObj();
823 pView
->ConvertMarkedObjTo3D(false, basegfx::B2DPoint(11000.0, -5000.0),
824 basegfx::B2DPoint(11000.0, -9000.0));
826 = dynamic_cast<E3dScene
*>(pView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj());
827 CPPUNIT_ASSERT(pObj
);
829 // Error was, that the 2D representation of the scene did not contain the default 20°
830 // rotation of the new scene around x-axis and therefore was not high enough.
831 const double fSnapRectHeight
= pObj
->GetSnapRect().getOpenHeight();
832 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("2D height", 7096.0, fSnapRectHeight
, 1.0);
835 void SdMiscTest::testTdf129898LayerDrawnInSlideshow()
837 // Versions LO 6.2 to 6.4 have produced files, where the layer DrawnInSlideshow has
838 // got visible=false and printable=false attributes. Those files should be repaired now.
839 createSdImpressDoc("tdf129898_faulty_DrawnInSlideshow.odp");
840 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
841 CPPUNIT_ASSERT(pXImpressDocument
);
842 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
845 static constexpr OUString sName
= u
"DrawnInSlideshow"_ustr
;
846 SdrLayerAdmin
& rLayerAdmin
= pDoc
->GetLayerAdmin();
847 SdrLayer
* pLayer
= rLayerAdmin
.GetLayer(sName
);
848 CPPUNIT_ASSERT_MESSAGE("No layer DrawnInSlideshow", pLayer
);
849 CPPUNIT_ASSERT(pLayer
->IsVisibleODF());
850 CPPUNIT_ASSERT(pLayer
->IsPrintableODF());
853 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
854 SdrPageView
* pPageView
= pViewShell
->GetView()->GetSdrPageView();
855 CPPUNIT_ASSERT(pPageView
->IsLayerVisible(sName
));
856 CPPUNIT_ASSERT(pPageView
->IsLayerPrintable(sName
));
859 void SdMiscTest::testTdf136956()
861 createSdImpressDoc("odp/cellspan.odp");
862 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
863 CPPUNIT_ASSERT(pXImpressDocument
);
865 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
866 const SdrPage
* pPage
= pDoc
->GetPage(1);
867 sdr::table::SdrTableObj
* pTableObj
= dynamic_cast<sdr::table::SdrTableObj
*>(pPage
->GetObj(0));
868 CPPUNIT_ASSERT(pTableObj
);
869 uno::Reference
<table::XTable
> xTable(pTableObj
->getTable(), uno::UNO_SET_THROW
);
871 uno::Reference
<css::table::XMergeableCellRange
> xRange(
872 xTable
->createCursorByRange(xTable
->getCellRangeByPosition(0, 0, 3, 2)),
873 uno::UNO_QUERY_THROW
);
875 // 4x3 Table before merge.
876 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable
->getColumnCount());
877 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable
->getRowCount());
881 // 1x1 Table after merge.
882 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getColumnCount());
883 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTable
->getRowCount());
885 pXImpressDocument
->GetDocShell()->GetUndoManager()->Undo();
887 // 4x3 Table after undo. Undo crashed before.
888 CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xTable
->getColumnCount());
889 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xTable
->getRowCount());
892 void SdMiscTest::testTdf39519()
894 createSdImpressDoc();
895 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
896 CPPUNIT_ASSERT(pXImpressDocument
);
898 // Change the name of the first page in the newly created document
899 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
900 SdPage
* pPage
= static_cast<SdPage
*>(pDoc
->GetPage(1));
901 pPage
->SetName(u
"Test"_ustr
);
903 // Insert a bookmark as a new page using the same name
904 std::vector
<OUString
> aBookmarkList
= { u
"Test"_ustr
};
905 pDoc
->InsertBookmarkAsPage(aBookmarkList
, nullptr, false, false, 2, true, pDoc
->GetDocSh(),
908 // Check if the copied page has a different name
909 SdPage
* pCopiedPage
= static_cast<SdPage
*>(pDoc
->GetPage(2));
910 // Without the fix in place, the names of the pages would not be different
911 CPPUNIT_ASSERT(pCopiedPage
->GetName() != pPage
->GetName());
914 void SdMiscTest::testTdf164284()
916 createSdImpressDoc();
917 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
918 CPPUNIT_ASSERT(pXImpressDocument
);
920 // Change the name of the first page in the newly created document
921 SdDrawDocument
* pDoc
= pXImpressDocument
->GetDoc();
922 SdPage
* pPage
= static_cast<SdPage
*>(pDoc
->GetPage(1));
923 pPage
->SetName(u
"Test"_ustr
);
925 // Move a bookmark as a page using the same name
926 pDoc
->DoMakePageObjectsNamesUnique(false);
927 std::vector
<OUString
> aBookmarkList
= { u
"Test"_ustr
};
928 pDoc
->InsertBookmarkAsPage(aBookmarkList
, nullptr, false, false, 2, true, pDoc
->GetDocSh(),
931 // Check if the moved page has the same name
932 SdPage
* pMovedPage
= static_cast<SdPage
*>(pDoc
->GetPage(2));
933 // Without the fix in place, the names of the pages would be different
934 CPPUNIT_ASSERT_EQUAL(pPage
->GetName(), pMovedPage
->GetName());
937 void SdMiscTest::testEncodedTableStyles()
939 // Silence unrelated failure:
940 // Error: element "table:table-template" is missing "first-row-start-column" attribute
946 uno::Reference
<style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier(mxComponent
,
947 uno::UNO_QUERY_THROW
);
948 uno::Reference
<css::lang::XSingleServiceFactory
> xTableStyleFamily(
949 xStyleFamiliesSupplier
->getStyleFamilies()->getByName(u
"table"_ustr
),
950 uno::UNO_QUERY_THROW
);
951 uno::Reference
<css::lang::XSingleServiceFactory
> xCellStyleFamily(
952 xStyleFamiliesSupplier
->getStyleFamilies()->getByName(u
"cell"_ustr
),
953 uno::UNO_QUERY_THROW
);
955 uno::Reference
<style::XStyle
> xTableStyle(xTableStyleFamily
->createInstance(),
956 uno::UNO_QUERY_THROW
);
957 uno::Reference
<style::XStyle
> xCellStyle(xCellStyleFamily
->createInstance(),
958 uno::UNO_QUERY_THROW
);
960 uno::Reference
<container::XNameContainer
>(xTableStyleFamily
, uno::UNO_QUERY_THROW
)
961 ->insertByName(u
"table_1"_ustr
, uno::Any(xTableStyle
));
962 uno::Reference
<container::XNameContainer
>(xCellStyleFamily
, uno::UNO_QUERY_THROW
)
963 ->insertByName(u
"table-body_1"_ustr
, uno::Any(xCellStyle
));
964 uno::Reference
<container::XNameReplace
>(xTableStyle
, uno::UNO_QUERY_THROW
)
965 ->replaceByName(u
"body"_ustr
, uno::Any(xCellStyle
));
968 saveAndReload(u
"draw8"_ustr
);
971 uno::Reference
<style::XStyleFamiliesSupplier
> xStyleFamiliesSupplier(mxComponent
,
972 uno::UNO_QUERY_THROW
);
973 uno::Reference
<container::XNameAccess
> xTableStyleFamily(
974 xStyleFamiliesSupplier
->getStyleFamilies()->getByName(u
"table"_ustr
),
975 uno::UNO_QUERY_THROW
);
976 // Such style used to be exported as "table_5f_1" instead.
977 CPPUNIT_ASSERT(xTableStyleFamily
->hasByName(u
"table_1"_ustr
));
979 uno::Reference
<container::XNameAccess
> xTableStyle(
980 xTableStyleFamily
->getByName(u
"table_1"_ustr
), uno::UNO_QUERY_THROW
);
981 uno::Reference
<style::XStyle
> xCellStyle(xTableStyle
->getByName(u
"body"_ustr
),
983 // Such style used to not be found by the table style, as it was
984 // searching for "table-body_5f_1" instead of "table-body_1".
985 CPPUNIT_ASSERT(xCellStyle
.is());
986 CPPUNIT_ASSERT_EQUAL(u
"table-body_1"_ustr
, xCellStyle
->getName());
990 void SdMiscTest::testTdf157117()
992 createSdImpressDoc();
993 SdXImpressDocument
* pXImpressDocument
= dynamic_cast<SdXImpressDocument
*>(mxComponent
.get());
994 CPPUNIT_ASSERT(pXImpressDocument
);
995 sd::ViewShell
* pViewShell
= pXImpressDocument
->GetDocShell()->GetViewShell();
997 // insert two pages to make a total of 3 pages
998 dispatchCommand(mxComponent
, u
".uno:InsertPage"_ustr
, {});
999 dispatchCommand(mxComponent
, u
".uno:InsertPage"_ustr
, {});
1001 // assert the document has 3 standard pages
1002 SdDrawDocument
* pDocument
= pXImpressDocument
->GetDoc();
1003 CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pDocument
->GetSdPageCount(PageKind::Standard
));
1005 // alternate page insert method
1006 // uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
1007 // uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages();
1008 // xDrawPages->insertNewByIndex(0);
1009 // xDrawPages->insertNewByIndex(0);
1010 // CPPUNIT_ASSERT_EQUAL(xDrawPages->getCount(), 3);
1012 // move to the last page
1013 dispatchCommand(mxComponent
, u
".uno:LastPage"_ustr
, {});
1015 SdPage
* pPage
= pViewShell
->GetActualPage();
1016 auto nPageNum
= pPage
->GetPageNum();
1017 // assert move to last page
1018 CPPUNIT_ASSERT_EQUAL(2, (nPageNum
- 1) / 2);
1020 // delete the last page
1021 dispatchCommand(mxComponent
, u
".uno:DeletePage"_ustr
, {});
1022 pPage
= pViewShell
->GetActualPage();
1023 nPageNum
= pPage
->GetPageNum();
1025 // Check that the new last page is moved to. Before, the first page was always moved to when
1026 // the last page was deleted.
1027 CPPUNIT_ASSERT_EQUAL(1, (nPageNum
- 1) / 2);
1030 CPPUNIT_TEST_SUITE_REGISTRATION(SdMiscTest
);
1032 CPPUNIT_PLUGIN_IMPLEMENT();
1034 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */