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