/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); // Make sure that the undo stack is empty.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc->GetUndoManager()->GetUndoActionCount());
// Set the vertical alignment of the cells to bottom.
sdr::table::SvxTableController* pTableController
= dynamic_cast<sdr::table::SvxTableController*>(pView->getSelectionController().get());
CPPUNIT_ASSERT(pTableController);
SfxRequest aRequest(*pViewShell->GetViewFrame(), SID_TABLE_VERT_BOTTOM);
pTableController->Execute(aRequest); // This was 0, it wasn't possible to undo a vertical alignment change.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pDoc->GetUndoManager()->GetUndoActionCount());
}
void SdMiscTest::testTableObjectUndoTest()
{ // See tdf#99396 for the issue
// Load the document and select the table.
createSdImpressDoc("tdf99396.odp");
SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pPage = pViewShell->GetActualPage(); auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pPage->GetObj(0));
CPPUNIT_ASSERT(pTableObject);
SdrView* pView = pViewShell->GetView();
pView->MarkObj(pTableObject, pView->GetSdrPageView());
SdDrawDocument* pDoc = pXImpressDocument->GetDoc(); // Make sure that the undo stack is empty.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pDoc->GetUndoManager()->GetUndoActionCount());
// Set horizontal and vertical adjustment during text edit.
pView->SdrBeginTextEdit(pTableObject);
CPPUNIT_ASSERT(pView->GetTextEditObject());
{
SfxRequest aRequest(*pViewShell->GetViewFrame(), SID_ATTR_PARA_ADJUST_RIGHT);
SfxItemSet aEditAttr(pDoc->GetPool());
pView->GetAttributes(aEditAttr);
SfxItemSet aNewAttr(*(aEditAttr.GetPool()), aEditAttr.GetRanges());
aNewAttr.Put(SvxAdjustItem(SvxAdjust::Right, EE_PARA_JUST));
aRequest.Done(aNewAttr); const SfxItemSet* pArgs = aRequest.GetArgs();
pView->SetAttributes(*pArgs);
} constauto& pLocalUndoManager = pView->getViewLocalUndoManager();
CPPUNIT_ASSERT_EQUAL(size_t(1), pLocalUndoManager->GetUndoActionCount());
CPPUNIT_ASSERT_EQUAL(u"Apply attributes"_ustr, pLocalUndoManager->GetUndoActionComment());
{ auto pTableController
= dynamic_cast<sdr::table::SvxTableController*>(pView->getSelectionController().get());
CPPUNIT_ASSERT(pTableController);
SfxRequest aRequest(*pViewShell->GetViewFrame(), SID_TABLE_VERT_BOTTOM);
pTableController->Execute(aRequest);
} // Global change "Format cell" is applied only - Change the vertical alignment to "Bottom"
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetUndoManager()->GetUndoActionCount());
CPPUNIT_ASSERT_EQUAL(u"Format cell"_ustr, pDoc->GetUndoManager()->GetUndoActionComment());
pView->SdrEndTextEdit();
// End of text edit, so the text edit action is added to the undo stack
CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetUndoManager()->GetUndoActionCount());
CPPUNIT_ASSERT_EQUAL(u"Edit text of Table"_ustr,
pDoc->GetUndoManager()->GetUndoActionComment(0));
CPPUNIT_ASSERT_EQUAL(u"Format cell"_ustr, pDoc->GetUndoManager()->GetUndoActionComment(1));
// Check that the result is what we expect.
{
uno::Reference<table::XTable> xTable = pTableObject->getTable();
uno::Reference<beans::XPropertySet> xCell(xTable->getCellByPosition(0, 0), uno::UNO_QUERY);
drawing::TextVerticalAdjust eAdjust = xCell->getPropertyValue(u"TextVerticalAdjust"_ustr)
.get<drawing::TextVerticalAdjust>();
CPPUNIT_ASSERT_EQUAL(int(drawing::TextVerticalAdjust_BOTTOM), static_cast<int>(eAdjust));
}
{ const EditTextObject& rEdit
= pTableObject->getText(0)->GetOutlinerParaObject()->GetTextObject(); const SfxItemSet& rParaAttribs = rEdit.GetParaAttribs(0); auto pAdjust = rParaAttribs.GetItem(EE_PARA_JUST);
CPPUNIT_ASSERT_EQUAL(SvxAdjust::Right, pAdjust->GetAdjust());
}
// Now undo.
pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
// Undoing the last action - one left
CPPUNIT_ASSERT_EQUAL(size_t(1), pDoc->GetUndoManager()->GetUndoActionCount());
CPPUNIT_ASSERT_EQUAL(u"Format cell"_ustr, pDoc->GetUndoManager()->GetUndoActionComment(0));
// Check again that the result is what we expect.
{
uno::Reference<table::XTable> xTable = pTableObject->getTable();
uno::Reference<beans::XPropertySet> xCell(xTable->getCellByPosition(0, 0), uno::UNO_QUERY);
drawing::TextVerticalAdjust eAdjust = xCell->getPropertyValue(u"TextVerticalAdjust"_ustr)
.get<drawing::TextVerticalAdjust>(); // This failed: Undo() did not change it from drawing::TextVerticalAdjust_BOTTOM.
CPPUNIT_ASSERT_EQUAL(int(drawing::TextVerticalAdjust_TOP), static_cast<int>(eAdjust));
}
{ const EditTextObject& rEdit
= pTableObject->getText(0)->GetOutlinerParaObject()->GetTextObject(); const SfxItemSet& rParaAttribs = rEdit.GetParaAttribs(0); auto pAdjust = rParaAttribs.GetItem(EE_PARA_JUST);
CPPUNIT_ASSERT_EQUAL(SvxAdjust::Center, pAdjust->GetAdjust());
}
/* * now test tdf#103950 - Undo does not revert bundled font size changes for table cells
*/
pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pPage->GetObj(0));
pView->MarkObj(pTableObject, pView->GetSdrPageView()); // select table
{
SfxRequest aRequest(*pViewShell->GetViewFrame(), SID_GROW_FONT_SIZE); static_cast<sd::DrawViewShell*>(pViewShell)->ExecChar(aRequest);
}
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pDoc->GetUndoManager()->GetUndoActionCount());
CPPUNIT_ASSERT_EQUAL(u"Apply attributes to Table"_ustr,
pDoc->GetUndoManager()->GetUndoActionComment(0));
CPPUNIT_ASSERT_EQUAL(u"Grow font size"_ustr, pDoc->GetUndoManager()->GetUndoActionComment(1));
CPPUNIT_ASSERT_EQUAL(u"Format cell"_ustr, pDoc->GetUndoManager()->GetUndoActionComment(2));
}
void SdMiscTest::testFillColor()
{ // Test if setting the shape fill color from color to transparent automatically turns off the fill style to none
createSdImpressDoc();
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); // Insert a new page.
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->insertNewByIndex(0),
uno::UNO_SET_THROW);
uno::Reference<drawing::XShapes> xShapes(xDrawPage, uno::UNO_QUERY_THROW); // Create a rectangle
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT(xFactory.is());
uno::Reference<drawing::XShape> xShape1(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr),
uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xPropSet(xShape1, uno::UNO_QUERY_THROW); // Set FillStyle and FillColor
xPropSet->setPropertyValue(u"FillStyle"_ustr, uno::Any(drawing::FillStyle_SOLID));
xPropSet->setPropertyValue(u"FillColor"_ustr, uno::Any(COL_RED)); // Add the rectangle to the page.
xShapes->add(xShape1);
// Retrieve the shape and check FillStyle and FillGradient
uno::Reference<container::XIndexAccess> xIndexAccess(xDrawPage, uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xPropSet2(xIndexAccess->getByIndex(0),
uno::UNO_QUERY_THROW);
drawing::FillStyle eFillStyle;
Color aColor;
CPPUNIT_ASSERT(xPropSet2->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle);
CPPUNIT_ASSERT_EQUAL(int(drawing::FillStyle_SOLID), static_cast<int>(eFillStyle));
CPPUNIT_ASSERT(xPropSet2->getPropertyValue(u"FillColor"_ustr) >>= aColor);
CPPUNIT_ASSERT_EQUAL(COL_RED, aColor);
// Setup transparent color and check fill styles
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<view::XSelectionSupplier> xSelectionSupplier(xModel->getCurrentController(),
uno::UNO_QUERY);
void SdMiscTest::testFillGradient()
{
createSdImpressDoc();
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); // Insert a new page.
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->insertNewByIndex(0),
uno::UNO_SET_THROW);
uno::Reference<drawing::XShapes> xShapes(xDrawPage, uno::UNO_QUERY_THROW); // Create a rectangle
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT(xFactory.is());
uno::Reference<drawing::XShape> xShape1(
xFactory->createInstance(u"com.sun.star.drawing.RectangleShape"_ustr),
uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xPropSet(xShape1, uno::UNO_QUERY_THROW); // Set FillStyle and FillGradient
awt::Gradient aGradient;
aGradient.StartColor = sal_Int32(COL_LIGHTRED);
aGradient.EndColor = sal_Int32(COL_LIGHTGREEN);
xPropSet->setPropertyValue(u"FillStyle"_ustr, uno::Any(drawing::FillStyle_GRADIENT));
xPropSet->setPropertyValue(u"FillGradient"_ustr, uno::Any(aGradient)); // Add the rectangle to the page.
xShapes->add(xShape1);
// Retrieve the shape and check FillStyle and FillGradient
uno::Reference<container::XIndexAccess> xIndexAccess(xDrawPage, uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xPropSet2(xIndexAccess->getByIndex(0),
uno::UNO_QUERY_THROW);
drawing::FillStyle eFillStyle;
awt::Gradient2 aGradient2;
CPPUNIT_ASSERT(xPropSet2->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle);
CPPUNIT_ASSERT_EQUAL(int(drawing::FillStyle_GRADIENT), static_cast<int>(eFillStyle));
CPPUNIT_ASSERT(xPropSet2->getPropertyValue(u"FillGradient"_ustr) >>= aGradient2);
// MCGR: Use the completely imported gradient to check for correctness const basegfx::BColorStops aColorStops
= model::gradient::getColorStopsFromUno(aGradient2.ColorStops);
// Create a new style with an empty name, like what happens in UI when creating a new style
SfxStyleSheetBase& rStyleA
= pSSPool->Make(u""_ustr, SfxStyleFamily::Para, SfxStyleSearchBits::UserDefined); // Assign a new name, which does not yet set its ApiName
rStyleA.SetName(u"StyleA"_ustr); // Create another style
SfxStyleSheetBase& rStyleB
= pSSPool->Make(u"StyleB"_ustr, SfxStyleFamily::Para, SfxStyleSearchBits::UserDefined); // ... and set its parent to the first one
rStyleB.SetParent(u"StyleA"_ustr);
// Now save the file and reload
saveAndReload(u"draw8"_ustr);
pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
pDocShell = pXImpressDocument->GetDocShell();
pSSPool = pDocShell->GetStyleSheetPool();
SfxStyleSheetBase* pStyle = pSSPool->Find(u"StyleB"_ustr, SfxStyleFamily::Para);
CPPUNIT_ASSERT(pStyle); // The parent set in StyleB used to reset, because parent style's msApiName was empty
CPPUNIT_ASSERT_EQUAL(u"StyleA"_ustr, pStyle->GetParent());
}
// Create a new style with a name
pSSPool->Make(u"StyleWithName1"_ustr, SfxStyleFamily::Para, SfxStyleSearchBits::UserDefined);
// Now save the file and reload
saveAndReload(u"draw8"_ustr);
pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
pDocShell = pXImpressDocument->GetDocShell();
pSSPool = pDocShell->GetStyleSheetPool();
// Rename the style
CPPUNIT_ASSERT(pStyle->SetName(u"StyleWithName2"_ustr));
// Save the file and reload again
saveAndReload(u"draw8"_ustr);
pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
pDocShell = pXImpressDocument->GetDocShell();
pSSPool = pDocShell->GetStyleSheetPool();
// The problem was that the style kept the old name upon reloading
pStyle = pSSPool->Find(u"StyleWithName1"_ustr, SfxStyleFamily::Para);
CPPUNIT_ASSERT(!pStyle);
pStyle = pSSPool->Find(u"StyleWithName2"_ustr, SfxStyleFamily::Para);
CPPUNIT_ASSERT(pStyle);
}
// Insert it.
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT(xDrawPagesSupplier.is());
uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages();
CPPUNIT_ASSERT(xDrawPages.is());
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY);
CPPUNIT_ASSERT(xDrawPage.is()); // This failed with a lang.IllegalArgumentException.
xDrawPage->add(xShape);
// Verify that the graphic was actually consumed.
uno::Reference<graphic::XGraphic> xGraphic;
xShapeProperySet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
CPPUNIT_ASSERT(xGraphic.is());
}
// Testing document model part of editengine-columns void SdMiscTest::testTextColumns()
{
createSdImpressDoc();
uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages(); // Insert a new page.
uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->insertNewByIndex(0),
uno::UNO_SET_THROW);
uno::Reference<drawing::XShapes> xShapes(xDrawPage, uno::UNO_QUERY_THROW);
{ // Create a text shape
uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
CPPUNIT_ASSERT(xFactory.is());
uno::Reference<drawing::XShape> xShape(
xFactory->createInstance(u"com.sun.star.drawing.TextShape"_ustr), uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY_THROW);
// Add the shape to the page.
xShapes->add(xShape);
// Set up columns auto pTextObj = DynCastSdrTextObj(SdrObject::getSdrObjectFromXShape(xShape));
CPPUNIT_ASSERT(pTextObj);
pTextObj->SetMergedItem(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER, 2));
pTextObj->SetMergedItem(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING, 1000));
}
{ // Retrieve the shape and check columns
uno::Reference<container::XIndexAccess> xIndexAccess(xDrawPage, uno::UNO_QUERY_THROW);
uno::Reference<drawing::XShape> xShape(xIndexAccess->getByIndex(0), uno::UNO_QUERY_THROW);
auto pTextObj = DynCastSdrTextObj(SdrObject::getSdrObjectFromXShape(xShape));
CPPUNIT_ASSERT(pTextObj);
// Since LO 6.2 the visible/printable/locked information for layers is always // written as ODF attributes draw:display and draw:protected. It is only read from // there, if the config items VisibleLayers, PrintableLayers and LockedLayers do // not exist. The user option WriteLayerStateAsConfigItem can be set to 'true' to // write these config items in addition to the ODF attributes for to produce // documents for older LO versions or Apache OpenOffice. With value 'false' no // config items are written. The 'testTdf101242_xyz' tests combine source // files with and without config items with option values 'true' and 'false'.
void SdMiscTest::testTdf101242_ODF_add_settings()
{ // Loads a document, which has the visible/printable/locked information for layers // only in the ODF attributes draw:display and draw:protected. The resaved document // should still have the ODF attributes and in addition the config items in settings.xml. // "Load" is needed for to handle layers, simple "loadURL" does not work.
createSdDrawDoc("tdf101242_ODF.odg");
// Saving including items in settings.xml
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, pBatch);
pBatch->commit();
save(u"draw8"_ustr);
// Verify, that the saved document still has the ODF attributes
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc); static constexpr OString sPathStart( "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr);
assertXPath(pXmlDoc,
sPathStart + "[@draw:name='backgroundobjects' and @draw:protected='true']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='controls' and @draw:display='screen']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='measurelines' and @draw:display='printer']");
// Verify, that the saved document has got the items in settings.xml
xmlDocUniquePtr pXmlDoc2 = parseExport(u"settings.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2); static constexpr OString sPathStart2("/office:document-settings/office:settings/" "config:config-item-set[@config:name='ooo:view-settings']/" "config:config-item-map-indexed[@config:name='Views']/" "config:config-item-map-entry"_ostr); // Value is a bitfield with first Byte in order '* * * measurelines controls backgroundobjects background layout' // The first three bits depend on initialization and may change. The values in file are Base64 encoded.
OUString sBase64;
uno::Sequence<sal_Int8> aDecodedSeq;
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='VisibleLayers']");
CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x0F, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='PrintableLayers']");
CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x17, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='LockedLayers']");
CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x04, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
}
void SdMiscTest::testTdf101242_ODF_no_settings()
{ // Loads a document, which has the visible/printable/locked information for layers // only in the ODF attributes draw:display and draw:protected. The resave document // should have only the ODF attributes and no config items in settings.xml.
createSdDrawDoc("tdf101242_ODF.odg");
// Saving without items in settings.xml
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(false, pBatch);
pBatch->commit();
save(u"draw8"_ustr);
// Verify, that the saved document still has the ODF attributes
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc); static constexpr OString sPathStart( "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr);
assertXPath(pXmlDoc,
sPathStart + "[@draw:name='backgroundobjects' and @draw:protected='true']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='controls' and @draw:display='screen']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='measurelines' and @draw:display='printer']");
// Verify, that the saved document has no layer items in settings.xml
xmlDocUniquePtr pXmlDoc2 = parseExport(u"settings.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2); static constexpr OString sPathStart2("/office:document-settings/office:settings/" "config:config-item-set[@config:name='ooo:view-settings']/" "config:config-item-map-indexed[@config:name='Views']/" "config:config-item-map-entry"_ostr);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='VisibleLayers']", 0);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='PrintableLayers']", 0);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='LockedLayers']", 0);
}
void SdMiscTest::testTdf101242_settings_keep()
{ // Loads a document, which has the visible/printable/locked information for layers // only in the config items in settings.xml. That is the case for all old documents. // The resaved document should have the ODF attributes draw:display and draw:protected // and should still have these config items in settings.xml.
createSdDrawDoc("tdf101242_settings.odg");
// Saving including items in settings.xml
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, pBatch);
pBatch->commit();
save(u"draw8"_ustr);
// Verify, that the saved document has the ODF attributes
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc); static constexpr OString sPathStart( "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr);
assertXPath(pXmlDoc,
sPathStart + "[@draw:name='backgroundobjects' and @draw:protected='true']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='controls' and @draw:display='screen']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='measurelines' and @draw:display='printer']");
// Verify, that the saved document still has the items in settings.xml
xmlDocUniquePtr pXmlDoc2 = parseExport(u"settings.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2); static constexpr OString sPathStart2("/office:document-settings/office:settings/" "config:config-item-set[@config:name='ooo:view-settings']/" "config:config-item-map-indexed[@config:name='Views']/" "config:config-item-map-entry"_ostr); // Value is a bitfield with first Byte in order '* * * measurelines controls backgroundobjects background layout' // The first three bits depend on initialization and may change. The values in file are Base64 encoded.
OUString sBase64;
uno::Sequence<sal_Int8> aDecodedSeq;
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='VisibleLayers']");
CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x0F, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='PrintableLayers']");
CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x17, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
sBase64 = getXPathContent(pXmlDoc2,
sPathStart2 + "/config:config-item[@config:name='LockedLayers']");
CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x04, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0x1F);
}
void SdMiscTest::testTdf101242_settings_remove()
{ // Loads a document, which has the visible/printable/locked information for layers // only in the config items in settings.xml. That is the case for all old documents. // The resaved document should have only the ODF attributes draw:display and draw:protected // and should have no config items in settings.xml.
createSdDrawDoc("tdf101242_settings.odg");
// Saving without config items in settings.xml
std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(false, pBatch);
pBatch->commit();
save(u"draw8"_ustr);
// Verify, that the saved document has the ODF attributes
xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'styles.xml'", pXmlDoc); static constexpr OString sPathStart( "/office:document-styles/office:master-styles/draw:layer-set/draw:layer"_ostr);
assertXPath(pXmlDoc,
sPathStart + "[@draw:name='backgroundobjects' and @draw:protected='true']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='controls' and @draw:display='screen']");
assertXPath(pXmlDoc, sPathStart + "[@draw:name='measurelines' and @draw:display='printer']");
// Verify, that the saved document has no layer items in settings.xml
xmlDocUniquePtr pXmlDoc2 = parseExport(u"settings.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc2); static constexpr OString sPathStart2("/office:document-settings/office:settings/" "config:config-item-set[@config:name='ooo:view-settings']/" "config:config-item-map-indexed[@config:name='Views']/" "config:config-item-map-entry"_ostr);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='VisibleLayers']", 0);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='PrintableLayers']", 0);
assertXPath(pXmlDoc2, sPathStart2 + "/config:config-item[@config:name='LockedLayers']", 0);
}
void SdMiscTest::testTdf119392()
{ // Loads a document which has two user layers "V--" and "V-L". Inserts a new layer "-P-" between them. // Checks, that the bitfields in the saved file have the bits in the correct order, in case // option WriteLayerAsConfigItem is true and the config items are written.
std::shared_ptr<comphelper::ConfigurationChanges> batch(
comphelper::ConfigurationChanges::create());
officecfg::Office::Common::Misc::WriteLayerStateAsConfigItem::set(true, batch);
batch->commit();
// Verify correct bit order in bitfield in the config items in settings.xml
xmlDocUniquePtr pXmlDoc = parseExport(u"settings.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'settings.xml'", pXmlDoc); static constexpr OString sPathStart("/office:document-settings/office:settings/" "config:config-item-set[@config:name='ooo:view-settings']/" "config:config-item-map-indexed[@config:name='Views']/" "config:config-item-map-entry"_ostr); // First Byte is in order 'V-L -P- V-- measurelines controls backgroundobjects background layout' // Bits need to be: visible=10111111=0xbf=191 printable=01011111=0x5f=95 locked=10000000=0x80=128 // The values in file are Base64 encoded.
OUString sBase64;
uno::Sequence<sal_Int8> aDecodedSeq;
sBase64 = getXPathContent(pXmlDoc,
sPathStart + "/config:config-item[@config:name='VisibleLayers']");
CPPUNIT_ASSERT_MESSAGE("Item VisibleLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0xbF, static_cast<sal_uInt8>(aDecodedSeq[0])
& 0xff); // & 0xff forces unambiguous types for CPPUNIT_ASSERT_EQUAL
sBase64 = getXPathContent(pXmlDoc,
sPathStart + "/config:config-item[@config:name='PrintableLayers']");
CPPUNIT_ASSERT_MESSAGE("Item PrintableLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x5f, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0xff);
sBase64
= getXPathContent(pXmlDoc, sPathStart + "/config:config-item[@config:name='LockedLayers']");
CPPUNIT_ASSERT_MESSAGE("Item LockedLayers does not exists.", !sBase64.isEmpty());
comphelper::Base64::decode(aDecodedSeq, sBase64);
CPPUNIT_ASSERT_EQUAL(0x80, static_cast<sal_uInt8>(aDecodedSeq[0]) & 0xff);
}
void SdMiscTest::testTdf67248()
{ // The document tdf67248.odg has been created with a German UI. It has a user layer named "Background". // On opening the user layer must still exists. The error was, that it was merged into the standard // layer "background".
createSdDrawDoc("tdf67248.odg");
SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
SdDrawDocument* pDoc = pXImpressDocument->GetDoc();
SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), rLayerAdmin.GetLayerCount());
}
// Alt+Click sets a tab in edit mode, so that you can rename it. // The error was, that Alt+Click on a tab, which was not the current tab, did not set the clicked tab // as current tab. As a result, the entered text was applied to the wrong tab.
// The test document has the layer tabs "layout", "controls", "measurelines" and "Layer4" in this order // The "pagePos" is 0, 1, 2, 3 // Make sure, that tab "layout" is the current tab.
MouseEvent aSyntheticMouseEvent; if (pLayerTabBar->GetCurPagePos() != 0)
{
sal_uInt16 nIdOfTabPos0(pLayerTabBar->GetPageId(0));
tools::Rectangle aTabPos0Rect(pLayerTabBar->GetPageRect(nIdOfTabPos0));
aSyntheticMouseEvent
= MouseEvent(aTabPos0Rect.Center(), 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0);
pLayerTabBar->MouseButtonDown(aSyntheticMouseEvent);
}
CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pLayerTabBar->GetCurPagePos());
// Make sure, tab 3 is current tab now.
CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pLayerTabBar->GetCurPagePos());
}
void SdMiscTest::testTdf98839_ShearVFlipH()
{ // Loads a document with a sheared shape and mirrors it
createSdDrawDoc("tdf98839_ShearVFlipH.odg");
SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
SdPage* pPage = pViewShell->GetActualPage();
SdrObjCustomShape* pShape = static_cast<SdrObjCustomShape*>(pPage->GetObj(0));
pShape->Mirror(Point(4000, 2000), Point(4000, 10000));
// Save and examine attribute draw:transform
save(u"draw8"_ustr);
xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
CPPUNIT_ASSERT_MESSAGE("Failed to get 'content.xml'", pXmlDoc); static constexpr OString sPathStart( "/office:document-content/office:body/office:drawing/draw:page"_ostr);
assertXPath(pXmlDoc, sPathStart); const OUString sTransform = getXPath(pXmlDoc, sPathStart + "/draw:custom-shape", "transform");
// Error was, that the shear angle had a wrong sign.
CPPUNIT_ASSERT_MESSAGE("expected: draw:transform='skewX (-0.64350...)",
sTransform.startsWith("skewX (-"));
}
// Error was, that the created 3D object had a wrong path. Instead examining // the path directly, I use the scene distance, because that is easier. The // scene distance is calculated from the object while creating. constdouble fDistance = pObj->GetDistance();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("D3DSceneDistance", 7071.0, fDistance, 0.5);
}
// The document contains a polygon, so that emulate command .uno:ConvertInto3DLathe // by direct call of ConvertMarkedObjTo3D works. // It produces a rotation around a vertical axis, which is far away from the // generating shape.
sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
E3dView* pView = pViewShell->GetView();
pView->MarkNextObj();
pView->ConvertMarkedObjTo3D(false, basegfx::B2DPoint(11000.0, -5000.0),
basegfx::B2DPoint(11000.0, -9000.0));
E3dScene* pObj
= dynamic_cast<E3dScene*>(pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj());
CPPUNIT_ASSERT(pObj);
// Error was, that the 2D representation of the scene did not contain the default 20° // rotation of the new scene around x-axis and therefore was not high enough. constdouble fSnapRectHeight = pObj->GetSnapRect().getOpenHeight();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("2D height", 7096.0, fSnapRectHeight, 1.0);
}
void SdMiscTest::testTdf129898LayerDrawnInSlideshow()
{ // Versions LO 6.2 to 6.4 have produced files, where the layer DrawnInSlideshow has // got visible=false and printable=false attributes. Those files should be repaired now.
createSdImpressDoc("tdf129898_faulty_DrawnInSlideshow.odp");
SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pXImpressDocument);
SdDrawDocument* pDoc = pXImpressDocument->GetDoc();
// Change the name of the first page in the newly created document
SdDrawDocument* pDoc = pXImpressDocument->GetDoc();
SdPage* pPage = static_cast<SdPage*>(pDoc->GetPage(1));
pPage->SetName(u"Test"_ustr);
// Insert a bookmark as a new page using the same name
std::vector<OUString> aBookmarkList = { u"Test"_ustr };
pDoc->CopyOrMovePagesWithinDocument(aBookmarkList, nullptr, 2, false);
// Check if the copied page has a different name
SdPage* pCopiedPage = static_cast<SdPage*>(pDoc->GetPage(2)); // Without the fix in place, the names of the pages would not be different
CPPUNIT_ASSERT(pCopiedPage->GetName() != pPage->GetName());
}
// Change the name of the first page in the newly created document
SdDrawDocument* pDoc = pXImpressDocument->GetDoc();
SdPage* pPage = static_cast<SdPage*>(pDoc->GetPage(1));
pPage->SetName(u"Test"_ustr);
// Move a bookmark as a page using the same name
pDoc->DoMakePageObjectsNamesUnique(false);
std::vector<OUString> aBookmarkList = { u"Test"_ustr };
pDoc->CopyOrMovePagesWithinDocument(aBookmarkList, nullptr, 2, true);
// Check if the moved page has the same name
SdPage* pMovedPage = static_cast<SdPage*>(pDoc->GetPage(2)); // Without the fix in place, the names of the pages would be different
CPPUNIT_ASSERT_EQUAL(pPage->GetName(), pMovedPage->GetName());
}
void SdMiscTest::testEncodedTableStyles()
{ // Silence unrelated failure: // Error: element "table:table-template" is missing "first-row-start-column" attribute
skipValidation();
{
uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent,
uno::UNO_QUERY_THROW);
uno::Reference<container::XNameAccess> xTableStyleFamily(
xStyleFamiliesSupplier->getStyleFamilies()->getByName(u"table"_ustr),
uno::UNO_QUERY_THROW); // Such style used to be exported as "table_5f_1" instead.
CPPUNIT_ASSERT(xTableStyleFamily->hasByName(u"table_1"_ustr));
uno::Reference<container::XNameAccess> xTableStyle(
xTableStyleFamily->getByName(u"table_1"_ustr), uno::UNO_QUERY_THROW);
uno::Reference<style::XStyle> xCellStyle(xTableStyle->getByName(u"body"_ustr),
uno::UNO_QUERY); // Such style used to not be found by the table style, as it was // searching for "table-body_5f_1" instead of "table-body_1".
CPPUNIT_ASSERT(xCellStyle.is());
CPPUNIT_ASSERT_EQUAL(u"table-body_1"_ustr, xCellStyle->getName());
}
}
// insert two pages to make a total of 3 pages
dispatchCommand(mxComponent, u".uno:InsertPage"_ustr, {});
dispatchCommand(mxComponent, u".uno:InsertPage"_ustr, {});
// assert the document has 3 standard pages
SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), pDocument->GetSdPageCount(PageKind::Standard));
// move to the last page
dispatchCommand(mxComponent, u".uno:LastPage"_ustr, {});
SdPage* pPage = pViewShell->GetActualPage(); auto nPageNum = pPage->GetPageNum(); // assert move to last page
CPPUNIT_ASSERT_EQUAL(2, (nPageNum - 1) / 2);
// delete the last page
dispatchCommand(mxComponent, u".uno:DeletePage"_ustr, {});
pPage = pViewShell->GetActualPage();
nPageNum = pPage->GetPageNum();
// Check that the new last page is moved to. Before, the first page was always moved to when // the last page was deleted.
CPPUNIT_ASSERT_EQUAL(1, (nPageNum - 1) / 2);
}
// Style should be "BITMAP"
CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
aMergedAttr.Get(XATTR_FILLSTYLE).GetValue()); auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
aGraphicNames.insert(aItem.GetName());
}
// Style should be "BITMAP"
CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP,
aMergedAttr.Get(XATTR_FILLSTYLE).GetValue()); auto aItem = aMergedAttr.Get<XFillBitmapItem>(XATTR_FILLBITMAP);
aGraphicNames.insert(aItem.GetName());
}
// Size of graphic names should be 4 - this means each page has a unique name
CPPUNIT_ASSERT_EQUAL(size_t(4), aGraphicNames.size()); // Check none of the graphic names is empty for (OUString const& rName : aGraphicNames)
CPPUNIT_ASSERT(!rName.isEmpty());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.