/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <sfx2/progress.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
#include <svl/eitem.hxx>
#include <tools/debug.hxx>
#include <sal/log.hxx>
#include <appdata.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/app.hxx>
#include <sfxtypes.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxsids.hrc>
#include <workwin.hxx>
#include <sfxbasecontroller_internal.hxx>
#include <time.h>
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::task;
struct SfxProgress_Impl
{
Reference < XStatusIndicator > xStatusInd;
OUString aText;
sal_uInt32 nMax;
clock_t nCreate;
bool bWaitMode;
bool bRunning;
SfxProgress* pActiveProgress;
SfxObjectShellRef xObjSh;
SfxWorkWindow* pWorkWin;
SfxViewFrame* pView;
explicit SfxProgress_Impl();
};
SfxProgress_Impl::SfxProgress_Impl()
: nMax(0)
, nCreate(0)
, bWaitMode(false)
, bRunning(false)
, pActiveProgress(nullptr)
, pWorkWin(nullptr)
, pView(nullptr)
{
}
SfxProgress::SfxProgress
(
SfxObjectShell* pObjSh, /* The action is performed on the
SfxObjectShell which can be NULL.
When it is then the application will be
used */
const OUString& rText, /* Text, which appears before the Statusmonitor
in the status line */
sal_uInt32 nRange, /* Max value for range */
bool bWait /* Activate the wait-Pointer initially (TRUE) */
)
/* [Description]
The constructor of the class SfxProgress switches the SfxObjectShell
passed as parameter and SfxViewFrames which display this document in
a progress mode. Ie as long as one of those SfxViewFrame instances is
active the associated SfxDispatcher and associated Window is disabled.
A progress-bar will be displayed in the status bar,
*/
: pImpl( new SfxProgress_Impl ),
nVal(0),
bSuspended(true)
{
pImpl->bRunning = true;
pImpl->xObjSh = pObjSh;
pImpl->aText = rText;
pImpl->nMax = nRange;
pImpl->bWaitMode = bWait;
pImpl->nCreate = Get10ThSec();
SAL_INFO(
"sfx.bastyp",
"SfxProgress: created for '" << rText << "' at " << pImpl->nCreate
<< "ds");
pImpl->pWorkWin = nullptr;
pImpl->pView = nullptr;
pImpl->pActiveProgress = GetActiveProgress( pObjSh );
if ( pObjSh )
pObjSh->SetProgress_Impl(this);
else if( !pImpl->pActiveProgress )
SfxGetpApp()->SetProgress_Impl(this);
Resume();
}
SfxProgress::~SfxProgress()
/* [Description]
The destructor of the class SfxProgress restores the old status,
the documents are released again and the status bar shows the items again.
*/
{
Stop();
if ( pImpl->xStatusInd.is() )
pImpl->xStatusInd->end();
}
void SfxProgress::Stop()
/* [Description]
Early Exit of <SfxProgress>.
*/
{
if( pImpl->pActiveProgress )
{
if ( pImpl->xObjSh.is() && pImpl->xObjSh->GetProgress() == this )
pImpl->xObjSh->SetProgress_Impl(nullptr);
return;
}
if ( !pImpl->bRunning )
return;
pImpl->bRunning = false;
SAL_INFO(
"sfx.bastyp", "SfxProgress: destroyed at " << Get10ThSec() << "ds");
Suspend();
if ( pImpl->xObjSh.is() )
pImpl->xObjSh->SetProgress_Impl(nullptr);
else
SfxGetpApp()->SetProgress_Impl(nullptr);
}
void SfxProgress::SetState
(
sal_uInt32 nNewVal, /* new value for the progress bar */
sal_uInt32 nNewRange /* new maximum value, 0 for retaining the old */
)
/* [Description]
Setting the current status, after a time delay Reschedule is called.
*/
{
if( pImpl->pActiveProgress ) return;
nVal = nNewVal;
// new Range?
if ( nNewRange && nNewRange != pImpl->nMax )
{
SAL_INFO(
"sfx.bastyp",
"SfxProgress: range changed from " << pImpl->nMax << " to "
<< nNewRange);
pImpl->nMax = nNewRange;
}
if ( !pImpl->xStatusInd.is() )
{
// get the active ViewFrame of the document this progress is working on
// if it doesn't work on a document, take the current ViewFrame
SfxObjectShell* pObjSh = pImpl->xObjSh.get();
pImpl->pView = SfxViewFrame::Current();
DBG_ASSERT( pImpl->pView || pObjSh, "Can't make progress bar!");
if ( pObjSh && ( !pImpl->pView || pObjSh != pImpl->pView->GetObjectShell() ) )
{
// current document does not belong to current ViewFrame; take it's first visible ViewFrame
SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
if ( pDocView )
pImpl->pView = pDocView;
else
{
// don't show status indicator for hidden documents (only valid while loading)
SfxMedium* pMedium = pObjSh->GetMedium();
const SfxBoolItem* pHiddenItem = pMedium->GetItemSet().GetItem(SID_HIDDEN, false);
if ( !pHiddenItem || !pHiddenItem->GetValue() )
{
const SfxUnoAnyItem* pIndicatorItem = pMedium->GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL, false);
Reference< XStatusIndicator > xInd;
if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
pImpl->xStatusInd = std::move(xInd);
}
}
}
else if ( pImpl->pView )
{
pImpl->pWorkWin = SfxGetpApp()->GetWorkWindow_Impl( pImpl->pView );
if ( pImpl->pWorkWin )
pImpl->xStatusInd = pImpl->pWorkWin->GetStatusIndicator();
}
if ( pImpl->xStatusInd.is() )
{
pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax );
pImpl->pView = nullptr;
}
}
if ( pImpl->xStatusInd.is() )
{
pImpl->xStatusInd->setValue( nNewVal );
}
}
void SfxProgress::Resume()
/* [Description]
Resumed the status of the display after an interrupt.
[Cross-reference]
<SfxProgress::Suspend()>
*/
{
if( pImpl->pActiveProgress ) return;
if ( !bSuspended )
return;
SAL_INFO("sfx.bastyp", "SfxProgress: resumed");
if ( pImpl->xStatusInd.is() )
{
pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax );
pImpl->xStatusInd->setValue( nVal );
}
if ( pImpl->bWaitMode )
{
if ( pImpl->xObjSh.is() )
{
for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get() );
pFrame;
pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) )
pFrame->GetWindow().EnterWait();
}
}
if ( pImpl->xObjSh.is() )
{
SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get());
if ( pFrame )
pFrame->GetBindings().ENTERREGISTRATIONS();
}
bSuspended = false;
}
void SfxProgress::Suspend()
/* [Description]
Interrupts the status of the display
[Cross-reference]
<SfxProgress::Resume()>
*/
{
if( pImpl->pActiveProgress ) return;
if ( bSuspended )
return;
SAL_INFO("sfx.bastyp", "SfxProgress: suspended");
bSuspended = true;
if ( pImpl->xStatusInd.is() )
{
pImpl->xStatusInd->reset();
}
if ( pImpl->xObjSh.is() )
{
for ( SfxViewFrame *pFrame =
SfxViewFrame::GetFirst(pImpl->xObjSh.get());
pFrame;
pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) )
pFrame->GetWindow().LeaveWait();
}
if ( pImpl->xObjSh.is() )
{
SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pImpl->xObjSh.get() );
if ( pFrame )
pFrame->GetBindings().LEAVEREGISTRATIONS();
}
}
void SfxProgress::Reschedule()
/* [Description]
Reschedule, callable from the outside
*/
{
SFX_STACK(SfxProgress::Reschedule);
}
SfxProgress* SfxProgress::GetActiveProgress
(
SfxObjectShell const * pDocSh /* the <SfxObjectShell>, which should be
queried after a current <SfxProgress>,
or 0 if a current SfxProgress for the
entire application should be obtained.
The pointer only needs at the time of
the call to be valid.
*/
)
/* [Description]
This method is used to check whether and which <SfxProgress> is currently
active for a specific instance of SfxObjectShell or even an entire
application. This can for example be used to check for Time-Out-Events, etc.
Instead of a pointer to the SfxProgress the SfxObjectShell may be
pointed at the SfxProgress of the application, with the query
'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
the application or a 0-pointer.
[Note]
If no SfxProgress is running in the application and also not at the
specified SfxObjectShell, then this method will always return 0,
even if one SfxProgress runs on another SfxObjectShell.
[Cross-reference]
<SfxApplication::GetProgress()const>
<SfxObjectShell::GetProgress()const>
*/
{
if ( !SfxApplication::Get() )
return nullptr;
SfxProgress *pProgress = nullptr;
if ( pDocSh )
pProgress = pDocSh->GetProgress();
if ( !pProgress )
pProgress = SfxGetpApp()->GetProgress();
return pProgress;
}
void SfxProgress::EnterLock()
{
SfxGetpApp()->Get_Impl()->nRescheduleLocks++;
}
void SfxProgress::LeaveLock()
{
SfxAppData_Impl *pImp = SfxGetpApp()->Get_Impl();
DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
pImp->nRescheduleLocks--;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V1019 Compound assignment expression 'pIndicatorItem->GetValue() >>= xInd' is used inside condition.