/src/libreoffice/sfx2/source/bastyp/progress.cxx
Line | Count | Source |
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 <svl/eitem.hxx> |
26 | | #include <svl/itemset.hxx> |
27 | | #include <tools/debug.hxx> |
28 | | #include <sal/log.hxx> |
29 | | |
30 | | #include <appdata.hxx> |
31 | | #include <sfx2/bindings.hxx> |
32 | | #include <sfx2/frame.hxx> |
33 | | #include <sfx2/viewfrm.hxx> |
34 | | #include <sfx2/objsh.hxx> |
35 | | #include <sfx2/app.hxx> |
36 | | #include <sfxtypes.hxx> |
37 | | #include <sfx2/docfile.hxx> |
38 | | #include <sfx2/sfxsids.hrc> |
39 | | #include <workwin.hxx> |
40 | | #include <sfxbasecontroller_internal.hxx> |
41 | | #include <time.h> |
42 | | |
43 | | using namespace ::com::sun::star::uno; |
44 | | using namespace ::com::sun::star::task; |
45 | | |
46 | | struct SfxProgress_Impl |
47 | | { |
48 | | Reference < XStatusIndicator > xStatusInd; |
49 | | OUString aText; |
50 | | sal_uInt32 nMax; |
51 | | clock_t nCreate; |
52 | | bool bWaitMode; |
53 | | bool bRunning; |
54 | | |
55 | | SfxProgress* pActiveProgress; |
56 | | SfxObjectShellRef xObjSh; |
57 | | SfxWorkWindow* pWorkWin; |
58 | | SfxViewFrame* pView; |
59 | | |
60 | | explicit SfxProgress_Impl(); |
61 | | }; |
62 | | |
63 | | SfxProgress_Impl::SfxProgress_Impl() |
64 | 111k | : nMax(0) |
65 | 111k | , nCreate(0) |
66 | 111k | , bWaitMode(false) |
67 | 111k | , bRunning(false) |
68 | 111k | , pActiveProgress(nullptr) |
69 | 111k | , pWorkWin(nullptr) |
70 | 111k | , pView(nullptr) |
71 | 111k | { |
72 | 111k | } |
73 | | |
74 | | |
75 | | SfxProgress::SfxProgress |
76 | | ( |
77 | | SfxObjectShell* pObjSh, /* The action is performed on the |
78 | | SfxObjectShell which can be NULL. |
79 | | When it is then the application will be |
80 | | used */ |
81 | | |
82 | | const OUString& rText, /* Text, which appears before the Statusmonitor |
83 | | in the status line */ |
84 | | |
85 | | sal_uInt32 nRange, /* Max value for range */ |
86 | | |
87 | | bool bWait /* Activate the wait-Pointer initially (TRUE) */ |
88 | | ) |
89 | | |
90 | | /* [Description] |
91 | | |
92 | | The constructor of the class SfxProgress switches the SfxObjectShell |
93 | | passed as parameter and SfxViewFrames which display this document in |
94 | | a progress mode. Ie as long as one of those SfxViewFrame instances is |
95 | | active the associated SfxDispatcher and associated Window is disabled. |
96 | | A progress-bar will be displayed in the status bar, |
97 | | */ |
98 | | |
99 | 111k | : pImpl( new SfxProgress_Impl ), |
100 | 111k | nVal(0), |
101 | 111k | bSuspended(true) |
102 | 111k | { |
103 | 111k | pImpl->bRunning = true; |
104 | | |
105 | 111k | pImpl->xObjSh = pObjSh; |
106 | 111k | pImpl->aText = rText; |
107 | 111k | pImpl->nMax = nRange; |
108 | 111k | pImpl->bWaitMode = bWait; |
109 | 111k | pImpl->nCreate = Get10ThSec(); |
110 | 111k | SAL_INFO( |
111 | 111k | "sfx.bastyp", |
112 | 111k | "SfxProgress: created for '" << rText << "' at " << pImpl->nCreate |
113 | 111k | << "ds"); |
114 | 111k | pImpl->pWorkWin = nullptr; |
115 | 111k | pImpl->pView = nullptr; |
116 | | |
117 | 111k | pImpl->pActiveProgress = GetActiveProgress( pObjSh ); |
118 | 111k | if ( pObjSh ) |
119 | 46.8k | pObjSh->SetProgress_Impl(this); |
120 | 64.4k | else if( !pImpl->pActiveProgress ) |
121 | 64.4k | SfxGetpApp()->SetProgress_Impl(this); |
122 | 111k | Resume(); |
123 | 111k | } |
124 | | |
125 | | |
126 | | SfxProgress::~SfxProgress() |
127 | | |
128 | | /* [Description] |
129 | | |
130 | | The destructor of the class SfxProgress restores the old status, |
131 | | the documents are released again and the status bar shows the items again. |
132 | | */ |
133 | | |
134 | 111k | { |
135 | 111k | Stop(); |
136 | 111k | if ( pImpl->xStatusInd.is() ) |
137 | 3.97k | pImpl->xStatusInd->end(); |
138 | 111k | } |
139 | | |
140 | | |
141 | | void SfxProgress::Stop() |
142 | | |
143 | | /* [Description] |
144 | | |
145 | | Early Exit of <SfxProgress>. |
146 | | */ |
147 | | |
148 | 158k | { |
149 | 158k | if( pImpl->pActiveProgress ) |
150 | 0 | { |
151 | 0 | if ( pImpl->xObjSh.is() && pImpl->xObjSh->GetProgress() == this ) |
152 | 0 | pImpl->xObjSh->SetProgress_Impl(nullptr); |
153 | 0 | return; |
154 | 0 | } |
155 | | |
156 | 158k | if ( !pImpl->bRunning ) |
157 | 46.8k | return; |
158 | 111k | pImpl->bRunning = false; |
159 | 111k | SAL_INFO( |
160 | 111k | "sfx.bastyp", "SfxProgress: destroyed at " << Get10ThSec() << "ds"); |
161 | | |
162 | 111k | Suspend(); |
163 | 111k | if ( pImpl->xObjSh.is() ) |
164 | 46.8k | pImpl->xObjSh->SetProgress_Impl(nullptr); |
165 | 64.4k | else |
166 | 64.4k | SfxGetpApp()->SetProgress_Impl(nullptr); |
167 | 111k | } |
168 | | |
169 | | void SfxProgress::SetState |
170 | | ( |
171 | | sal_uInt32 nNewVal, /* new value for the progress bar */ |
172 | | |
173 | | sal_uInt32 nNewRange /* new maximum value, 0 for retaining the old */ |
174 | | ) |
175 | | /* [Description] |
176 | | |
177 | | Setting the current status, after a time delay Reschedule is called. |
178 | | */ |
179 | | |
180 | 3.51M | { |
181 | 3.51M | if( pImpl->pActiveProgress ) return; |
182 | | |
183 | 3.51M | nVal = nNewVal; |
184 | | |
185 | | // new Range? |
186 | 3.51M | if ( nNewRange && nNewRange != pImpl->nMax ) |
187 | 0 | { |
188 | 0 | SAL_INFO( |
189 | 0 | "sfx.bastyp", |
190 | 0 | "SfxProgress: range changed from " << pImpl->nMax << " to " |
191 | 0 | << nNewRange); |
192 | 0 | pImpl->nMax = nNewRange; |
193 | 0 | } |
194 | | |
195 | 3.51M | if ( !pImpl->xStatusInd.is() ) |
196 | 3.46M | { |
197 | | // get the active ViewFrame of the document this progress is working on |
198 | | // if it doesn't work on a document, take the current ViewFrame |
199 | 3.46M | SfxObjectShell* pObjSh = pImpl->xObjSh.get(); |
200 | 3.46M | pImpl->pView = SfxViewFrame::Current(); |
201 | 3.46M | DBG_ASSERT( pImpl->pView || pObjSh, "Can't make progress bar!"); |
202 | 3.46M | if ( pObjSh && ( !pImpl->pView || pObjSh != pImpl->pView->GetObjectShell() ) ) |
203 | 2.29M | { |
204 | | // current document does not belong to current ViewFrame; take it's first visible ViewFrame |
205 | 2.29M | SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh ); |
206 | 2.29M | if ( pDocView ) |
207 | 0 | pImpl->pView = pDocView; |
208 | 2.29M | else |
209 | 2.29M | { |
210 | | // don't show status indicator for hidden documents (only valid while loading) |
211 | 2.29M | SfxMedium* pMedium = pObjSh->GetMedium(); |
212 | 2.29M | const SfxBoolItem* pHiddenItem = pMedium->GetItemSet().GetItem(SID_HIDDEN, false); |
213 | 2.29M | if ( !pHiddenItem || !pHiddenItem->GetValue() ) |
214 | 2.29M | { |
215 | 2.29M | const SfxUnoAnyItem* pIndicatorItem = pMedium->GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL, false); |
216 | 2.29M | Reference< XStatusIndicator > xInd; |
217 | 2.29M | if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) ) |
218 | 0 | pImpl->xStatusInd = std::move(xInd); |
219 | 2.29M | } |
220 | 2.29M | } |
221 | 2.29M | } |
222 | 1.17M | else if ( pImpl->pView ) |
223 | 3.97k | { |
224 | 3.97k | pImpl->pWorkWin = SfxGetpApp()->GetWorkWindow_Impl( pImpl->pView ); |
225 | 3.97k | if ( pImpl->pWorkWin ) |
226 | 3.97k | pImpl->xStatusInd = pImpl->pWorkWin->GetStatusIndicator(); |
227 | 3.97k | } |
228 | | |
229 | 3.46M | if ( pImpl->xStatusInd.is() ) |
230 | 3.97k | { |
231 | 3.97k | pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax ); |
232 | 3.97k | pImpl->pView = nullptr; |
233 | 3.97k | } |
234 | 3.46M | } |
235 | | |
236 | 3.51M | if ( pImpl->xStatusInd.is() ) |
237 | 54.3k | { |
238 | 54.3k | pImpl->xStatusInd->setValue( nNewVal ); |
239 | 54.3k | } |
240 | 3.51M | } |
241 | | |
242 | | |
243 | | void SfxProgress::Resume() |
244 | | |
245 | | /* [Description] |
246 | | |
247 | | Resumed the status of the display after an interrupt. |
248 | | |
249 | | [Cross-reference] |
250 | | |
251 | | <SfxProgress::Suspend()> |
252 | | */ |
253 | | |
254 | 111k | { |
255 | 111k | if( pImpl->pActiveProgress ) return; |
256 | 111k | if ( !bSuspended ) |
257 | 0 | return; |
258 | | |
259 | 111k | SAL_INFO("sfx.bastyp", "SfxProgress: resumed"); |
260 | 111k | if ( pImpl->xStatusInd.is() ) |
261 | 0 | { |
262 | 0 | pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax ); |
263 | 0 | pImpl->xStatusInd->setValue( nVal ); |
264 | 0 | } |
265 | | |
266 | 111k | if ( pImpl->bWaitMode ) |
267 | 111k | { |
268 | 111k | if ( pImpl->xObjSh.is() ) |
269 | 46.8k | { |
270 | 46.8k | for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get() ); |
271 | 50.8k | pFrame; |
272 | 46.8k | pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) ) |
273 | 4.02k | pFrame->GetWindow().EnterWait(); |
274 | 46.8k | } |
275 | 111k | } |
276 | | |
277 | 111k | if ( pImpl->xObjSh.is() ) |
278 | 46.8k | { |
279 | 46.8k | SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get()); |
280 | 46.8k | if ( pFrame ) |
281 | 4.02k | pFrame->GetBindings().ENTERREGISTRATIONS(); |
282 | 46.8k | } |
283 | | |
284 | 111k | bSuspended = false; |
285 | 111k | } |
286 | | |
287 | | |
288 | | void SfxProgress::Suspend() |
289 | | |
290 | | /* [Description] |
291 | | |
292 | | Interrupts the status of the display |
293 | | |
294 | | [Cross-reference] |
295 | | |
296 | | <SfxProgress::Resume()> |
297 | | */ |
298 | | |
299 | 111k | { |
300 | 111k | if( pImpl->pActiveProgress ) return; |
301 | 111k | if ( bSuspended ) |
302 | 0 | return; |
303 | | |
304 | 111k | SAL_INFO("sfx.bastyp", "SfxProgress: suspended"); |
305 | 111k | bSuspended = true; |
306 | | |
307 | 111k | if ( pImpl->xStatusInd.is() ) |
308 | 3.97k | { |
309 | 3.97k | pImpl->xStatusInd->reset(); |
310 | 3.97k | } |
311 | | |
312 | 111k | if ( pImpl->xObjSh.is() ) |
313 | 46.8k | { |
314 | 46.8k | for ( SfxViewFrame *pFrame = |
315 | 46.8k | SfxViewFrame::GetFirst(pImpl->xObjSh.get()); |
316 | 50.8k | pFrame; |
317 | 46.8k | pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) ) |
318 | 4.02k | pFrame->GetWindow().LeaveWait(); |
319 | 46.8k | } |
320 | 111k | if ( pImpl->xObjSh.is() ) |
321 | 46.8k | { |
322 | 46.8k | SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pImpl->xObjSh.get() ); |
323 | 46.8k | if ( pFrame ) |
324 | 4.02k | pFrame->GetBindings().LEAVEREGISTRATIONS(); |
325 | 46.8k | } |
326 | 111k | } |
327 | | |
328 | | |
329 | | void SfxProgress::Reschedule() |
330 | | |
331 | | /* [Description] |
332 | | |
333 | | Reschedule, callable from the outside |
334 | | */ |
335 | | |
336 | 342k | { |
337 | 342k | SFX_STACK(SfxProgress::Reschedule); |
338 | 342k | } |
339 | | |
340 | | |
341 | | SfxProgress* SfxProgress::GetActiveProgress |
342 | | ( |
343 | | SfxObjectShell const * pDocSh /* the <SfxObjectShell>, which should be |
344 | | queried after a current <SfxProgress>, |
345 | | or 0 if a current SfxProgress for the |
346 | | entire application should be obtained. |
347 | | The pointer only needs at the time of |
348 | | the call to be valid. |
349 | | */ |
350 | | ) |
351 | | |
352 | | /* [Description] |
353 | | |
354 | | This method is used to check whether and which <SfxProgress> is currently |
355 | | active for a specific instance of SfxObjectShell or even an entire |
356 | | application. This can for example be used to check for Time-Out-Events, etc. |
357 | | |
358 | | Instead of a pointer to the SfxProgress the SfxObjectShell may be |
359 | | pointed at the SfxProgress of the application, with the query |
360 | | 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current |
361 | | SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of |
362 | | the application or a 0-pointer. |
363 | | |
364 | | [Note] |
365 | | |
366 | | If no SfxProgress is running in the application and also not at the |
367 | | specified SfxObjectShell, then this method will always return 0, |
368 | | even if one SfxProgress runs on another SfxObjectShell. |
369 | | |
370 | | [Cross-reference] |
371 | | |
372 | | <SfxApplication::GetProgress()const> |
373 | | <SfxObjectShell::GetProgress()const> |
374 | | */ |
375 | | |
376 | 285k | { |
377 | 285k | if ( !SfxApplication::Get() ) |
378 | 0 | return nullptr; |
379 | | |
380 | 285k | SfxProgress *pProgress = nullptr; |
381 | 285k | if ( pDocSh ) |
382 | 104k | pProgress = pDocSh->GetProgress(); |
383 | 285k | if ( !pProgress ) |
384 | 285k | pProgress = SfxGetpApp()->GetProgress(); |
385 | 285k | return pProgress; |
386 | 285k | } |
387 | | |
388 | | |
389 | | void SfxProgress::EnterLock() |
390 | 140 | { |
391 | 140 | SfxGetpApp()->Get_Impl()->nRescheduleLocks++; |
392 | 140 | } |
393 | | |
394 | | |
395 | | void SfxProgress::LeaveLock() |
396 | 140 | { |
397 | 140 | SfxAppData_Impl *pImp = SfxGetpApp()->Get_Impl(); |
398 | 140 | DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" ); |
399 | 140 | pImp->nRescheduleLocks--; |
400 | 140 | } |
401 | | |
402 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |