Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / bastyp / progress.cxx
blob9a49a1aa20c4ad2f51256c1e2262aded13284388
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 .
21 #include <sfx2/progress.hxx>
22 #include <com/sun/star/uno/Reference.hxx>
23 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
25 #include <basic/sbx.hxx>
27 #include <svl/eitem.hxx>
28 #include <tools/time.hxx>
30 #include "appdata.hxx"
31 #include <sfx2/request.hxx>
32 #include <sfx2/frame.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <sfx2/viewsh.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <sfx2/app.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include "sfxtypes.hxx"
39 #include <sfx2/docfile.hxx>
40 #include "workwin.hxx"
41 #include "sfx2/sfxresid.hxx"
42 #include "bastyp.hrc"
43 #include <sfx2/msg.hxx>
45 #include <time.h>
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::frame;
49 using namespace ::com::sun::star::task;
51 struct SfxProgress_Impl
53 Reference < XStatusIndicator > xStatusInd;
54 String aText, aStateText;
55 sal_uIntPtr nMax;
56 clock_t nCreate;
57 clock_t nNextReschedule;
58 sal_Bool bLocked, bAllDocs;
59 sal_Bool bWaitMode;
60 sal_Bool bAllowRescheduling;
61 sal_Bool bRunning;
63 SfxProgress* pActiveProgress;
64 SfxObjectShellRef xObjSh;
65 SfxWorkWindow* pWorkWin;
66 SfxViewFrame* pView;
68 SfxProgress_Impl( const String& );
69 void Enable_Impl( sal_Bool );
73 //========================================================================
75 #include "sfxslots.hxx"
77 //========================================================================
78 extern sal_uInt32 Get10ThSec();
80 // -----------------------------------------------------------------------
82 void SfxProgress_Impl::Enable_Impl( sal_Bool bEnable )
84 SfxObjectShell* pDoc = bAllDocs ? NULL : (SfxObjectShell*) xObjSh;
85 SfxViewFrame *pFrame= SfxViewFrame::GetFirst(pDoc);
86 while ( pFrame )
88 pFrame->Enable(bEnable);
89 pFrame->GetDispatcher()->Lock( !bEnable );
90 pFrame = SfxViewFrame::GetNext(*pFrame, pDoc);
93 if ( pView )
95 pView->Enable( bEnable );
96 pView->GetDispatcher()->Lock( !bEnable );
99 if ( !pDoc )
100 SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable );
103 // -----------------------------------------------------------------------
105 SfxProgress_Impl::SfxProgress_Impl( const String &/*rTitle*/ )
106 : pActiveProgress( 0 )
110 // -----------------------------------------------------------------------
112 SfxProgress::SfxProgress
114 SfxObjectShell* pObjSh, /* The action is performed on the
115 SfxObjectShell which can be NULL.
116 When it is then the application will be
117 used */
119 const String& rText, /* Text, which appears before the Statusmonitor
120 in the status line */
122 sal_uIntPtr nRange, /* Max value for range */
124 sal_Bool bAll, /* Disable all documents or only the document of the ViewFram */
125 sal_Bool bWait /* Activate the wait-Pointer initially (TRUE) */
128 /* [Description]
130 The constructor of the class SfxProgress switches the SfxObjectShell
131 passed as parameter and SfxViewFrames which display this document in
132 a progress mode. Ie as long as one of those SfxViewFrame instances is
133 active the associated SfxDispatcher and associated Window is disabled.
134 A progress-bar will be displayed in the status bar,
137 : pImp( new SfxProgress_Impl( rText ) ),
138 nVal(0),
139 bSuspended(sal_True)
141 pImp->bRunning = sal_True;
142 pImp->bAllowRescheduling = Application::IsInExecute();
144 pImp->xObjSh = pObjSh;
145 pImp->aText = rText;
146 pImp->nMax = nRange;
147 pImp->bLocked = sal_False;
148 pImp->bWaitMode = bWait;
149 pImp->nCreate = Get10ThSec();
150 pImp->nNextReschedule = pImp->nCreate;
151 DBG( DbgOutf( "SfxProgress: created for '%s' at %luds",
152 rText.GetBuffer(), pImp->nCreate ) );
153 pImp->bAllDocs = bAll;
154 pImp->pWorkWin = 0;
155 pImp->pView = 0;
157 pImp->pActiveProgress = GetActiveProgress( pObjSh );
158 if ( pObjSh )
159 pObjSh->SetProgress_Impl(this);
160 else if( !pImp->pActiveProgress )
161 SFX_APP()->SetProgress_Impl(this);
162 Resume();
165 // -----------------------------------------------------------------------
167 SfxProgress::~SfxProgress()
169 /* [Description]
171 The destructor of the class SfxProgress restores the old status,
172 the documents are released again and the status bar shows the items again.
176 Stop();
177 if ( pImp->xStatusInd.is() )
178 pImp->xStatusInd->end();
179 delete pImp;
182 // -----------------------------------------------------------------------
184 void SfxProgress::Stop()
186 /* [Description]
188 Early Exit of <SfxProgress>.
192 if( pImp->pActiveProgress )
194 if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this )
195 pImp->xObjSh->SetProgress_Impl(0);
196 return;
199 if ( !pImp->bRunning )
200 return;
201 pImp->bRunning = sal_False;
202 DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
204 Suspend();
205 if ( pImp->xObjSh.Is() )
206 pImp->xObjSh->SetProgress_Impl(0);
207 else
208 SFX_APP()->SetProgress_Impl(0);
209 if ( pImp->bLocked )
210 pImp->Enable_Impl(sal_True);
213 // -----------------------------------------------------------------------
215 void SfxProgress::SetText( const OUString& /* new Text */)
217 /* [Description]
219 Changes the text that appears to the left next to progress bar.
223 if( pImp->pActiveProgress ) return;
224 if ( pImp->xStatusInd.is() )
226 pImp->xStatusInd->reset();
227 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
231 // -----------------------------------------------------------------------
233 // Required in App data
234 static sal_uIntPtr nLastTime = 0;
236 long TimeOut_Impl( void*, void* pArgV )
238 Timer *pArg = (Timer*)pArgV;
239 if( Time::GetSystemTicks() - nLastTime > 3000 )
241 nLastTime = 0;
242 delete pArg;
244 else pArg->Start();
245 return 0;
248 // -----------------------------------------------------------------------
250 sal_Bool SfxProgress::SetStateText
252 sal_uLong nNewVal, /* New value for the progress-bar */
253 const String& rNewVal, /* Status as Text */
254 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
258 pImp->aStateText = rNewVal;
259 return SetState( nNewVal, nNewRange );
262 // -----------------------------------------------------------------------
264 sal_Bool SfxProgress::SetState
266 sal_uLong nNewVal, /* new value for the progress bar */
268 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
270 /* [Description]
272 Setting the current status, after a time delay Reschedule is called.
274 [Return value]
276 sal_Bool TRUE
277 Proceed with the action
279 FALSE
280 Cancel action
284 if( pImp->pActiveProgress ) return sal_True;
286 nVal = nNewVal;
288 // new Range?
289 if ( nNewRange && nNewRange != pImp->nMax )
291 DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu",
292 pImp->nMax, nNewRange ) );
293 pImp->nMax = nNewRange;
296 if ( !pImp->xStatusInd.is() )
298 // get the active ViewFrame of the document this progress is working on
299 // if it doesn't work on a document, take the current ViewFrame
300 SfxObjectShell* pObjSh = pImp->xObjSh;
301 pImp->pView = SfxViewFrame::Current();
302 DBG_ASSERT( pImp->pView || pObjSh, "Can't make progress bar!");
303 if ( pObjSh && ( !pImp->pView || pObjSh != pImp->pView->GetObjectShell() ) )
305 // current document does not belong to current ViewFrame; take it's first visible ViewFrame
306 SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
307 if ( pDocView )
308 pImp->pView = pDocView;
309 else
311 // don't show status indicator for hidden documents (only valid while loading)
312 SfxMedium* pMedium = pObjSh->GetMedium();
313 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False );
314 if ( !pHiddenItem || !pHiddenItem->GetValue() )
317 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
318 Reference< XStatusIndicator > xInd;
319 if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
320 pImp->xStatusInd = xInd;
325 else if ( pImp->pView )
327 pImp->pWorkWin = SFX_APP()->GetWorkWindow_Impl( pImp->pView );
328 if ( pImp->pWorkWin )
329 pImp->xStatusInd = pImp->pWorkWin->GetStatusIndicator();
332 if ( pImp->xStatusInd.is() )
334 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
335 pImp->pView = NULL;
339 if ( pImp->xStatusInd.is() )
341 pImp->xStatusInd->setValue( nNewVal );
344 return sal_True;
347 // -----------------------------------------------------------------------
349 void SfxProgress::Resume()
351 /* [Description]
353 Resumed the status of the display after an interrupt.
355 [Cross-reference]
357 <SfxProgress::Suspend()>
361 if( pImp->pActiveProgress ) return;
362 if ( bSuspended )
364 DBG( DbgOutf( "SfxProgress: resumed" ) );
365 if ( pImp->xStatusInd.is() )
367 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
368 pImp->xStatusInd->setValue( nVal );
371 if ( pImp->bWaitMode )
373 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
375 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
376 pFrame;
377 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
378 pFrame->GetWindow().EnterWait();
382 if ( pImp->xObjSh )
384 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
385 if ( pFrame )
386 pFrame->GetBindings().ENTERREGISTRATIONS();
389 bSuspended = sal_False;
393 // -----------------------------------------------------------------------
395 void SfxProgress::Suspend()
397 /* [Description]
399 Interrupts the status of the display
401 [Cross-reference]
403 <SfxProgress::Resume()>
407 if( pImp->pActiveProgress ) return;
408 if ( !bSuspended )
410 DBG( DbgOutf( "SfxProgress: suspended" ) );
411 bSuspended = sal_True;
413 if ( pImp->xStatusInd.is() )
415 pImp->xStatusInd->reset();
418 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
420 for ( SfxViewFrame *pFrame =
421 SfxViewFrame::GetFirst(pImp->xObjSh);
422 pFrame;
423 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
424 pFrame->GetWindow().LeaveWait();
426 if ( pImp->xObjSh.Is() )
428 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
429 if ( pFrame )
430 pFrame->GetBindings().LEAVEREGISTRATIONS();
435 // -----------------------------------------------------------------------
437 void SfxProgress::UnLock()
439 if( pImp->pActiveProgress ) return;
440 if ( !pImp->bLocked )
441 return;
443 DBG( DbgOutf( "SfxProgress: unlocked" ) );
444 pImp->bLocked = sal_False;
445 pImp->Enable_Impl(sal_True);
448 // -----------------------------------------------------------------------
450 void SfxProgress::Reschedule()
452 /* [Description]
454 Reschedule, callable from the outside
458 SFX_STACK(SfxProgress::Reschedule);
460 if( pImp->pActiveProgress ) return;
461 SfxApplication* pApp = SFX_APP();
462 if ( pImp->bLocked && 0 == pApp->Get_Impl()->nRescheduleLocks )
464 SfxAppData_Impl *pAppData = pApp->Get_Impl();
465 ++pAppData->nInReschedule;
466 Application::Reschedule();
467 --pAppData->nInReschedule;
471 // -----------------------------------------------------------------------
473 SfxProgress* SfxProgress::GetActiveProgress
475 SfxObjectShell* pDocSh /* the <SfxObjectShell>, which should be
476 queried after a current <SfxProgress>,
477 or 0 if an current SfxProgress for the
478 entire application should be obtained.
479 The pointer only needs at the time of
480 the call to be valid.
484 /* [Description]
486 This method is used to check whether and which <SfxProgress> is currently
487 active for a specific instance of SfxObjectShell or even an entire
488 application. This can for example be used to check for Time-Out-Events, etc.
490 Instead of a pointer to the SfxProgress the SfxObjectShell may be
491 pointed at the SfxProgress of the application, with the query
492 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
493 SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
494 the application or a 0-pointer.
496 [Note]
498 If no SfxProgress is running in the application and also not at the
499 specified SfxObjectShell, then this method will always return 0,
500 even if one SfxProgress runs on another SfxObjectShell.
502 [Cross-reference]
504 <SfxApplication::GetProgress()const>
505 <SfxObjectShell::GetProgress()const>
509 if ( !SfxApplication::Get() )
510 return 0;
512 SfxProgress *pProgress = 0;
513 if ( pDocSh )
514 pProgress = pDocSh->GetProgress();
515 if ( !pProgress )
516 pProgress = SFX_APP()->GetProgress();
517 return pProgress;
520 // -----------------------------------------------------------------------
522 void SfxProgress::EnterLock()
524 SFX_APP()->Get_Impl()->nRescheduleLocks++;
527 // -----------------------------------------------------------------------
529 void SfxProgress::LeaveLock()
531 SfxAppData_Impl *pImp = SFX_APP()->Get_Impl();
532 DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
533 pImp->nRescheduleLocks--;
536 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */