Branch data Line data Source code
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 : :
21 : : #include <sfx2/progress.hxx>
22 : : #include <com/sun/star/uno/Reference.hxx>
23 : : #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
24 : :
25 : : #include <basic/sbx.hxx>
26 : :
27 : : #include <svl/eitem.hxx>
28 : : #include <tools/time.hxx>
29 : :
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 : :
45 : : #include <time.h>
46 : :
47 : : using namespace ::com::sun::star::uno;
48 : : using namespace ::com::sun::star::frame;
49 : : using namespace ::com::sun::star::task;
50 : :
51 [ + - ][ + - ]: 346 : struct SfxProgress_Impl
[ + - ]
52 : : {
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;
62 : :
63 : : SfxProgress* pActiveProgress;
64 : : SfxObjectShellRef xObjSh;
65 : : SfxWorkWindow* pWorkWin;
66 : : SfxViewFrame* pView;
67 : :
68 : : SfxProgress_Impl( const String& );
69 : : void Enable_Impl( sal_Bool );
70 : :
71 : : };
72 : :
73 : : //========================================================================
74 : :
75 : : #define Progress
76 : : #include "sfxslots.hxx"
77 : :
78 : : //========================================================================
79 : : extern sal_uInt32 Get10ThSec();
80 : :
81 : : // -----------------------------------------------------------------------
82 : :
83 : 0 : void SfxProgress_Impl::Enable_Impl( sal_Bool bEnable )
84 : : {
85 [ # # ]: 0 : SfxObjectShell* pDoc = bAllDocs ? NULL : (SfxObjectShell*) xObjSh;
86 : 0 : SfxViewFrame *pFrame= SfxViewFrame::GetFirst(pDoc);
87 [ # # ]: 0 : while ( pFrame )
88 : : {
89 : 0 : pFrame->Enable(bEnable);
90 : 0 : pFrame->GetDispatcher()->Lock( !bEnable );
91 : 0 : pFrame = SfxViewFrame::GetNext(*pFrame, pDoc);
92 : : }
93 : :
94 [ # # ]: 0 : if ( pView )
95 : : {
96 : 0 : pView->Enable( bEnable );
97 : 0 : pView->GetDispatcher()->Lock( !bEnable );
98 : : }
99 : :
100 [ # # ]: 0 : if ( !pDoc )
101 : 0 : SFX_APP()->GetAppDispatcher_Impl()->Lock( !bEnable );
102 : 0 : }
103 : :
104 : : // -----------------------------------------------------------------------
105 : :
106 : 346 : SfxProgress_Impl::SfxProgress_Impl( const String &/*rTitle*/ )
107 [ + - ][ + - ]: 346 : : pActiveProgress( 0 )
108 : : {
109 : 346 : }
110 : :
111 : : // -----------------------------------------------------------------------
112 : :
113 : 346 : SfxProgress::SfxProgress
114 : : (
115 : : SfxObjectShell* pObjSh, /* The action is performed on the
116 : : SfxObjectShell which can be NULL.
117 : : When it is then the application will be
118 : : used */
119 : :
120 : : const String& rText, /* Text, which appears before the Statusmonitor
121 : : in the status line */
122 : :
123 : : sal_uIntPtr nRange, /* Max value for range */
124 : :
125 : : sal_Bool bAll, /* Disable all documents or only the document of the ViewFram */
126 : : sal_Bool bWait /* Activate the wait-Pointer initially (TRUE) */
127 : : )
128 : :
129 : : /* [Description]
130 : :
131 : : The constructor of the class SfxProgress switches the SfxObjectShell
132 : : passed as parameter and SfxViewFrames which display this document in
133 : : a progress mode. Ie as long as one of those SfxViewFrame instances is
134 : : active the associated SfxDispatcher and associated Window is disabled.
135 : : A progress-bar will be displayed in the status bar,
136 : : */
137 : :
138 [ + - ]: 346 : : pImp( new SfxProgress_Impl( rText ) ),
139 : : nVal(0),
140 : 346 : bSuspended(sal_True)
141 : : {
142 : 346 : pImp->bRunning = sal_True;
143 : 346 : pImp->bAllowRescheduling = Application::IsInExecute();
144 : :
145 : 346 : pImp->xObjSh = pObjSh;
146 : 346 : pImp->aText = rText;
147 : 346 : pImp->nMax = nRange;
148 : 346 : pImp->bLocked = sal_False;
149 : 346 : pImp->bWaitMode = bWait;
150 : 346 : pImp->nCreate = Get10ThSec();
151 : 346 : pImp->nNextReschedule = pImp->nCreate;
152 : : DBG( DbgOutf( "SfxProgress: created for '%s' at %luds",
153 : : rText.GetBuffer(), pImp->nCreate ) );
154 : 346 : pImp->bAllDocs = bAll;
155 : 346 : pImp->pWorkWin = 0;
156 : 346 : pImp->pView = 0;
157 : :
158 : 346 : pImp->pActiveProgress = GetActiveProgress( pObjSh );
159 [ + - ]: 346 : if ( pObjSh )
160 : 346 : pObjSh->SetProgress_Impl(this);
161 [ # # ]: 0 : else if( !pImp->pActiveProgress )
162 : 0 : SFX_APP()->SetProgress_Impl(this);
163 : 346 : Resume();
164 : 346 : }
165 : :
166 : : // -----------------------------------------------------------------------
167 : :
168 : 692 : SfxProgress::~SfxProgress()
169 : :
170 : : /* [Description]
171 : :
172 : : The destructor of the class SfxProgress restores the old status,
173 : : the documents are released again and the status bar shows the items again.
174 : : */
175 : :
176 : : {
177 : 346 : Stop();
178 [ + + ]: 346 : if ( pImp->xStatusInd.is() )
179 : 89 : pImp->xStatusInd->end();
180 [ + - ]: 346 : delete pImp;
181 [ - + ]: 692 : }
182 : :
183 : : // -----------------------------------------------------------------------
184 : :
185 : 541 : void SfxProgress::Stop()
186 : :
187 : : /* [Description]
188 : :
189 : : Early Exit of <SfxProgress>.
190 : : */
191 : :
192 : : {
193 [ - + ]: 541 : if( pImp->pActiveProgress )
194 : : {
195 [ # # ][ # # ]: 0 : if ( pImp->xObjSh.Is() && pImp->xObjSh->GetProgress() == this )
[ # # ]
196 : 0 : pImp->xObjSh->SetProgress_Impl(0);
197 : 0 : return;
198 : : }
199 : :
200 [ + + ]: 541 : if ( !pImp->bRunning )
201 : 195 : return;
202 : 346 : pImp->bRunning = sal_False;
203 : : DBG( DbgOutf( "SfxProgress: destroyed at %luds", Get10ThSec() ) );
204 : :
205 : 346 : Suspend();
206 [ + - ]: 346 : if ( pImp->xObjSh.Is() )
207 : 346 : pImp->xObjSh->SetProgress_Impl(0);
208 : : else
209 : 0 : SFX_APP()->SetProgress_Impl(0);
210 [ - + ]: 346 : if ( pImp->bLocked )
211 : 541 : pImp->Enable_Impl(sal_True);
212 : : }
213 : :
214 : : // -----------------------------------------------------------------------
215 : :
216 : 0 : void SfxProgress::SetText
217 : : (
218 : : const String& /* new Text */
219 : : )
220 : :
221 : : /* [Description]
222 : :
223 : : Changes the text that appears to the left next to progress bar.
224 : : */
225 : :
226 : : {
227 [ # # ]: 0 : if( pImp->pActiveProgress ) return;
228 [ # # ]: 0 : if ( pImp->xStatusInd.is() )
229 : : {
230 : 0 : pImp->xStatusInd->reset();
231 [ # # ]: 0 : pImp->xStatusInd->start( pImp->aText, pImp->nMax );
232 : : }
233 : : }
234 : :
235 : : // -----------------------------------------------------------------------
236 : :
237 : : // Required in App data
238 : : static sal_uIntPtr nLastTime = 0;
239 : :
240 : 0 : long TimeOut_Impl( void*, void* pArgV )
241 : : {
242 : 0 : Timer *pArg = (Timer*)pArgV;
243 [ # # ]: 0 : if( Time::GetSystemTicks() - nLastTime > 3000 )
244 : : {
245 : 0 : nLastTime = 0;
246 [ # # ]: 0 : delete pArg;
247 : : }
248 : 0 : else pArg->Start();
249 : 0 : return 0;
250 : : }
251 : :
252 : : // -----------------------------------------------------------------------
253 : :
254 : 6 : sal_Bool SfxProgress::SetStateText
255 : : (
256 : : sal_uLong nNewVal, /* New value for the progress-bar */
257 : : const String& rNewVal, /* Status as Text */
258 : : sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
259 : : )
260 : :
261 : : {
262 : 6 : pImp->aStateText = rNewVal;
263 : 6 : return SetState( nNewVal, nNewRange );
264 : : }
265 : :
266 : : // -----------------------------------------------------------------------
267 : :
268 : 1701 : sal_Bool SfxProgress::SetState
269 : : (
270 : : sal_uLong nNewVal, /* new value for the progress bar */
271 : :
272 : : sal_uLong nNewRange /* new maximum value, 0 for retaining the old */
273 : : )
274 : : /* [Description]
275 : :
276 : : Setting the current status, after a time delay Reschedule is called.
277 : :
278 : : [Return value]
279 : :
280 : : sal_Bool TRUE
281 : : Proceed with the action
282 : :
283 : : FALSE
284 : : Cancel action
285 : : */
286 : :
287 : : {
288 [ - + ]: 1701 : if( pImp->pActiveProgress ) return sal_True;
289 : :
290 : 1701 : nVal = nNewVal;
291 : :
292 : : // new Range?
293 [ - + ][ # # ]: 1701 : if ( nNewRange && nNewRange != pImp->nMax )
294 : : {
295 : : DBG( DbgOutf( "SfxProgress: range changed from %lu to %lu",
296 : : pImp->nMax, nNewRange ) );
297 : 0 : pImp->nMax = nNewRange;
298 : : }
299 : :
300 [ + + ]: 1701 : if ( !pImp->xStatusInd.is() )
301 : : {
302 : : // get the active ViewFrame of the document this progress is working on
303 : : // if it doesn't work on a document, take the current ViewFrame
304 : 125 : SfxObjectShell* pObjSh = pImp->xObjSh;
305 : 125 : pImp->pView = SfxViewFrame::Current();
306 : : DBG_ASSERT( pImp->pView || pObjSh, "Can't make progress bar!");
307 [ + + ][ + + ]: 125 : if ( pObjSh && ( !pImp->pView || pObjSh != pImp->pView->GetObjectShell() ) )
[ + + ][ + - ]
308 : : {
309 : : // current document does not belong to current ViewFrame; take it's first visible ViewFrame
310 : 82 : SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
311 [ - + ]: 82 : if ( pDocView )
312 : 0 : pImp->pView = pDocView;
313 : : else
314 : : {
315 : : // don't show status indicator for hidden documents (only valid while loading)
316 : 82 : SfxMedium* pMedium = pObjSh->GetMedium();
317 : 82 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False );
318 [ # # ][ + - ]: 82 : if ( !pHiddenItem || !pHiddenItem->GetValue() )
[ - + ]
319 : : {
320 : : {
321 [ + - ][ + - ]: 82 : SFX_ITEMSET_ARG( pMedium->GetItemSet(), pIndicatorItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
[ + - ]
322 : 82 : Reference< XStatusIndicator > xInd;
323 [ + - ][ + - ]: 82 : if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
[ + + ]
[ + + # # ]
[ + + ]
324 [ + - ]: 82 : pImp->xStatusInd = xInd;
325 : : }
326 : : }
327 : : }
328 : : }
329 [ + - ]: 43 : else if ( pImp->pView )
330 : : {
331 : 43 : pImp->pWorkWin = SFX_APP()->GetWorkWindow_Impl( pImp->pView );
332 [ + - ]: 43 : if ( pImp->pWorkWin )
333 [ + - ]: 43 : pImp->xStatusInd = pImp->pWorkWin->GetStatusIndicator();
334 : : }
335 : :
336 [ + + ]: 125 : if ( pImp->xStatusInd.is() )
337 : : {
338 [ + - ]: 89 : pImp->xStatusInd->start( pImp->aText, pImp->nMax );
339 : 89 : pImp->pView = NULL;
340 : : }
341 : : }
342 : :
343 [ + + ]: 1701 : if ( pImp->xStatusInd.is() )
344 : : {
345 : 1665 : pImp->xStatusInd->setValue( nNewVal );
346 : : }
347 : :
348 : 1701 : return sal_True;
349 : : }
350 : :
351 : : // -----------------------------------------------------------------------
352 : :
353 : 346 : void SfxProgress::Resume()
354 : :
355 : : /* [Description]
356 : :
357 : : Resumed the status of the display after an interrupt.
358 : :
359 : : [Cross-reference]
360 : :
361 : : <SfxProgress::Suspend()>
362 : : */
363 : :
364 : : {
365 [ - + ]: 692 : if( pImp->pActiveProgress ) return;
366 [ + - ]: 346 : if ( bSuspended )
367 : : {
368 : : DBG( DbgOutf( "SfxProgress: resumed" ) );
369 [ - + ]: 346 : if ( pImp->xStatusInd.is() )
370 : : {
371 [ # # ]: 0 : pImp->xStatusInd->start( pImp->aText, pImp->nMax );
372 : 0 : pImp->xStatusInd->setValue( nVal );
373 : : }
374 : :
375 [ + - ]: 346 : if ( pImp->bWaitMode )
376 : : {
377 [ + - ][ + - ]: 346 : if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
[ + - ]
378 : : {
379 [ + + ]: 610 : for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
380 : : pFrame;
381 : 264 : pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
382 : 264 : pFrame->GetWindow().EnterWait();
383 : : }
384 : : }
385 : :
386 [ + - ]: 346 : if ( pImp->xObjSh )
387 : : {
388 : 346 : SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
389 [ + + ]: 346 : if ( pFrame )
390 : 264 : pFrame->GetBindings().ENTERREGISTRATIONS();
391 : : }
392 : :
393 : 346 : bSuspended = sal_False;
394 : : }
395 : : }
396 : :
397 : : // -----------------------------------------------------------------------
398 : :
399 : 346 : void SfxProgress::Suspend()
400 : :
401 : : /* [Description]
402 : :
403 : : Interrupts the status of the display
404 : :
405 : : [Cross-reference]
406 : :
407 : : <SfxProgress::Resume()>
408 : : */
409 : :
410 : : {
411 [ - + ]: 692 : if( pImp->pActiveProgress ) return;
412 [ + - ]: 346 : if ( !bSuspended )
413 : : {
414 : : DBG( DbgOutf( "SfxProgress: suspended" ) );
415 : 346 : bSuspended = sal_True;
416 : :
417 [ + + ]: 346 : if ( pImp->xStatusInd.is() )
418 : : {
419 : 89 : pImp->xStatusInd->reset();
420 : : }
421 : :
422 [ + - ][ + - ]: 346 : if ( pImp->xObjSh.Is() && !pImp->bAllDocs )
[ + - ]
423 : : {
424 [ + + ]: 610 : for ( SfxViewFrame *pFrame =
425 : 346 : SfxViewFrame::GetFirst(pImp->xObjSh);
426 : : pFrame;
427 : 264 : pFrame = SfxViewFrame::GetNext( *pFrame, pImp->xObjSh ) )
428 : 264 : pFrame->GetWindow().LeaveWait();
429 : : }
430 [ + - ]: 346 : if ( pImp->xObjSh.Is() )
431 : : {
432 : 346 : SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImp->xObjSh);
433 [ + + ]: 346 : if ( pFrame )
434 : 264 : pFrame->GetBindings().LEAVEREGISTRATIONS();
435 : : }
436 : : }
437 : : }
438 : :
439 : : // -----------------------------------------------------------------------
440 : :
441 : 0 : void SfxProgress::UnLock()
442 : : {
443 [ # # ]: 0 : if( pImp->pActiveProgress ) return;
444 [ # # ]: 0 : if ( !pImp->bLocked )
445 : 0 : return;
446 : :
447 : : DBG( DbgOutf( "SfxProgress: unlocked" ) );
448 : 0 : pImp->bLocked = sal_False;
449 : 0 : pImp->Enable_Impl(sal_True);
450 : : }
451 : :
452 : : // -----------------------------------------------------------------------
453 : :
454 : 42 : void SfxProgress::Reschedule()
455 : :
456 : : /* [Description]
457 : :
458 : : Reschedule, callable from the outside
459 : : */
460 : :
461 : : {
462 : : SFX_STACK(SfxProgress::Reschedule);
463 : :
464 [ - + ]: 84 : if( pImp->pActiveProgress ) return;
465 : 42 : SfxApplication* pApp = SFX_APP();
466 [ # # ][ - + ]: 42 : if ( pImp->bLocked && 0 == pApp->Get_Impl()->nRescheduleLocks )
[ - + ]
467 : : {
468 : 0 : SfxAppData_Impl *pAppData = pApp->Get_Impl();
469 : 0 : ++pAppData->nInReschedule;
470 : 0 : Application::Reschedule();
471 : 0 : --pAppData->nInReschedule;
472 : : }
473 : : }
474 : :
475 : : // -----------------------------------------------------------------------
476 : :
477 : 9951 : SfxProgress* SfxProgress::GetActiveProgress
478 : : (
479 : : SfxObjectShell* pDocSh /* the <SfxObjectShell>, which should be
480 : : queried after a current <SfxProgress>,
481 : : or 0 if an current SfxProgress for the
482 : : entire application should be obtained.
483 : : The pointer only needs at the time of
484 : : the call to be valid.
485 : : */
486 : : )
487 : :
488 : : /* [Description]
489 : :
490 : : This method is used to check whether and which <SfxProgress> is currently
491 : : active for a specific instance of SfxObjectShell or even an entire
492 : : application. This can for example be used to check for Time-Out-Events, etc.
493 : :
494 : : Instead of a pointer to the SfxProgress the SfxObjectShell may be
495 : : pointed at the SfxProgress of the application, with the query
496 : : 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
497 : : SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
498 : : the application or a 0-pointer.
499 : :
500 : : [Note]
501 : :
502 : : If no SfxProgress is running in the application and also not at the
503 : : specified SfxObjectShell, then this method will always return 0,
504 : : even if one SfxProgress runs on another SfxObjectShell.
505 : :
506 : : [Cross-reference]
507 : :
508 : : <SfxApplication::GetProgress()const>
509 : : <SfxObjectShell::GetProgress()const>
510 : : */
511 : :
512 : : {
513 [ - + ]: 9951 : if ( !SfxApplication::Get() )
514 : 0 : return 0;
515 : :
516 : 9951 : SfxProgress *pProgress = 0;
517 [ + + ]: 9951 : if ( pDocSh )
518 : 9636 : pProgress = pDocSh->GetProgress();
519 [ + + ]: 9951 : if ( !pProgress )
520 : 9940 : pProgress = SFX_APP()->GetProgress();
521 : 9951 : return pProgress;
522 : : }
523 : :
524 : : // -----------------------------------------------------------------------
525 : :
526 : 263 : void SfxProgress::EnterLock()
527 : : {
528 : 263 : SFX_APP()->Get_Impl()->nRescheduleLocks++;
529 : 263 : }
530 : :
531 : : // -----------------------------------------------------------------------
532 : :
533 : 263 : void SfxProgress::LeaveLock()
534 : : {
535 : 263 : SfxAppData_Impl *pImp = SFX_APP()->Get_Impl();
536 : : DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
537 : 263 : pImp->nRescheduleLocks--;
538 : 263 : }
539 : :
540 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|