xref: /AOO41X/main/sfx2/source/control/request.cxx (revision d119d52d53d0b2180f2ae51341d882123be2af2b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_sfx2.hxx"
27 
28 #include <com/sun/star/frame/DispatchStatement.hpp>
29 #include <com/sun/star/container/XIndexReplace.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/util/XURLTransformer.hpp>
34 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
35 #include <svl/itemiter.hxx>
36 
37 #ifndef _ARGS_HXX //autogen
38 #include <svl/itempool.hxx>
39 #endif
40 #include <svtools/itemdel.hxx>
41 
42 #include <comphelper/processfactory.hxx>
43 
44 #ifndef GCC
45 #endif
46 
47 #include <svl/smplhint.hxx>
48 
49 #include <sfx2/request.hxx>
50 #include <sfx2/dispatch.hxx>
51 #include <sfx2/msg.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include "macro.hxx"
54 #include <sfx2/objface.hxx>
55 #include <sfx2/appuno.hxx>
56 
57 //===================================================================
58 
59 using namespace ::com::sun::star;
60 
61 struct SfxRequest_Impl: public SfxListener
62 
63 /*  [Beschreibung]
64 
65     Implementations-Struktur der Klasse <SfxRequest>.
66 */
67 
68 {
69     SfxRequest*         pAnti;       // Owner wegen sterbendem Pool
70     String              aTarget;     // ggf. von App gesetztes Zielobjekt
71     SfxItemPool*        pPool;       // ItemSet mit diesem Pool bauen
72     SfxPoolItem*        pRetVal;     // R"uckgabewert geh"ort sich selbst
73     SfxShell*           pShell;      // ausgef"uhrt an dieser Shell
74     const SfxSlot*      pSlot;       // ausgef"uhrter Slot
75     sal_uInt16              nModifier;   // welche Modifier waren gedrueckt?
76     sal_Bool                bDone;       // "uberhaupt ausgef"uhrt
77     sal_Bool                bIgnored;    // vom User abgebrochen
78     sal_Bool                bCancelled;  // nicht mehr zustellen
79     sal_Bool                bUseTarget;  // aTarget wurde von Applikation gesetzt
80     sal_uInt16              nCallMode;   // Synch/Asynch/API/Record
81     sal_Bool                bAllowRecording;
82     SfxAllItemSet*      pInternalArgs;
83     SfxViewFrame*       pViewFrame;
84 
85     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
86 
SfxRequest_ImplSfxRequest_Impl87                         SfxRequest_Impl( SfxRequest *pOwner )
88                         : pAnti( pOwner)
89                         , pPool(0)
90                         , nModifier(0)
91                         , bCancelled(sal_False)
92                         , nCallMode( SFX_CALLMODE_SYNCHRON )
93                         , bAllowRecording( sal_False )
94                         , pInternalArgs( 0 )
95                         , pViewFrame(0)
96                         {}
~SfxRequest_ImplSfxRequest_Impl97     ~SfxRequest_Impl() { delete pInternalArgs; }
98 
99 
100     void                SetPool( SfxItemPool *pNewPool );
101     virtual void        Notify( SfxBroadcaster &rBC, const SfxHint &rHint );
102     void                Record( const uno::Sequence < beans::PropertyValue >& rArgs );
103 };
104 
105 
106 //====================================================================
107 
Notify(SfxBroadcaster &,const SfxHint & rHint)108 void SfxRequest_Impl::Notify( SfxBroadcaster&, const SfxHint &rHint )
109 {
110     SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
111     if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
112         pAnti->Cancel();
113 }
114 
115 //====================================================================
116 
SetPool(SfxItemPool * pNewPool)117 void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool )
118 {
119     if ( pNewPool != pPool )
120     {
121         if ( pPool )
122             EndListening( pPool->BC() );
123         pPool = pNewPool;
124         if ( pNewPool )
125             StartListening( pNewPool->BC() );
126     }
127 }
128 
129 //====================================================================
130 
131 
~SfxRequest()132 SfxRequest::~SfxRequest()
133 {
134     DBG_MEMTEST();
135 
136     // nicht mit Done() marktierte Requests mit 'rem' rausschreiben
137     if ( pImp->xRecorder.is() && !pImp->bDone && !pImp->bIgnored )
138         pImp->Record( uno::Sequence < beans::PropertyValue >() );
139 
140     // Objekt abr"aumen
141     delete pArgs;
142     if ( pImp->pRetVal )
143         DeleteItemOnIdle(pImp->pRetVal);
144     delete pImp;
145 }
146 //--------------------------------------------------------------------
147 
148 
SfxRequest(const SfxRequest & rOrig)149 SfxRequest::SfxRequest
150 (
151     const SfxRequest& rOrig
152 )
153 :   SfxHint( rOrig ),
154     nSlot(rOrig.nSlot),
155     pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): 0),
156     pImp( new SfxRequest_Impl(this) )
157 {
158     DBG_MEMTEST();
159 
160     pImp->bAllowRecording = rOrig.pImp->bAllowRecording;
161     pImp->bDone = sal_False;
162     pImp->bIgnored = sal_False;
163     pImp->pRetVal = 0;
164     pImp->pShell = 0;
165     pImp->pSlot = 0;
166     pImp->nCallMode = rOrig.pImp->nCallMode;
167     pImp->bUseTarget = rOrig.pImp->bUseTarget;
168     pImp->aTarget = rOrig.pImp->aTarget;
169     pImp->nModifier = rOrig.pImp->nModifier;
170 
171     // deep copy needed !
172     pImp->pInternalArgs = (rOrig.pImp->pInternalArgs ? new SfxAllItemSet(*rOrig.pImp->pInternalArgs) : 0);
173 
174     if ( pArgs )
175         pImp->SetPool( pArgs->GetPool() );
176     else
177         pImp->SetPool( rOrig.pImp->pPool );
178 }
179 //--------------------------------------------------------------------
180 
181 
SfxRequest(SfxViewFrame * pViewFrame,sal_uInt16 nSlotId)182 SfxRequest::SfxRequest
183 (
184     SfxViewFrame*   pViewFrame,
185     sal_uInt16          nSlotId
186 
187 )
188 
189 /*  [Beschreibung]
190 
191     Mit diesem Konstruktor k"onnen Events, die nicht "uber den SfxDispatcher
192     gelaufen sind (z.B aus KeyInput() oder Mouse-Events) nachtr"aglich
193     recorded werden. Dazu wird eine SfxRequest-Instanz mit diesem Konstruktor
194     erzeugt und dann genauso verfahren, wie mit einem SfxRequest, der in
195     eine <Slot-Execute-Methode> als Parameter gegeben wird.
196 */
197 
198 :   nSlot(nSlotId),
199     pArgs(0),
200     pImp( new SfxRequest_Impl(this) )
201 {
202     DBG_MEMTEST();
203 
204     pImp->bDone = sal_False;
205     pImp->bIgnored = sal_False;
206     pImp->SetPool( &pViewFrame->GetPool() );
207     pImp->pRetVal = 0;
208     pImp->pShell = 0;
209     pImp->pSlot = 0;
210     pImp->nCallMode = SFX_CALLMODE_SYNCHRON;
211     pImp->bUseTarget = sal_False;
212     pImp->pViewFrame = pViewFrame;
213     if( pImp->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl( nSlotId, &pImp->pShell, &pImp->pSlot, sal_True, sal_True ) )
214     {
215         pImp->SetPool( &pImp->pShell->GetPool() );
216         pImp->xRecorder = SfxRequest::GetMacroRecorder( pViewFrame );
217         pImp->aTarget = pImp->pShell->GetName();
218     }
219 #ifdef DBG_UTIL
220     else
221     {
222         ByteString aStr( "Recording unsupported slot: ");
223         aStr += ByteString::CreateFromInt32( pImp->pPool->GetSlotId(nSlotId) );
224         DBG_ERROR( aStr.GetBuffer() );
225     }
226 #endif
227 }
228 
229 //--------------------------------------------------------------------
230 
231 
SfxRequest(sal_uInt16 nSlotId,SfxCallMode nMode,SfxItemPool & rPool)232 SfxRequest::SfxRequest
233 (
234     sal_uInt16          nSlotId,    // auszuf"uhrende <Slot-Id>
235     SfxCallMode     nMode,      // Synch/API/...
236     SfxItemPool&    rPool       // ggf. f"ur das SfxItemSet f"ur Parameter
237 )
238 
239 // creates a SfxRequest without arguments
240 
241 :   nSlot(nSlotId),
242     pArgs(0),
243     pImp( new SfxRequest_Impl(this) )
244 {
245     DBG_MEMTEST();
246 
247     pImp->bDone = sal_False;
248     pImp->bIgnored = sal_False;
249     pImp->SetPool( &rPool );
250     pImp->pRetVal = 0;
251     pImp->pShell = 0;
252     pImp->pSlot = 0;
253     pImp->nCallMode = nMode;
254     pImp->bUseTarget = sal_False;
255 }
256 
SfxRequest(const SfxSlot * pSlot,const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> & rArgs,SfxCallMode nMode,SfxItemPool & rPool)257 SfxRequest::SfxRequest
258 (
259     const SfxSlot* pSlot,   // auszuf"uhrende <Slot-Id>
260     const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rArgs,
261     SfxCallMode     nMode,      // Synch/API/...
262     SfxItemPool&    rPool       // ggf. f"ur das SfxItemSet f"ur Parameter
263 )
264 :   nSlot(pSlot->GetSlotId()),
265     pArgs(new SfxAllItemSet(rPool)),
266     pImp( new SfxRequest_Impl(this) )
267 {
268     DBG_MEMTEST();
269 
270     pImp->bDone = sal_False;
271     pImp->bIgnored = sal_False;
272     pImp->SetPool( &rPool );
273     pImp->pRetVal = 0;
274     pImp->pShell = 0;
275     pImp->pSlot = 0;
276     pImp->nCallMode = nMode;
277     pImp->bUseTarget = sal_False;
278     TransformParameters( nSlot, rArgs, *pArgs, pSlot );
279 }
280 
281 //-----------------------------------------------------------------------
282 
SfxRequest(sal_uInt16 nSlotId,sal_uInt16 nMode,const SfxAllItemSet & rSfxArgs)283 SfxRequest::SfxRequest
284 (
285     sal_uInt16                  nSlotId,
286     sal_uInt16                  nMode,
287     const SfxAllItemSet&    rSfxArgs
288 )
289 
290 // creates a SfxRequest with arguments
291 
292 :   nSlot(nSlotId),
293     pArgs(new SfxAllItemSet(rSfxArgs)),
294     pImp( new SfxRequest_Impl(this) )
295 {
296     DBG_MEMTEST();
297 
298     pImp->bDone = sal_False;
299     pImp->bIgnored = sal_False;
300     pImp->SetPool( rSfxArgs.GetPool() );
301     pImp->pRetVal = 0;
302     pImp->pShell = 0;
303     pImp->pSlot = 0;
304     pImp->nCallMode = nMode;
305     pImp->bUseTarget = sal_False;
306 }
307 //--------------------------------------------------------------------
308 
GetCallMode() const309 sal_uInt16 SfxRequest::GetCallMode() const
310 {
311     return pImp->nCallMode;
312 }
313 
314 //--------------------------------------------------------------------
315 
IsSynchronCall() const316 sal_Bool SfxRequest::IsSynchronCall() const
317 {
318     return SFX_CALLMODE_SYNCHRON == ( SFX_CALLMODE_SYNCHRON & pImp->nCallMode );
319 }
320 
321 //--------------------------------------------------------------------
322 
SetSynchronCall(sal_Bool bSynchron)323 void SfxRequest::SetSynchronCall( sal_Bool bSynchron )
324 {
325     if ( bSynchron )
326         pImp->nCallMode |= SFX_CALLMODE_SYNCHRON;
327     else
328         pImp->nCallMode &= ~(sal_uInt16) SFX_CALLMODE_SYNCHRON;
329 }
330 
SetInternalArgs_Impl(const SfxAllItemSet & rArgs)331 void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs )
332 {
333     delete pImp->pInternalArgs;
334     pImp->pInternalArgs = new SfxAllItemSet( rArgs );
335 }
336 
GetInternalArgs_Impl() const337 const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const
338 {
339     return pImp->pInternalArgs;
340 }
341 
342 //--------------------------------------------------------------------
343 
344 
Record(const uno::Sequence<beans::PropertyValue> & rArgs)345 void SfxRequest_Impl::Record
346 (
347     const uno::Sequence < beans::PropertyValue >& rArgs    // aktuelle Parameter
348 )
349 
350 /*  [Beschreibung]
351 
352     Interne Hilfsmethode zum erzeugen einer <SfxMacroStatement>-Instanz,
353     welche den bereits ausgef"uhrten SfxRequest wiederholbar beschreibt.
354 
355     Die erzeugte Instanz, auf die ein Pointer zur"uckgeliefert wird
356     geht in das Eigentum des Aufrufers "uber.
357 */
358 
359 {
360     String aCommand = String::CreateFromAscii(".uno:");
361     aCommand.AppendAscii( pSlot->GetUnoName() );
362     ::rtl::OUString aCmd( aCommand );
363     if(xRecorder.is())
364     {
365         uno::Reference< container::XIndexReplace > xReplace( xRecorder, uno::UNO_QUERY );
366         if ( xReplace.is() && aCmd.compareToAscii(".uno:InsertText") == COMPARE_EQUAL )
367         {
368             sal_Int32 nCount = xReplace->getCount();
369             if ( nCount )
370             {
371                 frame::DispatchStatement aStatement;
372                 uno::Any aElement = xReplace->getByIndex(nCount-1);
373                 if ( (aElement >>= aStatement) && aStatement.aCommand == aCmd )
374                 {
375                     ::rtl::OUString aStr;
376                     ::rtl::OUString aNew;
377                     aStatement.aArgs[0].Value >>= aStr;
378                     rArgs[0].Value >>= aNew;
379                     aStr += aNew;
380                     aStatement.aArgs[0].Value <<= aStr;
381                     aElement <<= aStatement;
382                     xReplace->replaceByIndex( nCount-1, aElement );
383                     return;
384                 }
385             }
386         }
387 
388         com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xFactory(
389                 ::comphelper::getProcessServiceFactory(),
390                 com::sun::star::uno::UNO_QUERY);
391 
392         com::sun::star::uno::Reference< com::sun::star::util::XURLTransformer > xTransform(
393                 xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")),
394                 com::sun::star::uno::UNO_QUERY);
395 
396         com::sun::star::util::URL aURL;
397         aURL.Complete = aCmd;
398         xTransform->parseStrict(aURL);
399 
400         if (bDone)
401             xRecorder->recordDispatch(aURL,rArgs);
402         else
403             xRecorder->recordDispatchAsComment(aURL,rArgs);
404     }
405 }
406 
407 //--------------------------------------------------------------------
408 
Record_Impl(SfxShell & rSh,const SfxSlot & rSlot,com::sun::star::uno::Reference<com::sun::star::frame::XDispatchRecorder> xRecorder,SfxViewFrame * pViewFrame)409 void SfxRequest::Record_Impl
410 (
411     SfxShell& rSh,    // die <SfxShell>, die den Request ausgef"uhrt hat
412     const SfxSlot&  rSlot,  // der <SfxSlot>, der den Request ausgef"uhrt hat
413     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder,  // der Recorder, mit dem aufgezeichnet wird
414     SfxViewFrame* pViewFrame
415 )
416 
417 /*  [Beschreibung]
418 
419     Diese interne Methode markiert den SfxRequest als in dem angegebenen
420     SfxMakro aufzuzeichnen.
421 
422     Pointer auf die Parameter werden in Done() wieder verwendet, m"usseb
423     dann also noch leben.
424 */
425 
426 {
427     DBG_MEMTEST();
428     pImp->pShell = &rSh;
429     pImp->pSlot = &rSlot;
430     pImp->xRecorder = xRecorder;
431     pImp->aTarget = rSh.GetName();
432     pImp->pViewFrame = pViewFrame;
433 }
434 
435 //--------------------------------------------------------------------
436 
SetArgs(const SfxAllItemSet & rArgs)437 void SfxRequest::SetArgs( const SfxAllItemSet& rArgs )
438 {
439     delete pArgs;
440     pArgs = new SfxAllItemSet(rArgs);
441     pImp->SetPool( pArgs->GetPool() );
442 }
443 
444 //--------------------------------------------------------------------
445 
AppendItem(const SfxPoolItem & rItem)446 void SfxRequest::AppendItem(const SfxPoolItem &rItem)
447 {
448     if(!pArgs)
449         pArgs = new SfxAllItemSet(*pImp->pPool);
450     pArgs->Put(rItem, rItem.Which());
451 }
452 
453 //--------------------------------------------------------------------
454 
RemoveItem(sal_uInt16 nID)455 void SfxRequest::RemoveItem( sal_uInt16 nID )
456 {
457     if (pArgs)
458     {
459         pArgs->ClearItem(nID);
460         if ( !pArgs->Count() )
461             DELETEZ(pArgs);
462     }
463 }
464 
465 //--------------------------------------------------------------------
466 
GetArg(sal_uInt16 nSlotId,bool bDeep,TypeId aType) const467 const SfxPoolItem* SfxRequest::GetArg
468 (
469     sal_uInt16          nSlotId,    // Slot-Id oder Which-Id des Parameters
470     bool        bDeep,      // false: nicht in Parent-ItemSets suchen
471     TypeId          aType       // != 0:  RTTI Pruefung mit Assertion
472 )   const
473 {
474     return GetItem( pArgs, nSlotId, bDeep, aType );
475 }
476 
477 
478 //--------------------------------------------------------------------
GetItem(const SfxItemSet * pArgs,sal_uInt16 nSlotId,bool bDeep,TypeId aType)479 const SfxPoolItem* SfxRequest::GetItem
480 (
481     const SfxItemSet* pArgs,
482     sal_uInt16          nSlotId,    // Slot-Id oder Which-Id des Parameters
483     bool            bDeep,      // false: nicht in Parent-ItemSets suchen
484     TypeId          aType       // != 0:  RTTI Pruefung mit Assertion
485 )
486 
487 /*  [Beschreibung]
488 
489     Mit dieser Methode wird der Zugriff auf einzelne Parameter im
490     SfxRequest wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
491     (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
492     wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
493     eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
494     angegebenen Klasse ist.
495 
496 
497     [Beispiel]
498 
499     void MyShell::Execute( SfxRequest &rReq )
500     {
501         switch ( rReq.GetSlot() )
502         {
503             case SID_MY:
504             {
505                 ...
506                 // ein Beispiel ohne Verwendung des Makros
507                 const SfxInt32Item *pPosItem = (const SfxUInt32Item*)
508                     rReq.GetArg( SID_POS, sal_False, TYPE(SfxInt32Item) );
509                 sal_uInt16 nPos = pPosItem ? pPosItem->GetValue() : 0;
510 
511                 // ein Beispiel mit Verwendung des Makros
512                 SFX_REQUEST_ARG(rReq, pSizeItem, SfxInt32Item, SID_SIZE, sal_False);
513                 sal_uInt16 nSize = pSizeItem ? pPosItem->GetValue() : 0;
514 
515                 ...
516             }
517 
518             ...
519         }
520     }
521 */
522 
523 {
524     if ( pArgs )
525     {
526         // ggf. in Which-Id umrechnen
527         sal_uInt16 nWhich = pArgs->GetPool()->GetWhich(nSlotId);
528 
529         // ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
530         const SfxPoolItem *pItem = 0;
531         if ( ( bDeep ? SFX_ITEM_AVAILABLE : SFX_ITEM_SET )
532              <= pArgs->GetItemState( nWhich, bDeep, &pItem ) )
533         {
534             // stimmt der Typ "uberein?
535             if ( !pItem || pItem->IsA(aType) )
536                 return pItem;
537 
538             // Item da aber falsch => Programmierfehler
539             DBG_ERROR(  "invalid argument type" );
540         }
541     }
542 
543     // keine Parameter, nicht gefunden oder falschen Typ gefunden
544     return 0;
545 }
546 
547 //--------------------------------------------------------------------
548 
SetReturnValue(const SfxPoolItem & rItem)549 void SfxRequest::SetReturnValue(const SfxPoolItem &rItem)
550 {
551     DBG_ASSERT(!pImp->pRetVal, "Returnwert mehrfach setzen?");
552     if(pImp->pRetVal)
553         delete pImp->pRetVal;
554     pImp->pRetVal = rItem.Clone();
555 }
556 
557 //--------------------------------------------------------------------
558 
GetReturnValue() const559 const SfxPoolItem* SfxRequest::GetReturnValue() const
560 {
561     return pImp->pRetVal;
562 }
563 
564 //--------------------------------------------------------------------
565 
Done(const SfxItemSet & rSet,bool bKeep)566 void SfxRequest::Done
567 (
568     const SfxItemSet&   rSet,   /*  von der Applikation mitgeteilte Parameter,
569                                     die z.B. in einem Dialog vom Benuter
570                                     erfragt wurden, ggf. 0 falls keine
571                                     Parameter gesetzt wurden */
572 
573     bool            bKeep   /*  true (default)
574                                     'rSet' wird gepeichert und ist "uber
575                                     GetArgs() abfragbar
576 
577                                     false
578                                     'rSet' wird nicht kopiert (schneller) */
579 )
580 
581 /*  [Beschreibung]
582 
583     Diese Methode mu\s in der <Execute-Methode> des <SfxSlot>s gerufen
584     werden, der den SfxRequest ausgef"uhrt hat, wenn die Ausf"uhrung
585     tats"achlich stattgefunden hat. Wird 'Done()' nicht gerufen, gilt
586     der SfxRequest als abgebrochen.
587 
588     Etwaige Returnwerte werden nur durchgereicht, wenn 'Done()' gerufen
589     wurde. Ebenso werden beim Aufzeichnen von Makros nur echte
590     Statements erzeugt, wenn 'Done()' gerufen wurde; f"ur SfxRequests,
591     die nicht derart gekennzeichnet wurden, wird anstelle dessen eine
592     auf die abgebrochene Funktion hinweisende Bemerkung ('rem') eingf"ugt.
593 
594 
595     [Anmerkung]
596 
597     'Done()' wird z.B. nicht gerufen, wenn ein durch die Funktion gestarteter
598     Dialog vom Benutzer abgebrochen wurde oder das Ausf"uhren aufgrund
599     eines falschen Kontextes (ohne Verwendung separater <SfxShell>s)
600     nicht durchgef"uhrt werden konnte. 'Done()' mu\s sehr wohl gerufen
601     werden, wenn das Ausf"uhren der Funktion zu einem regul"aren Fehler
602     f"uhrte (z.B. Datei konnte nicht ge"offnet werden).
603 */
604 
605 {
606     Done_Impl( &rSet );
607 
608     // ggf. Items merken, damit StarDraw sie abfragen kann
609     if ( bKeep )
610     {
611         if ( !pArgs )
612         {
613             pArgs = new SfxAllItemSet( rSet );
614             pImp->SetPool( pArgs->GetPool() );
615         }
616         else
617         {
618             SfxItemIter aIter(rSet);
619             const SfxPoolItem* pItem = aIter.FirstItem();
620             while(pItem)
621             {
622                 if(!IsInvalidItem(pItem))
623                     pArgs->Put(*pItem,pItem->Which());
624                 pItem = aIter.NextItem();
625             }
626         }
627     }
628 }
629 
630 //--------------------------------------------------------------------
631 
632 
Done(sal_Bool bRelease)633 void SfxRequest::Done( sal_Bool bRelease )
634 //  [<SfxRequest::Done(SfxItemSet&)>]
635 {
636     Done_Impl( pArgs );
637     if( bRelease )
638         DELETEZ( pArgs );
639 }
640 
641 //--------------------------------------------------------------------
642 
ForgetAllArgs()643 void SfxRequest::ForgetAllArgs()
644 {
645     DELETEZ( pArgs );
646     DELETEZ( pImp->pInternalArgs );
647 }
648 
649 //--------------------------------------------------------------------
650 
IsCancelled() const651 sal_Bool SfxRequest::IsCancelled() const
652 {
653     return pImp->bCancelled;
654 }
655 
656 //--------------------------------------------------------------------
657 
Cancel()658 void SfxRequest::Cancel()
659 
660 /*  [Beschreibung]
661 
662     Markiert diesen Request als nicht mehr auszufuehren. Wird z.B. gerufen,
663     wenn das Ziel (genauer dessen Pool) stirbt.
664 */
665 
666 {
667     pImp->bCancelled = sal_True;
668     pImp->SetPool( 0 );
669     DELETEZ( pArgs );
670 }
671 
672 //--------------------------------------------------------------------
673 
674 
Ignore()675 void SfxRequest::Ignore()
676 
677 /*  [Beschreibung]
678 
679     Wird diese Methode anstelle von <SfxRequest::Done()> gerufen, dann
680     wird dieser Request nicht recorded.
681 
682 
683     [Bespiel]
684 
685     Das Selektieren von Tools im StarDraw soll nicht aufgezeichnet werden,
686     dieselben Slots sollen aber zum erzeugen der von den Tools zu
687     erzeugenden Objekte verwendet werde. Also kann nicht NoRecord
688     angegeben werden, dennoch soll u.U. nicht aufgezeichnet werden.
689 */
690 
691 {
692     // als tats"achlich ausgef"uhrt markieren
693     pImp->bIgnored = sal_True;
694 }
695 
696 //--------------------------------------------------------------------
697 
Done_Impl(const SfxItemSet * pSet)698 void SfxRequest::Done_Impl
699 (
700     const SfxItemSet*   pSet    /*  von der Applikation mitgeteilte Parameter,
701                                     die z.B. in einem Dialog vom Benuter
702                                     erfragt wurden, ggf. 0 falls keine
703                                     Parameter gesetzt wurden */
704 )
705 
706 /*  [Beschreibung]
707 
708     Interne Methode zum als 'done' markieren des SfxRequest und zum Auswerten
709     der Parameter in 'pSet' falls aufgezeichnet wird.
710 */
711 
712 {
713     // als tats"achlich ausgef"uhrt markieren
714     pImp->bDone = sal_True;
715 
716     // nicht Recorden
717     if ( !pImp->xRecorder.is() )
718         return;
719 
720     // wurde ein anderer Slot ausgef"uhrt als angefordert (Delegation)
721     if ( nSlot != pImp->pSlot->GetSlotId() )
722     {
723         // Slot neu suchen
724         pImp->pSlot = pImp->pShell->GetInterface()->GetSlot(nSlot);
725         DBG_ASSERT( pImp->pSlot, "delegated SlotId not found" );
726         if ( !pImp->pSlot ) // Hosentr"ger und G"urtel
727             return;
728     }
729 
730     // record-f"ahig?
731     // neues Recorden verwendet UnoName!
732     if ( !pImp->pSlot->pUnoName )
733     {
734         ByteString aStr( "Recording not exported slot: ");
735         aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
736         DBG_ERROR( aStr.GetBuffer() );
737     }
738 
739     if ( !pImp->pSlot->pUnoName ) // Hosentr"ger und G"urtel
740         return;
741 
742     // "ofters ben"otigte Werte
743     SfxItemPool &rPool = pImp->pShell->GetPool();
744 
745     // Property-Slot?
746     if ( !pImp->pSlot->IsMode(SFX_SLOT_METHOD) )
747     {
748         // des Property als SfxPoolItem besorgen
749         const SfxPoolItem *pItem;
750         sal_uInt16 nWhich = rPool.GetWhich(pImp->pSlot->GetSlotId());
751         SfxItemState eState = pSet ? pSet->GetItemState( nWhich, sal_False, &pItem ) : SFX_ITEM_UNKNOWN;
752 #ifdef DBG_UTIL
753         if ( SFX_ITEM_SET != eState )
754         {
755             ByteString aStr( "Recording property not available: ");
756             aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
757             DBG_ERROR( aStr.GetBuffer() );
758         }
759 #endif
760         uno::Sequence < beans::PropertyValue > aSeq;
761         if ( eState == SFX_ITEM_SET )
762             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
763         pImp->Record( aSeq );
764     }
765 
766     // alles in ein einziges Statement aufzeichnen?
767     else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERSET) )
768     {
769         uno::Sequence < beans::PropertyValue > aSeq;
770         if ( pSet )
771             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
772         pImp->Record( aSeq );
773     }
774 
775     // jedes Item als einzelnes Statement recorden
776     else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERITEM) )
777     {
778         if ( pSet )
779         {
780             // "uber die Items iterieren
781             SfxItemIter aIter(*pSet);
782             for ( const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem() )
783             {
784                 // die Slot-Id f"ur das einzelne Item ermitteln
785                 sal_uInt16 nSlotId = rPool.GetSlotId( pItem->Which() );
786                 if ( nSlotId == nSlot )
787                 {
788                     // mit Hosentr"ager und G"urtel reparieren des falschen Flags
789                     DBG_ERROR( "recursion RecordPerItem - use RecordPerSet!" );
790                     SfxSlot *pSlot = (SfxSlot*) pImp->pSlot;
791                     pSlot->nFlags &= ~((sal_uIntPtr)SFX_SLOT_RECORDPERITEM);
792                     pSlot->nFlags &=  SFX_SLOT_RECORDPERSET;
793                 }
794 
795                 // einen Sub-Request recorden
796                 SfxRequest aReq( pImp->pViewFrame, nSlotId );
797                 if ( aReq.pImp->pSlot )
798                     aReq.AppendItem( *pItem );
799                 aReq.Done();
800             }
801         }
802         else
803         {
804             HACK(hierueber nochmal nachdenken)
805             pImp->Record( uno::Sequence < beans::PropertyValue >() );
806         }
807     }
808 }
809 
810 //--------------------------------------------------------------------
811 
IsDone() const812 sal_Bool SfxRequest::IsDone() const
813 
814 /*  [Beschreibung]
815 
816     Mit dieser Methode kann abgefragt werden, ob der SfxRequest tats"achlich
817     ausgef"uhrt wurde oder nicht. Wurde ein SfxRequest nicht ausgef"uhrt,
818     liegt dies z.B. daran, da\s der Benutzer abgebrochen hat oder
819     der Kontext f"ur diesen Request falsch war, dieses aber nicht "uber
820     eine separate <SfxShell> realisiert wurde.
821 
822     SfxRequest-Instanzen, die hier sal_False liefern, werden nicht recorded.
823 
824 
825     [Querverweise]
826 
827     <SfxRequest::Done(const SfxItemSet&)>
828     <SfxRequest::Done()>
829 */
830 
831 {
832     return pImp->bDone;
833 }
834 
835 //--------------------------------------------------------------------
836 
GetRecordingMacro()837 SfxMacro* SfxRequest::GetRecordingMacro()
838 
839 /*  [Beschreibung]
840 
841     Mit dieser Methode kann abgefragt werden, ob und in welchem <SfxMacro>
842     die SfxRequests gerade aufgezeichnet werden.
843 */
844 
845 {
846     return NULL;
847 }
848 
849 //--------------------------------------------------------------------
850 
GetMacroRecorder(SfxViewFrame * pView)851 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxRequest::GetMacroRecorder( SfxViewFrame* pView )
852 
853 /*  [Beschreibung]
854 
855     Hier wird versucht einen Recorder fuer dispatch() Aufrufe vom Frame zu bekommen.
856     Dieser ist dort per Property an einem Supplier verfuegbar - aber nur dann, wenn
857     recording angeschaltet wurde.
858     (Siehe auch SfxViewFrame::MiscExec_Impl() und SID_RECORDING)
859 */
860 
861 {
862     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
863 
864     com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
865         (pView ? pView : SfxViewFrame::Current())->GetFrame().GetFrameInterface(),
866         com::sun::star::uno::UNO_QUERY);
867 
868     if(xSet.is())
869     {
870         com::sun::star::uno::Any aProp = xSet->getPropertyValue(rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
871         com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
872         aProp >>= xSupplier;
873         if(xSupplier.is())
874             xRecorder = xSupplier->getDispatchRecorder();
875     }
876 
877     return xRecorder;
878 }
879 
HasMacroRecorder(SfxViewFrame * pView)880 sal_Bool SfxRequest::HasMacroRecorder( SfxViewFrame* pView )
881 {
882     return GetMacroRecorder( pView ).is();
883 }
884 
885 
886 //--------------------------------------------------------------------
887 
IsAPI() const888 sal_Bool SfxRequest::IsAPI() const
889 
890 /*  [Beschreibung]
891 
892     Liefert sal_True, wenn dieser SfxRequest von einer API (z.B. BASIC)
893     erzeugt wurde, sonst sal_False.
894 */
895 
896 {
897     return SFX_CALLMODE_API == ( SFX_CALLMODE_API & pImp->nCallMode );
898 }
899 
900 //--------------------------------------------------------------------
901 
902 
IsRecording() const903 bool SfxRequest::IsRecording() const
904 
905 /*  [Beschreibung]
906 
907     Liefert sal_True, wenn dieser SfxRequest recorded werden soll, d.h.
908     1. zu Zeit ein Makro aufgezeichnet wird
909     2. dieser Request "uberhaupt aufgezeichnet wird
910     3. der Request nicht von reiner API (z.B. BASIC) ausgeht,
911     sonst sal_False.
912 */
913 
914 {
915     return ( AllowsRecording() && GetMacroRecorder().is() );
916 }
917 
918 //--------------------------------------------------------------------
SetModifier(sal_uInt16 nModi)919 void SfxRequest::SetModifier( sal_uInt16 nModi )
920 {
921     pImp->nModifier = nModi;
922 }
923 
924 //--------------------------------------------------------------------
GetModifier() const925 sal_uInt16 SfxRequest::GetModifier() const
926 {
927     return pImp->nModifier;
928 }
929 
930 //--------------------------------------------------------------------
931 
SetTarget(const String & rTarget)932 void SfxRequest::SetTarget( const String &rTarget )
933 
934 /*  [Beschreibung]
935 
936     Mit dieser Methode kann das zu recordende Zielobjekt umgesetzt werden.
937 
938 
939     [Beispiel]
940 
941     Die BASIC-Methode 'Open' wird zwar von der Shell 'Application' ausgef"uhrt,
942     aber am Objekt 'Documents' (global) recorded:
943 
944         rReq.SetTarget( "Documents" );
945 
946     Dies f"uhrt dann zu:
947 
948         Documents.Open( ... )
949 */
950 
951 {
952     pImp->aTarget = rTarget;
953     pImp->bUseTarget = sal_True;
954 }
955 
AllowRecording(sal_Bool bSet)956 void SfxRequest::AllowRecording( sal_Bool bSet )
957 {
958     pImp->bAllowRecording = bSet;
959 }
960 
AllowsRecording() const961 sal_Bool SfxRequest::AllowsRecording() const
962 {
963     sal_Bool bAllow = pImp->bAllowRecording;
964     if( !bAllow )
965         bAllow = ( SFX_CALLMODE_API != ( SFX_CALLMODE_API & pImp->nCallMode ) ) &&
966                  ( SFX_CALLMODE_RECORD == ( SFX_CALLMODE_RECORD & pImp->nCallMode ) );
967     return bAllow;
968 }
969 
ReleaseArgs()970 void SfxRequest::ReleaseArgs()
971 {
972     DELETEZ( pArgs );
973     DELETEZ( pImp->pInternalArgs );
974 }
975