cid#1607171 Data race condition
[LibreOffice.git] / sd / source / ui / view / ViewShellImplementation.cxx
blobb84ff8643ffca0aba8e92893e05d02eff83264f3
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <ViewShellImplementation.hxx>
24 #include <sdpage.hxx>
25 #include <drawdoc.hxx>
26 #include <sdresid.hxx>
27 #include <unokywds.hxx>
28 #include <strings.hrc>
29 #include <app.hrc>
30 #include <unmodpg.hxx>
31 #include <DrawDocShell.hxx>
32 #include <FactoryIds.hxx>
33 #include <ViewShellBase.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/request.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <sfx2/viewfrm.hxx>
40 #include <sfx2/sidebar/Sidebar.hxx>
41 #include <svl/intitem.hxx>
42 #include <svl/stritem.hxx>
43 #include <svx/imapdlg.hxx>
44 #include <basic/sbstar.hxx>
45 #include <basic/sberrors.hxx>
46 #include <xmloff/autolayout.hxx>
47 #include <vcl/svapp.hxx>
49 #include <undo/undoobjects.hxx>
51 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
53 namespace sd {
55 ViewShell::Implementation::Implementation (ViewShell& rViewShell)
56 : mbIsMainViewShell(false),
57 mbIsInitialized(false),
58 mbArrangeActive(false),
59 mrViewShell(rViewShell)
63 ViewShell::Implementation::~Implementation() COVERITY_NOEXCEPT_FALSE
65 if ( ! mpUpdateLockForMouse.expired())
67 std::shared_ptr<ToolBarManagerLock> pLock(mpUpdateLockForMouse);
68 if (pLock != nullptr)
70 // Force the ToolBarManagerLock to be released even when the
71 // IsUICaptured() returns <TRUE/>.
72 pLock->Release(true);
77 void ViewShell::Implementation::ProcessModifyPageSlot (
78 SfxRequest& rRequest,
79 SdPage* pCurrentPage,
80 PageKind ePageKind)
82 SdDrawDocument* pDocument = mrViewShell.GetDoc();
83 SdrLayerAdmin& rLayerAdmin = pDocument->GetLayerAdmin();
84 SdrLayerIDSet aVisibleLayers;
85 bool bHandoutMode = false;
86 SdPage* pHandoutMPage = nullptr;
87 OUString aNewName;
89 AutoLayout aNewAutoLayout;
91 bool bBVisible;
92 bool bBObjsVisible;
93 const SfxItemSet* pArgs = rRequest.GetArgs();
95 if (pCurrentPage != nullptr && pCurrentPage->TRG_HasMasterPage())
96 aVisibleLayers = pCurrentPage->TRG_GetMasterPageVisibleLayers();
97 else
98 aVisibleLayers.SetAll();
102 if (pCurrentPage == nullptr)
103 break;
105 if (!pArgs || pArgs->Count() == 1 || pArgs->Count() == 2 )
107 // First make sure that the sidebar is visible
108 mrViewShell.GetDrawView()->SdrEndTextEdit();
109 mrViewShell.GetDrawView()->UnmarkAll();
110 if (SfxViewFrame* pViewFrame = mrViewShell.GetViewFrame())
112 pViewFrame->ShowChildWindow(SID_SIDEBAR);
113 sfx2::sidebar::Sidebar::TogglePanel(
114 u"SdLayoutsPanel",
115 pViewFrame->GetFrame().GetFrameInterface());
117 break;
119 else if (pArgs->Count() == 4)
121 const SfxStringItem* pNewName = rRequest.GetArg<SfxStringItem>(ID_VAL_PAGENAME);
122 const SfxUInt32Item* pNewAutoLayout = rRequest.GetArg<SfxUInt32Item>(ID_VAL_WHATLAYOUT);
123 const SfxBoolItem* pBVisible = rRequest.GetArg<SfxBoolItem>(ID_VAL_ISPAGEBACK);
124 const SfxBoolItem* pBObjsVisible = rRequest.GetArg<SfxBoolItem>(ID_VAL_ISPAGEOBJ);
125 assert(pNewName && pNewAutoLayout && pBVisible && pBObjsVisible && "must be present");
126 AutoLayout aLayout (static_cast<AutoLayout>(pNewAutoLayout->GetValue ()));
127 if (aLayout >= AUTOLAYOUT_START
128 && aLayout < AUTOLAYOUT_END)
130 aNewName = pNewName->GetValue ();
131 aNewAutoLayout = static_cast<AutoLayout>(pNewAutoLayout->GetValue ());
132 bBVisible = pBVisible->GetValue ();
133 bBObjsVisible = pBObjsVisible->GetValue ();
135 else
137 #if HAVE_FEATURE_SCRIPTING
138 StarBASIC::FatalError (ERRCODE_BASIC_BAD_PROP_VALUE);
139 #endif
140 rRequest.Ignore ();
141 break;
143 if (ePageKind == PageKind::Handout)
145 bHandoutMode = true;
146 pHandoutMPage = pDocument->GetMasterSdPage(0, PageKind::Handout);
149 else
151 #if HAVE_FEATURE_SCRIPTING
152 StarBASIC::FatalError (ERRCODE_BASIC_WRONG_ARGS);
153 #endif
154 rRequest.Ignore ();
155 break;
158 SdPage* pUndoPage =
159 bHandoutMode ? pHandoutMPage : pCurrentPage;
161 SfxUndoManager* pUndoManager = mrViewShell.GetDocSh()->GetUndoManager();
162 DBG_ASSERT(pUndoManager, "No UNDO MANAGER ?!?");
164 if( pUndoManager )
166 OUString aComment( SdResId(STR_UNDO_MODIFY_PAGE) );
167 pUndoManager->EnterListAction(aComment, aComment, 0, mrViewShell.GetViewShellBase().GetViewShellId());
168 pUndoManager->AddUndoAction(
169 std::make_unique<ModifyPageUndoAction>(
170 pDocument, pUndoPage, aNewName, aNewAutoLayout, bBVisible, bBObjsVisible));
172 // Clear the selection because the selected object may be removed as
173 // a result of the assignment of the layout.
174 mrViewShell.GetDrawView()->UnmarkAll();
176 if (!bHandoutMode)
178 if (pCurrentPage->GetName() != aNewName)
180 pCurrentPage->SetName(aNewName);
182 if (ePageKind == PageKind::Standard)
184 sal_uInt16 nPage = (pCurrentPage->GetPageNum()-1) / 2;
185 SdPage* pNotesPage = pDocument->GetSdPage(nPage, PageKind::Notes);
186 if (pNotesPage != nullptr)
187 pNotesPage->SetName(aNewName);
191 pCurrentPage->SetAutoLayout(aNewAutoLayout, true);
193 SdrLayerID aBckgrnd = rLayerAdmin.GetLayerID(sUNO_LayerName_background);
194 SdrLayerID aBckgrndObj = rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects);
195 aVisibleLayers.Set(aBckgrnd, bBVisible);
196 aVisibleLayers.Set(aBckgrndObj, bBObjsVisible);
197 pCurrentPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers);
199 else
201 pHandoutMPage->SetAutoLayout(aNewAutoLayout, true);
204 mrViewShell.GetViewFrame()->GetDispatcher()->Execute(SID_SWITCHPAGE,
205 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
207 bool bSetModified = true;
209 if (pArgs->Count() == 1)
211 bSetModified = static_cast<const SfxBoolItem&>(pArgs->Get(SID_MODIFYPAGE)).GetValue();
214 pUndoManager->AddUndoAction( std::make_unique<UndoAutoLayoutPosAndSize>( *pUndoPage ) );
215 pUndoManager->LeaveListAction();
217 pDocument->SetChanged(bSetModified);
220 while (false);
222 mrViewShell.Cancel();
223 rRequest.Done ();
226 void ViewShell::Implementation::AssignLayout ( SfxRequest const & rRequest, PageKind ePageKind )
228 const SfxUInt32Item* pWhatPage = rRequest.GetArg<SfxUInt32Item>(ID_VAL_WHATPAGE);
229 const SfxUInt32Item* pWhatLayout = rRequest.GetArg<SfxUInt32Item>(ID_VAL_WHATLAYOUT);
231 SdDrawDocument* pDocument = mrViewShell.GetDoc();
232 if( !pDocument )
233 return;
235 SdPage* pPage = nullptr;
236 if( pWhatPage )
238 pPage = pDocument->GetSdPage(static_cast<sal_uInt16>(pWhatPage->GetValue()), ePageKind);
241 if( pPage == nullptr )
242 pPage = mrViewShell.getCurrentPage();
244 if( !pPage )
245 return;
247 AutoLayout eLayout = pPage->GetAutoLayout();
249 if( pWhatLayout )
250 eLayout = static_cast< AutoLayout >( pWhatLayout->GetValue() );
252 // Transform the given request into the four argument form that is
253 // understood by ProcessModifyPageSlot().
254 SdrLayerAdmin& rLayerAdmin (mrViewShell.GetViewShellBase().GetDocument()->GetLayerAdmin());
255 SdrLayerID aBackground (rLayerAdmin.GetLayerID(sUNO_LayerName_background));
256 SdrLayerID aBackgroundObject (rLayerAdmin.GetLayerID(sUNO_LayerName_background_objects));
258 SdrLayerIDSet aVisibleLayers;
260 if( pPage->GetPageKind() == PageKind::Handout )
261 aVisibleLayers.SetAll();
262 else
263 aVisibleLayers = pPage->TRG_GetMasterPageVisibleLayers();
265 SfxRequest aRequest(mrViewShell.GetViewShellBase().GetViewFrame(), SID_MODIFYPAGE);
266 aRequest.AppendItem(SfxStringItem (ID_VAL_PAGENAME, pPage->GetName()));
267 aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, eLayout));
268 aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground)));
269 aRequest.AppendItem(SfxBoolItem(ID_VAL_ISPAGEOBJ, aVisibleLayers.IsSet(aBackgroundObject)));
271 // Forward the call with the new arguments.
272 ProcessModifyPageSlot( aRequest, pPage, pPage->GetPageKind());
275 SfxInterfaceId ViewShell::Implementation::GetViewId() const
277 switch (mrViewShell.GetShellType())
279 case ViewShell::ST_IMPRESS:
280 case ViewShell::ST_NOTES:
281 case ViewShell::ST_HANDOUT:
282 return IMPRESS_FACTORY_ID;
284 case ViewShell::ST_DRAW:
285 return DRAW_FACTORY_ID;
287 case ViewShell::ST_OUTLINE:
288 return OUTLINE_FACTORY_ID;
290 case ViewShell::ST_SLIDE_SORTER:
291 return SLIDE_SORTER_FACTORY_ID;
293 case ViewShell::ST_PRESENTATION:
294 return PRESENTATION_FACTORY_ID;
296 // Since we have to return a view id for every possible shell type
297 // and there is not (yet) a proper ViewShellBase sub class for the
298 // remaining types we chose the Impress factory as a fall back.
299 case ViewShell::ST_NOTESPANEL:
300 case ViewShell::ST_SIDEBAR:
301 case ViewShell::ST_NONE:
302 default:
303 return IMPRESS_FACTORY_ID;
307 SvxIMapDlg* ViewShell::Implementation::GetImageMapDialog()
309 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
310 if (!pViewFrm)
311 return nullptr;
313 SfxChildWindow* pChildWindow = pViewFrm->GetChildWindow(
314 SvxIMapDlgChildWindow::GetChildWindowId());
315 if (pChildWindow == nullptr)
316 return nullptr;
318 return dynamic_cast<SvxIMapDlg*>(pChildWindow->GetController().get());
321 //===== ToolBarManagerLock ====================================================
323 class ViewShell::Implementation::ToolBarManagerLock::Deleter { public:
324 void operator() (ToolBarManagerLock* pObject) { delete pObject; }
327 std::shared_ptr<ViewShell::Implementation::ToolBarManagerLock>
328 ViewShell::Implementation::ToolBarManagerLock::Create (
329 const std::shared_ptr<ToolBarManager>& rpManager)
331 std::shared_ptr<ToolBarManagerLock> pLock (
332 new ViewShell::Implementation::ToolBarManagerLock(rpManager),
333 ViewShell::Implementation::ToolBarManagerLock::Deleter());
334 pLock->mpSelf = pLock;
335 return pLock;
338 ViewShell::Implementation::ToolBarManagerLock::ToolBarManagerLock (
339 const std::shared_ptr<ToolBarManager>& rpManager)
340 : mpLock(new ToolBarManager::UpdateLock(rpManager)),
341 maTimer("sd ToolBarManagerLock maTimer")
343 // Start a timer that will unlock the ToolBarManager update lock when
344 // that is not done explicitly by calling Release().
345 maTimer.SetInvokeHandler(LINK(this,ToolBarManagerLock,TimeoutCallback));
346 maTimer.SetTimeout(100);
347 maTimer.Start();
350 IMPL_LINK_NOARG(ViewShell::Implementation::ToolBarManagerLock, TimeoutCallback, Timer *, void)
352 // If possible then release the lock now. Otherwise start the timer
353 // and try again later.
354 if (Application::IsUICaptured())
356 maTimer.Start();
358 else
360 mpSelf.reset();
364 void ViewShell::Implementation::ToolBarManagerLock::Release (bool bForce)
366 // If possible then release the lock now. Otherwise try again when the
367 // timer expires.
368 if (bForce || ! Application::IsUICaptured())
370 mpSelf.reset();
374 ViewShell::Implementation::ToolBarManagerLock::~ToolBarManagerLock()
376 mpLock.reset();
379 } // end of namespace sd
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */