/src/libreoffice/sfx2/source/control/request.cxx
Line | Count | Source |
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 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <memory> |
21 | | #include <com/sun/star/frame/DispatchStatement.hpp> |
22 | | #include <com/sun/star/container/XIndexReplace.hpp> |
23 | | #include <com/sun/star/beans/PropertyValue.hpp> |
24 | | #include <com/sun/star/uno/Sequence.hxx> |
25 | | #include <com/sun/star/beans/XPropertySet.hpp> |
26 | | #include <com/sun/star/util/URLTransformer.hpp> |
27 | | #include <com/sun/star/util/XURLTransformer.hpp> |
28 | | #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp> |
29 | | #include <svl/itemiter.hxx> |
30 | | #include <sal/log.hxx> |
31 | | #include <osl/diagnose.h> |
32 | | #include <tools/debug.hxx> |
33 | | |
34 | | #include <svl/itempool.hxx> |
35 | | |
36 | | #include <comphelper/processfactory.hxx> |
37 | | |
38 | | #include <svl/hint.hxx> |
39 | | |
40 | | #include <sfx2/request.hxx> |
41 | | #include <sfx2/dispatch.hxx> |
42 | | #include <sfx2/msg.hxx> |
43 | | #include <sfx2/viewfrm.hxx> |
44 | | #include <sfx2/objface.hxx> |
45 | | #include <sfx2/sfxuno.hxx> |
46 | | |
47 | | |
48 | | using namespace ::com::sun::star; |
49 | | |
50 | | struct SfxRequest_Impl: public SfxListener |
51 | | |
52 | | /* [Description] |
53 | | |
54 | | Implementation structure of the <SfxRequest> class. |
55 | | */ |
56 | | |
57 | | { |
58 | | SfxRequest* pAnti; // Owner because of dying pool |
59 | | OUString aTarget; // if possible from target object set by App |
60 | | SfxItemPool* pPool; // ItemSet build with this pool |
61 | | SfxPoolItemHolder aRetVal; // Return value belongs to itself |
62 | | SfxShell* pShell; // run from this shell |
63 | | const SfxSlot* pSlot; // executed Slot |
64 | | sal_uInt16 nModifier; // which Modifier was pressed? |
65 | | bool bDone; // at all executed |
66 | | bool bIgnored; // Cancelled by the User |
67 | | bool bCancelled; // no longer notify |
68 | | SfxCallMode nCallMode; // Synch/Asynch/API/Record |
69 | | bool bAllowRecording; |
70 | | std::unique_ptr<SfxAllItemSet> |
71 | | pInternalArgs; |
72 | | SfxViewFrame* pViewFrame; |
73 | | int m_nLokViewId = -1; |
74 | | |
75 | | css::uno::Reference< css::frame::XDispatchRecorder > xRecorder; |
76 | | css::uno::Reference< css::util::XURLTransformer > xTransform; |
77 | | |
78 | | explicit SfxRequest_Impl( SfxRequest *pOwner ) |
79 | 0 | : pAnti( pOwner) |
80 | 0 | , pPool(nullptr) |
81 | 0 | , pShell(nullptr) |
82 | 0 | , pSlot(nullptr) |
83 | 0 | , nModifier(0) |
84 | 0 | , bDone(false) |
85 | 0 | , bIgnored(false) |
86 | 0 | , bCancelled(false) |
87 | 0 | , nCallMode( SfxCallMode::SYNCHRON ) |
88 | 0 | , bAllowRecording( false ) |
89 | 0 | , pViewFrame(nullptr) |
90 | 0 | { |
91 | 0 | } |
92 | | |
93 | | void SetPool( SfxItemPool *pNewPool ); |
94 | | virtual void Notify( SfxBroadcaster &rBC, const SfxHint &rHint ) override; |
95 | | void Record( const uno::Sequence < beans::PropertyValue >& rArgs ); |
96 | | }; |
97 | | |
98 | | |
99 | | void SfxRequest_Impl::Notify( SfxBroadcaster&, const SfxHint &rHint ) |
100 | 0 | { |
101 | 0 | if ( rHint.GetId() == SfxHintId::Dying ) |
102 | 0 | pAnti->Cancel(); |
103 | 0 | } |
104 | | |
105 | | |
106 | | void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool ) |
107 | 0 | { |
108 | 0 | if ( pNewPool != pPool ) |
109 | 0 | { |
110 | 0 | if ( pPool ) |
111 | 0 | EndListening( pPool->BC() ); |
112 | | |
113 | | // tdf#159719 reset SfxPoolItemHolder |
114 | 0 | aRetVal = SfxPoolItemHolder(); |
115 | |
|
116 | 0 | pPool = pNewPool; |
117 | |
|
118 | 0 | if ( pNewPool ) |
119 | 0 | StartListening( pNewPool->BC() ); |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | | |
124 | | SfxRequest::~SfxRequest() |
125 | 0 | { |
126 | | // Leave out Done() marked requests with 'rem' |
127 | 0 | if ( pImpl->xRecorder.is() && !pImpl->bDone && !pImpl->bIgnored ) |
128 | 0 | pImpl->Record( uno::Sequence < beans::PropertyValue >() ); |
129 | | |
130 | | // Clear object |
131 | 0 | pArgs.reset(); |
132 | 0 | } |
133 | | |
134 | | |
135 | | SfxRequest::SfxRequest |
136 | | ( |
137 | | const SfxRequest& rOrig |
138 | | ) |
139 | 0 | : nSlot(rOrig.nSlot), |
140 | 0 | pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): nullptr), |
141 | 0 | pImpl( new SfxRequest_Impl(this) ) |
142 | 0 | { |
143 | 0 | pImpl->bAllowRecording = rOrig.pImpl->bAllowRecording; |
144 | 0 | pImpl->bDone = false; |
145 | 0 | pImpl->bIgnored = false; |
146 | 0 | pImpl->pShell = nullptr; |
147 | 0 | pImpl->pSlot = nullptr; |
148 | 0 | pImpl->nCallMode = rOrig.pImpl->nCallMode; |
149 | 0 | pImpl->aTarget = rOrig.pImpl->aTarget; |
150 | 0 | pImpl->nModifier = rOrig.pImpl->nModifier; |
151 | | |
152 | | // deep copy needed ! |
153 | 0 | pImpl->pInternalArgs.reset( rOrig.pImpl->pInternalArgs ? new SfxAllItemSet(*rOrig.pImpl->pInternalArgs) : nullptr); |
154 | |
|
155 | 0 | if ( pArgs ) |
156 | 0 | pImpl->SetPool( pArgs->GetPool() ); |
157 | 0 | else |
158 | 0 | pImpl->SetPool( rOrig.pImpl->pPool ); |
159 | | |
160 | | // setup macro recording if it was in the original SfxRequest |
161 | 0 | if (!rOrig.pImpl->pViewFrame || !rOrig.pImpl->xRecorder.is()) |
162 | 0 | return; |
163 | | |
164 | 0 | nSlot = rOrig.nSlot; |
165 | 0 | pImpl->pViewFrame = rOrig.pImpl->pViewFrame; |
166 | 0 | if (pImpl->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl(nSlot, &pImpl->pShell, &pImpl->pSlot, true, true)) |
167 | 0 | { |
168 | 0 | pImpl->SetPool( &pImpl->pShell->GetPool() ); |
169 | 0 | pImpl->xRecorder = SfxRequest::GetMacroRecorder(*pImpl->pViewFrame); |
170 | 0 | if (pImpl->xRecorder) |
171 | 0 | pImpl->xTransform = util::URLTransformer::create(comphelper::getProcessComponentContext()); |
172 | 0 | pImpl->aTarget = pImpl->pShell->GetName(); |
173 | 0 | } |
174 | 0 | else |
175 | 0 | { |
176 | 0 | SAL_WARN("sfx", "Recording unsupported slot: " << pImpl->pPool->GetSlotId(nSlot)); |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | | |
181 | | /* [Description] |
182 | | |
183 | | With this constructor events can subsequently be recorded that are not run |
184 | | across SfxDispatcher (eg from KeyInput() or mouse events). For this, a |
185 | | SfxRequest instance is created by this constructor and then proceed |
186 | | exactly as with a SfxRequest that in a <Slot-Execute-Method> is given as a |
187 | | parameter. |
188 | | */ |
189 | | |
190 | | SfxRequest::SfxRequest(SfxViewFrame& rViewFrame, sal_uInt16 nSlotId) |
191 | 0 | : nSlot(nSlotId) |
192 | 0 | , pImpl(new SfxRequest_Impl(this)) |
193 | 0 | { |
194 | 0 | pImpl->bDone = false; |
195 | 0 | pImpl->bIgnored = false; |
196 | 0 | pImpl->SetPool( &rViewFrame.GetPool() ); |
197 | 0 | pImpl->pShell = nullptr; |
198 | 0 | pImpl->pSlot = nullptr; |
199 | 0 | pImpl->nCallMode = SfxCallMode::SYNCHRON; |
200 | 0 | pImpl->pViewFrame = &rViewFrame; |
201 | 0 | if( pImpl->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl( nSlotId, &pImpl->pShell, &pImpl->pSlot, true, true ) ) |
202 | 0 | { |
203 | 0 | pImpl->SetPool( &pImpl->pShell->GetPool() ); |
204 | 0 | pImpl->xRecorder = SfxRequest::GetMacroRecorder(rViewFrame); |
205 | 0 | if (pImpl->xRecorder) |
206 | 0 | pImpl->xTransform = util::URLTransformer::create(comphelper::getProcessComponentContext()); |
207 | 0 | pImpl->aTarget = pImpl->pShell->GetName(); |
208 | 0 | } |
209 | 0 | else |
210 | 0 | { |
211 | 0 | SAL_WARN( "sfx", "Recording unsupported slot: " << pImpl->pPool->GetSlotId(nSlotId) ); |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | | |
216 | | SfxRequest::SfxRequest |
217 | | ( |
218 | | sal_uInt16 nSlotId, // executed <Slot-Id> |
219 | | SfxCallMode nMode, // Synch/API/... |
220 | | SfxItemPool& rPool // necessary for the SfxItemSet for parameters |
221 | | ) |
222 | | |
223 | | // creates a SfxRequest without arguments |
224 | | |
225 | 0 | : nSlot(nSlotId), |
226 | 0 | pImpl( new SfxRequest_Impl(this) ) |
227 | 0 | { |
228 | 0 | pImpl->bDone = false; |
229 | 0 | pImpl->bIgnored = false; |
230 | 0 | pImpl->SetPool( &rPool ); |
231 | 0 | pImpl->pShell = nullptr; |
232 | 0 | pImpl->pSlot = nullptr; |
233 | 0 | pImpl->nCallMode = nMode; |
234 | 0 | } |
235 | | |
236 | | SfxRequest::SfxRequest |
237 | | ( |
238 | | const SfxSlot* pSlot, // executed <Slot-Id> |
239 | | const css::uno::Sequence < css::beans::PropertyValue >& rArgs, |
240 | | SfxCallMode nMode, // Synch/API/... |
241 | | SfxItemPool& rPool // necessary for the SfxItemSet for parameters |
242 | | ) |
243 | 0 | : nSlot(pSlot->GetSlotId()), |
244 | 0 | pArgs(new SfxAllItemSet(rPool)), |
245 | 0 | pImpl( new SfxRequest_Impl(this) ) |
246 | 0 | { |
247 | 0 | pImpl->bDone = false; |
248 | 0 | pImpl->bIgnored = false; |
249 | 0 | pImpl->SetPool( &rPool ); |
250 | 0 | pImpl->pShell = nullptr; |
251 | 0 | pImpl->pSlot = nullptr; |
252 | 0 | pImpl->nCallMode = nMode; |
253 | 0 | TransformParameters( nSlot, rArgs, *pArgs, pSlot ); |
254 | 0 | } |
255 | | |
256 | | |
257 | | SfxRequest::SfxRequest |
258 | | ( |
259 | | sal_uInt16 nSlotId, |
260 | | SfxCallMode nMode, |
261 | | const SfxAllItemSet& rSfxArgs |
262 | | ) |
263 | | |
264 | | // creates a SfxRequest with arguments |
265 | | |
266 | 0 | : nSlot(nSlotId), |
267 | 0 | pArgs(new SfxAllItemSet(rSfxArgs)), |
268 | 0 | pImpl( new SfxRequest_Impl(this) ) |
269 | 0 | { |
270 | 0 | pImpl->bDone = false; |
271 | 0 | pImpl->bIgnored = false; |
272 | 0 | pImpl->SetPool( rSfxArgs.GetPool() ); |
273 | 0 | pImpl->pShell = nullptr; |
274 | 0 | pImpl->pSlot = nullptr; |
275 | 0 | pImpl->nCallMode = nMode; |
276 | 0 | } |
277 | | |
278 | | |
279 | | SfxRequest::SfxRequest |
280 | | ( |
281 | | sal_uInt16 nSlotId, |
282 | | SfxCallMode nMode, |
283 | | const SfxAllItemSet& rSfxArgs, |
284 | | const SfxAllItemSet& rSfxInternalArgs |
285 | | ) |
286 | 0 | : SfxRequest(nSlotId, nMode, rSfxArgs) |
287 | 0 | { |
288 | 0 | SetInternalArgs_Impl(rSfxInternalArgs); |
289 | 0 | } |
290 | | |
291 | | SfxCallMode SfxRequest::GetCallMode() const |
292 | 0 | { |
293 | 0 | return pImpl->nCallMode; |
294 | 0 | } |
295 | | |
296 | | |
297 | | bool SfxRequest::IsSynchronCall() const |
298 | 0 | { |
299 | 0 | return SfxCallMode::SYNCHRON == ( SfxCallMode::SYNCHRON & pImpl->nCallMode ); |
300 | 0 | } |
301 | | |
302 | | |
303 | | void SfxRequest::SetSynchronCall( bool bSynchron ) |
304 | 0 | { |
305 | 0 | if ( bSynchron ) |
306 | 0 | pImpl->nCallMode |= SfxCallMode::SYNCHRON; |
307 | 0 | else |
308 | 0 | pImpl->nCallMode &= ~SfxCallMode::SYNCHRON; |
309 | 0 | } |
310 | | |
311 | | void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs ) |
312 | 0 | { |
313 | 0 | pImpl->pInternalArgs.reset( new SfxAllItemSet( rArgs ) ); |
314 | 0 | } |
315 | | |
316 | | const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const |
317 | 0 | { |
318 | 0 | return pImpl->pInternalArgs.get(); |
319 | 0 | } |
320 | | |
321 | | |
322 | | void SfxRequest_Impl::Record |
323 | | ( |
324 | | const uno::Sequence < beans::PropertyValue >& rArgs // current Parameter |
325 | | ) |
326 | | |
327 | | /* [Description] |
328 | | |
329 | | Internal helper method to create a repeatable description of the just |
330 | | executed SfxRequest. |
331 | | */ |
332 | | |
333 | 0 | { |
334 | 0 | if(!xRecorder.is()) |
335 | 0 | return; |
336 | | |
337 | 0 | OUString aCmd = pSlot->GetCommand(); |
338 | |
|
339 | 0 | uno::Reference< container::XIndexReplace > xReplace( xRecorder, uno::UNO_QUERY ); |
340 | 0 | if ( xReplace.is() && aCmd == ".uno:InsertText" ) |
341 | 0 | { |
342 | 0 | sal_Int32 nCount = xReplace->getCount(); |
343 | 0 | if ( nCount ) |
344 | 0 | { |
345 | 0 | frame::DispatchStatement aStatement; |
346 | 0 | uno::Any aElement = xReplace->getByIndex(nCount-1); |
347 | 0 | if ( (aElement >>= aStatement) && aStatement.aCommand == aCmd ) |
348 | 0 | { |
349 | 0 | OUString aStr; |
350 | 0 | OUString aNew; |
351 | 0 | aStatement.aArgs[0].Value >>= aStr; |
352 | 0 | rArgs[0].Value >>= aNew; |
353 | 0 | aStr += aNew; |
354 | 0 | aStatement.aArgs.getArray()[0].Value <<= aStr; |
355 | 0 | aElement <<= aStatement; |
356 | 0 | xReplace->replaceByIndex( nCount-1, aElement ); |
357 | 0 | return; |
358 | 0 | } |
359 | 0 | } |
360 | 0 | } |
361 | | |
362 | 0 | css::util::URL aURL; |
363 | 0 | aURL.Complete = aCmd; |
364 | 0 | xTransform->parseStrict(aURL); |
365 | |
|
366 | 0 | if (bDone) |
367 | 0 | xRecorder->recordDispatch(aURL,rArgs); |
368 | 0 | else |
369 | 0 | xRecorder->recordDispatchAsComment(aURL,rArgs); |
370 | 0 | } |
371 | | |
372 | | |
373 | | void SfxRequest::Record_Impl |
374 | | ( |
375 | | SfxShell& rSh, // the <SfxShell>, which has executed the Request |
376 | | const SfxSlot& rSlot, // the <SfxSlot>, which has executed the Request |
377 | | const css::uno::Reference< css::frame::XDispatchRecorder >& xRecorder, |
378 | | SfxViewFrame* pViewFrame |
379 | | ) |
380 | | |
381 | | /* [Description] |
382 | | |
383 | | This internal method marks the specified SfxMakro SfxRequest as recorded in |
384 | | SfxMakro. Pointer to the parameters in Done() is used again, thus has to |
385 | | still be alive. |
386 | | */ |
387 | | |
388 | 0 | { |
389 | 0 | pImpl->pShell = &rSh; |
390 | 0 | pImpl->pSlot = &rSlot; |
391 | 0 | pImpl->xRecorder = xRecorder; |
392 | 0 | if (pImpl->xRecorder && !pImpl->xTransform) |
393 | 0 | pImpl->xTransform = util::URLTransformer::create(comphelper::getProcessComponentContext()); |
394 | 0 | pImpl->aTarget = rSh.GetName(); |
395 | 0 | pImpl->pViewFrame = pViewFrame; |
396 | 0 | } |
397 | | |
398 | | |
399 | | void SfxRequest::SetArgs( const SfxAllItemSet& rArgs ) |
400 | 0 | { |
401 | 0 | pArgs.reset(new SfxAllItemSet(rArgs)); |
402 | 0 | pImpl->SetPool( pArgs->GetPool() ); |
403 | 0 | } |
404 | | |
405 | | |
406 | | void SfxRequest::AppendItem(const SfxPoolItem &rItem) |
407 | 0 | { |
408 | 0 | if(!pArgs) |
409 | 0 | pArgs.reset( new SfxAllItemSet(*pImpl->pPool) ); |
410 | 0 | pArgs->Put(rItem); |
411 | 0 | } |
412 | | |
413 | | |
414 | | void SfxRequest::RemoveItem( sal_uInt16 nID ) |
415 | 0 | { |
416 | 0 | if (pArgs) |
417 | 0 | { |
418 | 0 | pArgs->ClearItem(nID); |
419 | 0 | if ( !pArgs->Count() ) |
420 | 0 | pArgs.reset(); |
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | | void SfxRequest::SetReturnValue(const SfxPoolItem &rItem) |
425 | 0 | { |
426 | 0 | DBG_ASSERT(nullptr != pImpl->pPool, "Missing SfxItemPool (!)"); |
427 | 0 | if (nullptr != pImpl->pPool) |
428 | 0 | pImpl->aRetVal = SfxPoolItemHolder(*pImpl->pPool, &rItem); |
429 | 0 | } |
430 | | |
431 | | |
432 | | const SfxPoolItemHolder& SfxRequest::GetReturnValue() const |
433 | 0 | { |
434 | 0 | return pImpl->aRetVal; |
435 | 0 | } |
436 | | |
437 | | |
438 | | void SfxRequest::Done |
439 | | ( |
440 | | const SfxItemSet& rSet /* parameters passed on by the application, |
441 | | that for example were asked for by the user |
442 | | in a dialogue, 0 if no parameters have been |
443 | | set */ |
444 | | ) |
445 | | |
446 | | /* [Description] |
447 | | |
448 | | This method must be called in the <Execute-Method> of the <SfxSlot>s, which |
449 | | has performed the SfxRequest when the execution actually took place. If |
450 | | 'Done()' is not called, then the SfxRequest is considered canceled. |
451 | | |
452 | | Any return values are passed only when 'Done()' was called. Similar, when |
453 | | recording a macro only true statements are generated if 'Done()' was |
454 | | called; for SfxRequests that were not identified as such will instead |
455 | | be commented out by inserting ('rem'). |
456 | | |
457 | | [Note] |
458 | | |
459 | | 'Done ()' is not called, for example when a dialog started by the function |
460 | | was canceled by the user or if the execution could not be performed due to |
461 | | a wrong context (without use of separate <SfxShell>s). 'Done ()' will be |
462 | | launched, when executing the function led to a regular error |
463 | | (for example, file could not be opened). |
464 | | */ |
465 | | |
466 | 0 | { |
467 | 0 | Done_Impl( &rSet ); |
468 | | |
469 | | // Keep items if possible, so they can be queried by StarDraw. |
470 | 0 | if ( !pArgs ) |
471 | 0 | { |
472 | 0 | pArgs.reset( new SfxAllItemSet( rSet ) ); |
473 | 0 | pImpl->SetPool( pArgs->GetPool() ); |
474 | 0 | } |
475 | 0 | else |
476 | 0 | { |
477 | 0 | SfxItemIter aIter(rSet); |
478 | 0 | for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) |
479 | 0 | { |
480 | 0 | if(!IsInvalidItem(pItem)) |
481 | 0 | pArgs->Put(*pItem); |
482 | 0 | } |
483 | 0 | } |
484 | 0 | } |
485 | | |
486 | | |
487 | | void SfxRequest::Done( bool bRelease ) |
488 | | // [<SfxRequest::Done(SfxItemSet&)>] |
489 | 0 | { |
490 | 0 | Done_Impl( pArgs.get() ); |
491 | 0 | if( bRelease ) |
492 | 0 | pArgs.reset(); |
493 | 0 | } |
494 | | |
495 | | |
496 | | void SfxRequest::ForgetAllArgs() |
497 | 0 | { |
498 | 0 | pArgs.reset(); |
499 | 0 | pImpl->pInternalArgs.reset(); |
500 | 0 | } |
501 | | |
502 | | |
503 | | bool SfxRequest::IsCancelled() const |
504 | 0 | { |
505 | 0 | return pImpl->bCancelled; |
506 | 0 | } |
507 | | |
508 | | |
509 | | void SfxRequest::Cancel() |
510 | | |
511 | | /* [Description] |
512 | | |
513 | | Marks this request as no longer executable. For example, if called when |
514 | | the target (more precisely, its pool) dies. |
515 | | */ |
516 | | |
517 | 0 | { |
518 | 0 | pImpl->bCancelled = true; |
519 | 0 | pImpl->SetPool( nullptr ); |
520 | 0 | pArgs.reset(); |
521 | 0 | } |
522 | | |
523 | | |
524 | | void SfxRequest::Ignore() |
525 | | |
526 | | /* [Description] |
527 | | |
528 | | If this method is called instead of <SfxRequest::Done()>, then this |
529 | | request is not recorded. |
530 | | |
531 | | [Example] |
532 | | |
533 | | The selecting of tools in StarDraw should not be recorded, but the same |
534 | | slots are to be used from the generation of the tools to the generated |
535 | | objects. Thus can NoRecords not be specified, i.e. should not be recorded. |
536 | | */ |
537 | | |
538 | 0 | { |
539 | | // Mark as actually executed |
540 | 0 | pImpl->bIgnored = true; |
541 | 0 | } |
542 | | |
543 | | |
544 | | void SfxRequest::Done_Impl |
545 | | ( |
546 | | const SfxItemSet* pSet /* parameters passed on by the application, |
547 | | that for example were asked for by the user |
548 | | in a dialogue, 0 if no parameters have been |
549 | | set */ |
550 | | |
551 | | ) |
552 | | |
553 | | /* [Description] |
554 | | |
555 | | Internal method to mark SfxRequest with 'done' and to evaluate the |
556 | | parameters in 'pSet' in case it is recorded. |
557 | | */ |
558 | | |
559 | 0 | { |
560 | | // Mark as actually executed |
561 | 0 | pImpl->bDone = true; |
562 | | |
563 | | // not Recording |
564 | 0 | if ( !pImpl->xRecorder.is() ) |
565 | 0 | return; |
566 | | |
567 | | // was running a different slot than requested (Delegation) |
568 | 0 | if ( nSlot != pImpl->pSlot->GetSlotId() ) |
569 | 0 | { |
570 | | // Search Slot again |
571 | 0 | pImpl->pSlot = pImpl->pShell->GetInterface()->GetSlot(nSlot); |
572 | 0 | DBG_ASSERT( pImpl->pSlot, "delegated SlotId not found" ); |
573 | 0 | if ( !pImpl->pSlot ) // playing it safe |
574 | 0 | return; |
575 | 0 | } |
576 | | |
577 | | // recordable? |
578 | | // new Recording uses UnoName! |
579 | 0 | SAL_WARN_IF( pImpl->pSlot->aUnoName.isEmpty(), "sfx", "Recording not exported slot: " |
580 | 0 | << pImpl->pSlot->GetSlotId() ); |
581 | | |
582 | 0 | if ( pImpl->pSlot->aUnoName.isEmpty() ) // playing it safe |
583 | 0 | return; |
584 | | |
585 | | // often required values |
586 | 0 | SfxItemPool &rPool = pImpl->pShell->GetPool(); |
587 | | |
588 | | // Property-Slot? |
589 | 0 | if ( !pImpl->pSlot->IsMode(SfxSlotMode::METHOD) ) |
590 | 0 | { |
591 | | // get the property as SfxPoolItem |
592 | 0 | const SfxPoolItem *pItem(nullptr); |
593 | 0 | const sal_uInt16 nWhich(rPool.GetWhichIDFromSlotID(pImpl->pSlot->GetSlotId())); |
594 | 0 | const bool bItemStateSet(nullptr != pSet); |
595 | 0 | const SfxItemState eState(bItemStateSet ? pSet->GetItemState( nWhich, false, &pItem ) : SfxItemState::DEFAULT); |
596 | 0 | SAL_WARN_IF( !bItemStateSet || SfxItemState::SET != eState, "sfx", "Recording property not available: " |
597 | 0 | << pImpl->pSlot->GetSlotId() ); |
598 | 0 | uno::Sequence < beans::PropertyValue > aSeq; |
599 | |
|
600 | 0 | if ( bItemStateSet && SfxItemState::SET == eState ) |
601 | 0 | aSeq = TransformItems(pImpl->pSlot->GetSlotId(), *pSet, pImpl->pSlot).getAsConstPropertyValueList(); |
602 | |
|
603 | 0 | pImpl->Record( aSeq ); |
604 | 0 | } |
605 | | |
606 | | // record everything in a single statement? |
607 | 0 | else if ( pImpl->pSlot->IsMode(SfxSlotMode::RECORDPERSET) ) |
608 | 0 | { |
609 | 0 | uno::Sequence < beans::PropertyValue > aSeq; |
610 | 0 | if ( pSet ) |
611 | 0 | aSeq = TransformItems(pImpl->pSlot->GetSlotId(), *pSet, pImpl->pSlot).getAsConstPropertyValueList(); |
612 | 0 | pImpl->Record( aSeq ); |
613 | 0 | } |
614 | | |
615 | | // record each item as a single statement |
616 | 0 | else if ( pImpl->pSlot->IsMode(SfxSlotMode::RECORDPERITEM) ) |
617 | 0 | { |
618 | 0 | if ( pSet ) |
619 | 0 | { |
620 | | // iterate over Items |
621 | 0 | SfxItemIter aIter(*pSet); |
622 | 0 | for ( const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem() ) |
623 | 0 | { |
624 | | // to determine the slot ID for the individual item |
625 | 0 | sal_uInt16 nSlotId = rPool.GetSlotId( pItem->Which() ); |
626 | 0 | if ( nSlotId == nSlot ) |
627 | 0 | { |
628 | | // play it safe; repair the wrong flags |
629 | 0 | OSL_FAIL( "recursion RecordPerItem - use RecordPerSet!" ); |
630 | 0 | SfxSlot *pSlot = const_cast<SfxSlot*>(pImpl->pSlot); |
631 | 0 | pSlot->nFlags &= ~SfxSlotMode::RECORDPERITEM; |
632 | 0 | pSlot->nFlags &= SfxSlotMode::RECORDPERSET; |
633 | 0 | } |
634 | | |
635 | | // Record a Sub-Request |
636 | 0 | SfxRequest aReq( *pImpl->pViewFrame, nSlotId ); |
637 | 0 | if ( aReq.pImpl->pSlot ) |
638 | 0 | aReq.AppendItem( *pItem ); |
639 | 0 | aReq.Done(); |
640 | 0 | } |
641 | 0 | } |
642 | 0 | else |
643 | 0 | { |
644 | | //HACK(think about this again) |
645 | 0 | pImpl->Record( uno::Sequence < beans::PropertyValue >() ); |
646 | 0 | } |
647 | 0 | } |
648 | 0 | } |
649 | | |
650 | | |
651 | | bool SfxRequest::IsDone() const |
652 | | |
653 | | /* [Description] |
654 | | |
655 | | With this method it can be queried whether the SfxRequest was actually |
656 | | executed or not. If a SfxRequest was not executed, then this is for example |
657 | | because it was canceled by the user or the context for this request was |
658 | | wrong, this was not implemented on a separate <SfxShell>. |
659 | | |
660 | | SfxRequest instances that return false will not be recorded. |
661 | | |
662 | | [Cross-reference] |
663 | | |
664 | | <SfxRequest::Done(const SfxItemSet&)> |
665 | | <SfxRequest::Done()> |
666 | | */ |
667 | | |
668 | 0 | { |
669 | 0 | return pImpl->bDone; |
670 | 0 | } |
671 | | |
672 | | |
673 | | css::uno::Reference< css::frame::XDispatchRecorder > SfxRequest::GetMacroRecorder(const SfxViewFrame& rView) |
674 | | |
675 | | /* [Description] |
676 | | |
677 | | This recorder is an attempt for dispatch () to get calls from the Frame. |
678 | | This is then available through a property by a supplier but only when |
679 | | recording was turned on. |
680 | | |
681 | | (See also SfxViewFrame::MiscExec_Impl() and SID_RECORDING) |
682 | | */ |
683 | | |
684 | 0 | { |
685 | 0 | css::uno::Reference< css::frame::XDispatchRecorder > xRecorder; |
686 | |
|
687 | 0 | css::uno::Reference< css::beans::XPropertySet > xSet( |
688 | 0 | rView.GetFrame().GetFrameInterface(), |
689 | 0 | css::uno::UNO_QUERY); |
690 | |
|
691 | 0 | if(xSet.is()) |
692 | 0 | { |
693 | 0 | css::uno::Any aProp = xSet->getPropertyValue(u"DispatchRecorderSupplier"_ustr); |
694 | 0 | css::uno::Reference< css::frame::XDispatchRecorderSupplier > xSupplier; |
695 | 0 | aProp >>= xSupplier; |
696 | 0 | if(xSupplier.is()) |
697 | 0 | xRecorder = xSupplier->getDispatchRecorder(); |
698 | 0 | } |
699 | |
|
700 | 0 | return xRecorder; |
701 | 0 | } |
702 | | |
703 | | bool SfxRequest::HasMacroRecorder(const SfxViewFrame& rView) |
704 | 0 | { |
705 | 0 | return GetMacroRecorder(rView).is(); |
706 | 0 | } |
707 | | |
708 | | bool SfxRequest::IsAPI() const |
709 | | |
710 | | /* [Description] |
711 | | |
712 | | Returns true if this SfxRequest was generated by an API (for example BASIC), |
713 | | otherwise false. |
714 | | */ |
715 | | |
716 | 0 | { |
717 | 0 | return SfxCallMode::API == ( SfxCallMode::API & pImpl->nCallMode ); |
718 | 0 | } |
719 | | |
720 | | |
721 | | void SfxRequest::SetModifier( sal_uInt16 nModi ) |
722 | 0 | { |
723 | 0 | pImpl->nModifier = nModi; |
724 | 0 | } |
725 | | |
726 | | |
727 | | sal_uInt16 SfxRequest::GetModifier() const |
728 | 0 | { |
729 | 0 | return pImpl->nModifier; |
730 | 0 | } |
731 | | |
732 | | |
733 | | void SfxRequest::AllowRecording( bool bSet ) |
734 | 0 | { |
735 | 0 | pImpl->bAllowRecording = bSet; |
736 | 0 | } |
737 | | |
738 | | bool SfxRequest::AllowsRecording() const |
739 | 0 | { |
740 | 0 | bool bAllow = pImpl->bAllowRecording; |
741 | 0 | if( !bAllow ) |
742 | 0 | bAllow = ( SfxCallMode::API != ( SfxCallMode::API & pImpl->nCallMode ) ) && |
743 | 0 | ( SfxCallMode::RECORD == ( SfxCallMode::RECORD & pImpl->nCallMode ) ); |
744 | 0 | return bAllow; |
745 | 0 | } |
746 | | |
747 | | void SfxRequest::ReleaseArgs() |
748 | 0 | { |
749 | 0 | pArgs.reset(); |
750 | 0 | pImpl->pInternalArgs.reset(); |
751 | 0 | } |
752 | | |
753 | | void SfxRequest::SetLokViewId(int nId) |
754 | 0 | { |
755 | 0 | pImpl->m_nLokViewId = nId; |
756 | 0 | } |
757 | | |
758 | | int SfxRequest::GetLokViewId() const |
759 | 0 | { |
760 | 0 | return pImpl->m_nLokViewId; |
761 | 0 | } |
762 | | |
763 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |