Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */