1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <test/bootstrapfixture.hxx>
11 #include <unotest/macros_test.hxx>
12 
13 #include <com/sun/star/frame/Desktop.hpp>
14 #include <com/sun/star/uno/Reference.hxx>
15 
16 #include <comphelper/processfactory.hxx>
17 #include <sfx2/dispatch.hxx>
18 #include <sfx2/request.hxx>
19 #include <sfx2/viewfrm.hxx>
20 #include <svl/intitem.hxx>
21 #include <svx/svxids.hrc>
22 #include <svx/svdoashp.hxx>
23 #include <svl/stritem.hxx>
24 #include <undo/undomanager.hxx>
25 
26 #include <DrawDocShell.hxx>
27 #include <ViewShell.hxx>
28 #include <app.hrc>
29 #include <drawdoc.hxx>
30 #include <sdpage.hxx>
31 #include <unomodel.hxx>
32 
33 using namespace ::com::sun::star;
34 
35 /// Impress UI tests.
36 class SdUiImpressTest : public test::BootstrapFixture, public unotest::MacrosTest
37 {
38 protected:
39     uno::Reference<uno::XComponentContext> mxComponentContext;
40     uno::Reference<lang::XComponent> mxComponent;
41 
42 public:
43     virtual void setUp() override;
44     virtual void tearDown() override;
45 };
46 
setUp()47 void SdUiImpressTest::setUp()
48 {
49     test::BootstrapFixture::setUp();
50 
51     mxComponentContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
52     mxDesktop.set(frame::Desktop::create(mxComponentContext));
53 }
54 
tearDown()55 void SdUiImpressTest::tearDown()
56 {
57     if (mxComponent.is())
58         mxComponent->dispose();
59 
60     test::BootstrapFixture::tearDown();
61 }
62 
CPPUNIT_TEST_FIXTURE(SdUiImpressTest,testTdf111522)63 CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf111522)
64 {
65     // Load the document and create two new windows.
66     mxComponent = loadFromDesktop(m_directories.getURLFromSrc("sd/qa/unit/data/tdf111522.odp"));
67     auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
68     sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell();
69     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_NEWWINDOW, SfxCallMode::SYNCHRON);
70     sd::ViewShell* pViewShell1 = pImpressDocument->GetDocShell()->GetViewShell();
71     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_NEWWINDOW, SfxCallMode::SYNCHRON);
72     sd::ViewShell* pViewShell2 = pImpressDocument->GetDocShell()->GetViewShell();
73     CPPUNIT_ASSERT(pViewShell1 != pViewShell2);
74 
75     // Have slide 1 in window 1, slide 2 in window 2.
76     SfxRequest aRequest(pViewShell2->GetViewFrame(), SID_SWITCHPAGE);
77     aRequest.AppendItem(SfxUInt32Item(ID_VAL_WHATPAGE, 1));
78     aRequest.AppendItem(
79         SfxUInt32Item(ID_VAL_WHATKIND, static_cast<sal_uInt32>(PageKind::Standard)));
80     pViewShell2->ExecuteSlot(aRequest, /*bAsync=*/false);
81 
82     // Start text edit in window 1.
83     SdPage* pPage1 = pViewShell1->GetActualPage();
84     SdrObject* pShape1 = pPage1->GetObj(0);
85     SdrView* pView1 = pViewShell1->GetView();
86     pView1->MarkObj(pShape1, pView1->GetSdrPageView());
87     pView1->SdrBeginTextEdit(pShape1);
88     CPPUNIT_ASSERT(pView1->IsTextEdit());
89 
90     // Move the shape in window 2 & undo.
91     SdPage* pPage2 = pViewShell2->GetActualPage();
92     CPPUNIT_ASSERT(pPage1 != pPage2);
93     SdrObject* pShape2 = pPage2->GetObj(0);
94     SdrView* pView2 = pViewShell2->GetView();
95     pView2->MarkObj(pShape2, pView2->GetSdrPageView());
96     pView2->MoveMarkedObj(Size(1, 1), /*bCopy=*/false);
97     // Without the accompanying fix in place, this test would have failed with an assertion failure
98     // in SdrObjEditView::SdrEndTextEdit() as mpOldTextEditUndoManager was not nullptr.
99     pViewShell2->GetViewFrame()->GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
100 
101     // Rotate the shape in window 2 & undo.
102     pView2->MarkObj(pShape2, pView2->GetSdrPageView());
103     pView2->RotateMarkedObj(pShape2->GetLastBoundRect().Center(), /*nAngle=*/45);
104     // Without the accompanying fix in place, this test would have failed with an assertion failure
105     // in SdrObjEditView::SdrEndTextEdit() as mpOldTextEditUndoManager was not nullptr.
106     pViewShell2->GetViewFrame()->GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
107 
108     // Start text edit in window 2.
109     // tdf#125824
110     pView2->MarkObj(pShape2, pView2->GetSdrPageView());
111     pView2->SdrBeginTextEdit(pShape2);
112     CPPUNIT_ASSERT(pView2->IsTextEdit());
113     // Write 'test' inside the shape
114     SfxStringItem aInputString(SID_ATTR_CHAR, "test");
115     pViewShell2->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON,
116                                                               { &aInputString });
117     CPPUNIT_ASSERT(pView2->GetTextEditObject());
118     EditView& rEditView = pView2->GetTextEditOutlinerView()->GetEditView();
119     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), rEditView.GetSelection().nStartPos);
120     pView2->SdrEndTextEdit();
121     // Without the accompanying fix in place, this test would have failed with an assertion failure
122     // in SdrObjEditView::SdrEndTextEdit() as mpOldTextEditUndoManager was not nullptr.
123     pViewShell2->GetViewFrame()->GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
124 }
125 
CPPUNIT_TEST_FIXTURE(SdUiImpressTest,testTdf126197)126 CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf126197)
127 {
128     // Load the document and create two new windows.
129     mxComponent = loadFromDesktop(m_directories.getURLFromSrc("sd/qa/unit/data/tdf126197.odp"));
130     auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
131     sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell();
132     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_NEWWINDOW, SfxCallMode::SYNCHRON);
133     sd::ViewShell* pViewShell1 = pImpressDocument->GetDocShell()->GetViewShell();
134     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_NEWWINDOW, SfxCallMode::SYNCHRON);
135     sd::ViewShell* pViewShell2 = pImpressDocument->GetDocShell()->GetViewShell();
136     CPPUNIT_ASSERT(pViewShell1 != pViewShell2);
137 
138     // Start text edit in window 1.
139     SdPage* pPage1 = pViewShell1->GetActualPage();
140     SdrObject* pShape1 = pPage1->GetObj(0);
141     SdrView* pView1 = pViewShell1->GetView();
142     pView1->MarkObj(pShape1, pView1->GetSdrPageView());
143     pView1->SdrBeginTextEdit(pShape1);
144     CPPUNIT_ASSERT(pView1->IsTextEdit());
145 
146     SdPage* pPage2 = pViewShell2->GetActualPage();
147     CPPUNIT_ASSERT_EQUAL(pPage1, pPage2);
148     SdrObject* pShape2 = pPage2->GetObj(0);
149     CPPUNIT_ASSERT_EQUAL(pShape1, pShape2);
150     SdrView* pView2 = pViewShell2->GetView();
151     pView2->MarkObj(pShape2, pView2->GetSdrPageView());
152 
153     // Without the accompanying fix in place, this test would have failed with an assertion failure
154     // in SdrObjEditView::SdrEndTextEdit()
155     pViewShell2->GetViewFrame()->GetDispatcher()->Execute(SID_DELETE, SfxCallMode::SYNCHRON);
156 }
157 
CPPUNIT_TEST_FIXTURE(SdUiImpressTest,testTdf128651)158 CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf128651)
159 {
160     // Error was, that undo and redo changes size of the shape. Affected actions were e.g.
161     // extrusion on/off, shadow on/off, changes on line or fill attributes.
162     // All these actions do not change the snap rectangle.
163     mxComponent = loadFromDesktop(
164         m_directories.getURLFromSrc("sd/qa/unit/data/tdf128651_CustomShapeUndo.odp"));
165     auto pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
166     sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
167     SdPage* pActualPage = pViewShell->GetActualPage();
168     SdrObject* pObject = pActualPage->GetObj(0);
169     auto pCustomShape = dynamic_cast<SdrObjCustomShape*>(pObject);
170     CPPUNIT_ASSERT_MESSAGE("No Shape", pCustomShape);
171     const sal_Int32 nOrigWidth(pCustomShape->GetSnapRect().GetWidth());
172 
173     SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
174     sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
175     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pUndoManager->GetUndoActionCount());
176     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pUndoManager->GetRedoActionCount());
177 
178     SdrView* pView = pViewShell->GetView();
179     pView->MarkObj(pCustomShape, pView->GetSdrPageView());
180     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_EXTRUSION_TOGGLE,
181                                                          SfxCallMode::SYNCHRON);
182     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
183 
184     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
185     const sal_Int32 nUndoWidth(pCustomShape->GetSnapRect().GetWidth());
186     CPPUNIT_ASSERT_EQUAL_MESSAGE("Undo changes width", nOrigWidth, nUndoWidth);
187 
188     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetRedoActionCount());
189     pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_REDO, SfxCallMode::SYNCHRON);
190     const sal_Int32 nRedoWidth(pCustomShape->GetSnapRect().GetWidth());
191     CPPUNIT_ASSERT_EQUAL_MESSAGE("Redo changes width", nUndoWidth, nRedoWidth);
192 }
193 CPPUNIT_PLUGIN_IMPLEMENT();
194 
195 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
196