Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / uibase / uiview / uiview.cxx
blob5a0f1db584e251c9c124cb84fa6e696f8405b51a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <swmodeltestbase.hxx>
12 #include <comphelper/processfactory.hxx>
13 #include <osl/file.hxx>
14 #include <comphelper/propertyvalue.hxx>
15 #include <comphelper/scopeguard.hxx>
16 #include <vcl/scheduler.hxx>
18 #include <com/sun/star/frame/XDispatchHelper.hpp>
19 #include <com/sun/star/frame/XDispatchProvider.hpp>
20 #include <com/sun/star/frame/XComponentLoader.hpp>
21 #include <com/sun/star/frame/XStorable2.hpp>
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
24 #include <com/sun/star/view/XSelectionSupplier.hpp>
26 #include <unotxdoc.hxx>
27 #include <docsh.hxx>
28 #include <wrtsh.hxx>
29 #include <swmodule.hxx>
30 #include <view.hxx>
32 /// Covers sw/source/uibase/uiview/ fixes.
33 class SwUibaseUiviewTest : public SwModelTestBase
35 public:
36 SwUibaseUiviewTest()
37 : SwModelTestBase("/sw/qa/uibase/uiview/data/")
42 CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, testUpdateAllObjectReplacements)
44 // Make a temporary copy of the test document
45 createTempCopy(u"updateall-objectreplacements.odt");
47 /* BASIC code that exhibits the problem:
49 desktop = CreateUnoService("com.sun.star.frame.Desktop")
50 Dim props(0) as new com.sun.star.beans.PropertyValue
51 props(0).Name = "Hidden"
52 props(0).Value = true
53 component = desktop.loadComponentFromURL("file://.../test.odt", "_default", 0, props)
54 Wait 1000 ' workaround
55 dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
56 frame = component.CurrentController.Frame
57 dispatcher.executeDispatch(frame, ".uno:UpdateAll", "", 0, Array())
58 component.storeSelf(Array())
59 component.dispose()
62 uno::Reference<lang::XMultiServiceFactory> xFactory(comphelper::getProcessServiceFactory());
64 // Load the copy
65 uno::Reference<uno::XInterface> xInterface
66 = xFactory->createInstance("com.sun.star.frame.Desktop");
67 uno::Reference<frame::XComponentLoader> xComponentLoader(xInterface, uno::UNO_QUERY);
68 uno::Sequence<beans::PropertyValue> aLoadArgs{ comphelper::makePropertyValue("Hidden", true) };
69 mxComponent
70 = xComponentLoader->loadComponentFromURL(maTempFile.GetURL(), "_default", 0, aLoadArgs);
72 // Perform the .uno:UpdateAll call and save
73 xInterface = xFactory->createInstance("com.sun.star.frame.DispatchHelper");
74 uno::Reference<frame::XDispatchHelper> xDispatchHelper(xInterface, uno::UNO_QUERY);
75 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
76 uno::Reference<frame::XDispatchProvider> xDispatchProvider(
77 xModel->getCurrentController()->getFrame(), uno::UNO_QUERY);
78 uno::Sequence<beans::PropertyValue> aNoArgs;
79 xDispatchHelper->executeDispatch(xDispatchProvider, ".uno:UpdateAll", OUString(), 0, aNoArgs);
80 uno::Reference<frame::XStorable2> xStorable(mxComponent, uno::UNO_QUERY);
81 xStorable->storeSelf(aNoArgs);
83 // Check the contents of the updated copy and verify that ObjectReplacements are there
84 uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
85 = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(xFactory),
86 maTempFile.GetURL());
88 CPPUNIT_ASSERT(xNameAccess->hasByName("ObjectReplacements/Components"));
89 CPPUNIT_ASSERT(xNameAccess->hasByName("ObjectReplacements/Components_1"));
92 CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, testUpdateReplacementNosetting)
94 // Load a copy of the document in hidden mode.
95 OUString aSourceURL = createFileURL(u"update-replacement-nosetting.odt");
96 CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, osl::File::copy(aSourceURL, maTempFile.GetURL()));
97 mxComponent = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument",
98 { comphelper::makePropertyValue("Hidden", true) });
100 // Update "everything" (including object replacements) and save it.
101 dispatchCommand(mxComponent, ".uno:UpdateAll", {});
102 uno::Reference<frame::XStorable2> xStorable(mxComponent, uno::UNO_QUERY);
103 xStorable->storeSelf({});
105 // Check the contents of the updated copy.
106 uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
107 uno::Reference<packages::zip::XZipFileAccess2> xNameAccess
108 = packages::zip::ZipFileAccess::createWithURL(xContext, maTempFile.GetURL());
110 // Without the accompanying fix in place, this test would have failed, because the embedded
111 // object replacement image was not generated.
112 CPPUNIT_ASSERT(xNameAccess->hasByName("ObjectReplacements/Components"));
115 CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, testKeepRatio)
117 // Given a document with a custom KeepRatio:
118 OUString aURL = createFileURL(u"keep-ratio.fodt");
120 // When loading that document:
121 mxComponent = loadFromDesktop(aURL);
123 // Then make sure we read the custom value:
124 auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get());
125 SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
126 const SwViewOption* pViewOption = pWrtShell->GetViewOptions();
127 comphelper::ScopeGuard g([pWrtShell, pViewOption] {
128 SwViewOption aViewOption(*pViewOption);
129 aViewOption.SetKeepRatio(false);
130 SW_MOD()->ApplyUsrPref(aViewOption, &pWrtShell->GetView());
132 // Without the accompanying fix in place, this test would have failed, because KeepRatio was not
133 // mapped to settings.xml
134 CPPUNIT_ASSERT(pViewOption->IsKeepRatio());
136 // Then export as well:
137 save("writer8");
138 xmlDocUniquePtr pXmlDoc = parseExport("settings.xml");
139 assertXPathContent(pXmlDoc, "//config:config-item[@config:name='KeepRatio']", "true");
142 namespace
144 /// Interception implementation that disables .uno:Zoom on Image1, but not on Image2.
145 struct ImageInterceptor : public cppu::WeakImplHelper<frame::XDispatchProviderInterceptor>
147 uno::Reference<view::XSelectionSupplier> m_xSelectionSupplier;
148 uno::Reference<frame::XDispatchProvider> m_xMaster;
149 uno::Reference<frame::XDispatchProvider> m_xSlave;
150 int m_nEnabled = 0;
151 int m_nDisabled = 0;
153 public:
154 ImageInterceptor(const uno::Reference<lang::XComponent>& xComponent);
156 // XDispatchProviderInterceptor
157 uno::Reference<frame::XDispatchProvider> SAL_CALL getMasterDispatchProvider() override;
158 uno::Reference<frame::XDispatchProvider> SAL_CALL getSlaveDispatchProvider() override;
159 void SAL_CALL setMasterDispatchProvider(
160 const uno::Reference<frame::XDispatchProvider>& xNewSupplier) override;
161 void SAL_CALL
162 setSlaveDispatchProvider(const uno::Reference<frame::XDispatchProvider>& xNewSupplier) override;
164 // XDispatchProvider
165 uno::Reference<frame::XDispatch> SAL_CALL queryDispatch(const util::URL& rURL,
166 const OUString& rTargetFrameName,
167 sal_Int32 SearchFlags) override;
168 uno::Sequence<uno::Reference<frame::XDispatch>> SAL_CALL
169 queryDispatches(const uno::Sequence<frame::DispatchDescriptor>& rRequests) override;
173 ImageInterceptor::ImageInterceptor(const uno::Reference<lang::XComponent>& xComponent)
175 uno::Reference<frame::XModel2> xModel(xComponent, uno::UNO_QUERY);
176 CPPUNIT_ASSERT(xModel.is());
177 m_xSelectionSupplier.set(xModel->getCurrentController(), uno::UNO_QUERY);
178 CPPUNIT_ASSERT(m_xSelectionSupplier.is());
181 uno::Reference<frame::XDispatchProvider> ImageInterceptor::getMasterDispatchProvider()
183 return m_xMaster;
186 uno::Reference<frame::XDispatchProvider> ImageInterceptor::getSlaveDispatchProvider()
188 return m_xSlave;
191 void ImageInterceptor::setMasterDispatchProvider(
192 const uno::Reference<frame::XDispatchProvider>& xNewSupplier)
194 m_xMaster = xNewSupplier;
197 void ImageInterceptor::setSlaveDispatchProvider(
198 const uno::Reference<frame::XDispatchProvider>& xNewSupplier)
200 m_xSlave = xNewSupplier;
203 uno::Reference<frame::XDispatch> ImageInterceptor::queryDispatch(const util::URL& rURL,
204 const OUString& rTargetFrameName,
205 sal_Int32 nSearchFlags)
207 // Disable the UNO command based on the currently selected image, i.e. this can't be cached when
208 // a different image is selected. Originally this was .uno:SetBorderStyle, but let's pick a
209 // command which is active when running cppunit tests:
210 if (rURL.Complete == ".uno:Zoom")
212 uno::Reference<container::XNamed> xImage;
213 m_xSelectionSupplier->getSelection() >>= xImage;
214 if (xImage.is() && xImage->getName() == "Image1")
216 ++m_nDisabled;
217 return {};
220 ++m_nEnabled;
223 return m_xSlave->queryDispatch(rURL, rTargetFrameName, nSearchFlags);
226 uno::Sequence<uno::Reference<frame::XDispatch>>
227 ImageInterceptor::queryDispatches(const uno::Sequence<frame::DispatchDescriptor>& /*rRequests*/)
229 return {};
232 CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, testSwitchBetweenImages)
234 // Given a document with 2 images, and an interceptor catching an UNO command that specific to
235 // the current selection:
236 createSwDoc();
237 SwDoc* pDoc = getSwDoc();
238 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
239 uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY);
240 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
241 uno::Reference<text::XText> xText = xTextDocument->getText();
242 uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
243 for (int i = 0; i < 2; ++i)
245 uno::Reference<beans::XPropertySet> xTextGraphic(
246 xMSF->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY);
247 xTextGraphic->setPropertyValue("AnchorType",
248 uno::Any(text::TextContentAnchorType_AS_CHARACTER));
249 xTextGraphic->setPropertyValue("Size", uno::Any(awt::Size(5000, 5000)));
250 uno::Reference<text::XTextContent> xTextContent(xTextGraphic, uno::UNO_QUERY);
251 xText->insertTextContent(xCursor, xTextContent, false);
253 pWrtShell->SttEndDoc(/*bStt=*/false);
254 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
255 uno::Reference<frame::XDispatchProviderInterception> xRegistration(
256 xModel->getCurrentController()->getFrame(), uno::UNO_QUERY);
257 rtl::Reference pInterceptor(new ImageInterceptor(mxComponent));
259 xRegistration->registerDispatchProviderInterceptor(pInterceptor);
260 pInterceptor->m_nEnabled = 0;
261 pInterceptor->m_nDisabled = 0;
263 // When selecting the first image:
264 selectShape(1);
266 // Then make sure the UNO command is disabled:
267 CPPUNIT_ASSERT_EQUAL(0, pInterceptor->m_nEnabled);
268 CPPUNIT_ASSERT_GREATEREQUAL(1, pInterceptor->m_nDisabled);
270 // Given a clean state:
271 pInterceptor->m_nEnabled = 0;
272 pInterceptor->m_nDisabled = 0;
274 // When selecting the second image:
275 selectShape(2);
277 // Then make sure the UNO command is enabled:
278 CPPUNIT_ASSERT_GREATEREQUAL(1, pInterceptor->m_nEnabled);
279 CPPUNIT_ASSERT_EQUAL(0, pInterceptor->m_nDisabled);
281 // Given a clean state:
282 pInterceptor->m_nEnabled = 0;
283 pInterceptor->m_nDisabled = 0;
285 // When selecting the first image, again (this time not changing the selection type):
286 selectShape(1);
288 // Then make sure the UNO command is disabled:
289 CPPUNIT_ASSERT_EQUAL(0, pInterceptor->m_nEnabled);
290 // Without the accompanying fix in place, this test would have failed with:
291 // - Expected greater or equal than: 1
292 // - Actual : 0
293 // i.e. selecting the first image didn't result in a disabled UNO command.
294 CPPUNIT_ASSERT_GREATEREQUAL(1, pInterceptor->m_nDisabled);
297 CPPUNIT_PLUGIN_IMPLEMENT();
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */