Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / bastyp / progress.cxx
blob1593ef3992f05c844d085efc42aafc7ef5c331da
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>
44 #include "sfxslots.hxx"
45 #include "sfxbasecontroller_internal.hxx"
46 #include <time.h>
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::frame;
50 using namespace ::com::sun::star::task;
52 struct SfxProgress_Impl
54 Reference < XStatusIndicator > xStatusInd;
55 OUString aText, aStateText;
56 sal_uIntPtr nMax;
57 clock_t nCreate;
58 clock_t nNextReschedule;
59 bool bLocked, bAllDocs;
60 bool bWaitMode;
61 bool bAllowRescheduling;
62 bool bRunning;
64 SfxProgress* pActiveProgress;
65 SfxObjectShellRef xObjSh;
66 SfxWorkWindow* pWorkWin;
67 SfxViewFrame* pView;
69 SfxProgress_Impl( const OUString& );
70 void Enable_Impl( bool );
76 void SfxProgress_Impl::Enable_Impl( bool bEnable )
78 SfxObjectShell* pDoc = bAllDocs ? NULL : (SfxObjectShell*) xObjSh;
79 SfxViewFrame *pFrame= SfxViewFrame::GetFirst(pDoc);
80 while ( pFrame )
82 pFrame->Enable(bEnable);
83 pFrame->GetDispatcher()->Lock( !bEnable );
84 pFrame = SfxViewFrame::GetNext(*pFrame, pDoc);
87 if ( pView )
89 pView->Enable( bEnable );
90 pView->GetDispatcher()->Lock( !bEnable );
93 if ( !pDoc )
94 SfxGetpApp()->GetAppDispatcher_Impl()->Lock( !bEnable );
99 SfxProgress_Impl::SfxProgress_Impl( const OUString &/*rTitle*/ )
100 : nMax(0)
101 , nCreate(0)
102 , nNextReschedule(0)
103 , bLocked(false)
104 , bAllDocs(false)
105 , bWaitMode(false)
106 , bAllowRescheduling(false)
107 , bRunning(false)
108 , pActiveProgress(0)
109 , pWorkWin(0)
110 , pView(0)
116 SfxProgress::SfxProgress
118 SfxObjectShell* pObjSh, /* The action is performed on the
119 SfxObjectShell which can be NULL.
120 When it is then the application will be
121 used */
123 const OUString& rText, /* Text, which appears before the Statusmonitor
124 in the status line */
126 sal_uIntPtr nRange, /* Max value for range */
128 bool bAll, /* Disable all documents or only the document of the ViewFram */
129 bool bWait /* Activate the wait-Pointer initially (TRUE) */
132 /* [Description]
134 The constructor of the class SfxProgress switches the SfxObjectShell
135 passed as parameter and SfxViewFrames which display this document in
136 a progress mode. Ie as long as one of those SfxViewFrame instances is
137 active the associated SfxDispatcher and associated Window is disabled.
138 A progress-bar will be displayed in the status bar,
141 : pImp( new SfxProgress_Impl( rText ) ),
142 nVal(0),
143 bSuspended(true)
145 pImp->bRunning = true;
146 pImp->bAllowRescheduling = Application::IsInExecute();
148 pImp->xObjSh = pObjSh;
149 pImp->aText = rText;
150 pImp->nMax = nRange;
151 pImp->bLocked = false;
152 pImp->bWaitMode = bWait;
153 pImp->nCreate = Get10ThSec();
154 pImp->nNextReschedule = pImp->nCreate;
155 SAL_INFO(
156 "sfx.bastyp",
157 "SfxProgress: created for '" << rText << "' at " << pImp->nCreate
158 << "ds");
159 pImp->bAllDocs = bAll;
160 pImp->pWorkWin = 0;
161 pImp->pView = 0;
163 pImp->pActiveProgress = GetActiveProgress( pObjSh );
164 if ( pObjSh )
165 pObjSh->SetProgress_Impl(this);
166 else if( !pImp->pActiveProgress )
167 SfxGetpApp()->SetProgress_Impl(this);
168 Resume();
173 SfxProgress::~SfxProgress()
175 /* [Description]
177 The destructor of the class SfxProgress restores the old status,
178 the documents are released again and the status bar shows the items again.
182 Stop();
183 if ( pImp->xStatusInd.is() )
184 pImp->xStatusInd->end();
185 delete pImp;
190 void SfxProgress::Stop()
192 /* [Description]
194 Early Exit of <SfxProgress>.
198 if( pImp->pActiveProgress )
200 if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this )
201 pImp->xObjSh->SetProgress_Impl(0);
202 return;
205 if ( !pImp->bRunning )
206 return;
207 pImp->bRunning = false;
208 SAL_INFO(
209 "sfx.bastyp", "SfxProgress: destroyed at " << Get10ThSec() << "ds");
211 Suspend();
212 if ( pImp->xObjSh.Is() )
213 pImp->xObjSh->SetProgress_Impl(0);
214 else
215 SfxGetpApp()->SetProgress_Impl(0);
216 if ( pImp->bLocked )
217 pImp->Enable_Impl(true);
220 bool SfxProgress::SetStateText
222 sal_uLong nNewVal, /* New value for the progress-bar */
223 const OUString& rNewVal, /* Status as Text */
224 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
228 pImp->aStateText = rNewVal;
229 return SetState( nNewVal, nNewRange );
232 bool SfxProgress::SetState
234 sal_uLong nNewVal, /* new value for the progress bar */
236 sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
238 /* [Description]
240 Setting the current status, after a time delay Reschedule is called.
242 [Return value]
244 bool TRUE
245 Proceed with the action
247 FALSE
248 Cancel action
252 if( pImp->pActiveProgress ) return true;
254 nVal = nNewVal;
256 // new Range?
257 if ( nNewRange && nNewRange != pImp->nMax )
259 SAL_INFO(
260 "sfx.bastyp",
261 "SfxProgress: range changed from " << pImp->nMax << " to "
262 << nNewRange);
263 pImp->nMax = nNewRange;
266 if ( !pImp->xStatusInd.is() )
268 // get the active ViewFrame of the document this progress is working on
269 // if it doesn't work on a document, take the current ViewFrame
270 SfxObjectShell* pObjSh = pImp->xObjSh;
271 pImp->pView = SfxViewFrame::Current();
272 DBG_ASSERT( pImp->pView || pObjSh, "Can't make progress bar!");
273 if ( pObjSh && ( !pImp->pView || pObjSh != pImp->pView->GetObjectShell() ) )
275 // current document does not belong to current ViewFrame; take it's first visible ViewFrame
276 SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
277 if ( pDocView )
278 pImp->pView = pDocView;
279 else
281 // don't show status indicator for hidden documents (only valid while loading)
282 SfxMedium* pMedium = pObjSh->GetMedium();
283 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, false );
284 if ( !pHiddenItem || !pHiddenItem->GetValue() )
287 SFX_ITEMSET_ARG( pMedium->GetItemSet(), pIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, false );
288 Reference< XStatusIndicator > xInd;
289 if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
290 pImp->xStatusInd = xInd;
295 else if ( pImp->pView )
297 pImp->pWorkWin = SfxGetpApp()->GetWorkWindow_Impl( pImp->pView );
298 if ( pImp->pWorkWin )
299 pImp->xStatusInd = pImp->pWorkWin->GetStatusIndicator();
302 if ( pImp->xStatusInd.is() )
304 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
305 pImp->pView = NULL;
309 if ( pImp->xStatusInd.is() )
311 pImp->xStatusInd->setValue( nNewVal );
314 return true;
319 void SfxProgress::Resume()
321 /* [Description]
323 Resumed the status of the display after an interrupt.
325 [Cross-reference]
327 <SfxProgress::Suspend()>
331 if( pImp->pActiveProgress ) return;
332 if ( bSuspended )
334 SAL_INFO("sfx.bastyp", "SfxProgress: resumed");
335 if ( pImp->xStatusInd.is() )
337 pImp->xStatusInd->start( pImp->aText, pImp->nMax );
338 pImp->xStatusInd->setValue( nVal );
341 if ( pImp->bWaitMode )
343 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
345 for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
346 pFrame;
347 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
348 pFrame->GetWindow().EnterWait();
352 if ( pImp->xObjSh )
354 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
355 if ( pFrame )
356 pFrame->GetBindings().ENTERREGISTRATIONS();
359 bSuspended = false;
365 void SfxProgress::Suspend()
367 /* [Description]
369 Interrupts the status of the display
371 [Cross-reference]
373 <SfxProgress::Resume()>
377 if( pImp->pActiveProgress ) return;
378 if ( !bSuspended )
380 SAL_INFO("sfx.bastyp", "SfxProgress: suspended");
381 bSuspended = true;
383 if ( pImp->xStatusInd.is() )
385 pImp->xStatusInd->reset();
388 if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
390 for ( SfxViewFrame *pFrame =
391 SfxViewFrame::GetFirst(pImp->xObjSh);
392 pFrame;
393 pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
394 pFrame->GetWindow().LeaveWait();
396 if ( pImp->xObjSh.Is() )
398 SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
399 if ( pFrame )
400 pFrame->GetBindings().LEAVEREGISTRATIONS();
407 void SfxProgress::UnLock()
409 if( pImp->pActiveProgress ) return;
410 if ( !pImp->bLocked )
411 return;
413 SAL_INFO("sfx.bastyp", "SfxProgress: unlocked");
414 pImp->bLocked = false;
415 pImp->Enable_Impl(true);
420 void SfxProgress::Reschedule()
422 /* [Description]
424 Reschedule, callable from the outside
428 SFX_STACK(SfxProgress::Reschedule);
430 if( pImp->pActiveProgress ) return;
431 SfxApplication* pApp = SfxGetpApp();
432 if ( pImp->bLocked && 0 == pApp->Get_Impl()->nRescheduleLocks )
434 SfxAppData_Impl *pAppData = pApp->Get_Impl();
435 ++pAppData->nInReschedule;
436 Application::Reschedule();
437 --pAppData->nInReschedule;
443 SfxProgress* SfxProgress::GetActiveProgress
445 SfxObjectShell* pDocSh /* the <SfxObjectShell>, which should be
446 queried after a current <SfxProgress>,
447 or 0 if an current SfxProgress for the
448 entire application should be obtained.
449 The pointer only needs at the time of
450 the call to be valid.
454 /* [Description]
456 This method is used to check whether and which <SfxProgress> is currently
457 active for a specific instance of SfxObjectShell or even an entire
458 application. This can for example be used to check for Time-Out-Events, etc.
460 Instead of a pointer to the SfxProgress the SfxObjectShell may be
461 pointed at the SfxProgress of the application, with the query
462 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
463 SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
464 the application or a 0-pointer.
466 [Note]
468 If no SfxProgress is running in the application and also not at the
469 specified SfxObjectShell, then this method will always return 0,
470 even if one SfxProgress runs on another SfxObjectShell.
472 [Cross-reference]
474 <SfxApplication::GetProgress()const>
475 <SfxObjectShell::GetProgress()const>
479 if ( !SfxApplication::Get() )
480 return 0;
482 SfxProgress *pProgress = 0;
483 if ( pDocSh )
484 pProgress = pDocSh->GetProgress();
485 if ( !pProgress )
486 pProgress = SfxGetpApp()->GetProgress();
487 return pProgress;
492 void SfxProgress::EnterLock()
494 SfxGetpApp()->Get_Impl()->nRescheduleLocks++;
499 void SfxProgress::LeaveLock()
501 SfxAppData_Impl *pImp = SfxGetpApp()->Get_Impl();
502 DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
503 pImp->nRescheduleLocks--;
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */