diff options
Diffstat (limited to 'sfx2/source/bastyp/progress.cxx')
-rw-r--r-- | sfx2/source/bastyp/progress.cxx | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/sfx2/source/bastyp/progress.cxx b/sfx2/source/bastyp/progress.cxx new file mode 100644 index 000000000..6d73d8316 --- /dev/null +++ b/sfx2/source/bastyp/progress.cxx @@ -0,0 +1,401 @@ +/* -*- 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 = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_HIDDEN, false); + if ( !pHiddenItem || !pHiddenItem->GetValue() ) + { + const SfxUnoAnyItem* pIndicatorItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pMedium->GetItemSet(), SID_PROGRESS_STATUSBAR_CONTROL, false); + Reference< XStatusIndicator > xInd; + if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) ) + pImpl->xStatusInd = 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: */ |