[Libreoffice-commits] core.git: sw/inc sw/source

Jan-Marek Glogowski glogow at fbihome.de
Fri Oct 6 13:04:05 UTC 2017


 sw/inc/IDocumentTimerAccess.hxx             |    5 +
 sw/inc/doc.hxx                              |    9 +-
 sw/source/core/doc/DocumentTimerManager.cxx |  121 ++++++++++++++++------------
 sw/source/core/doc/SwDocIdle.cxx            |    6 +
 sw/source/core/doc/docnew.cxx               |   17 ++-
 sw/source/core/inc/DocumentTimerManager.hxx |   23 ++++-
 sw/source/uibase/uiview/view0.cxx           |    2 
 7 files changed, 121 insertions(+), 62 deletions(-)

New commits:
commit 53da556c600fa82ba84bc7fdce6a594b43f2b097
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Oct 6 11:00:19 2017 +0200

    Don't schedule the Idle job for busy documents
    
    This refactors DocumentTimerManager to export the busy status
    independent of the Idle function. This way it can be ignored in
    the Scheduler while the document is busy,
    
    Change-Id: Icec2075d3338ad8dd4440678eb0570d7fe887778
    Reviewed-on: https://gerrit.libreoffice.org/43197
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/sw/inc/IDocumentTimerAccess.hxx b/sw/inc/IDocumentTimerAccess.hxx
index 717728f83c99..6efe1a114963 100644
--- a/sw/inc/IDocumentTimerAccess.hxx
+++ b/sw/inc/IDocumentTimerAccess.hxx
@@ -55,6 +55,11 @@ public:
     */
     virtual void StartBackgroundJobs() = 0;
 
+    /**
+     * Is the document ready to be processed?
+     */
+    virtual bool IsDocIdle() const = 0;
+
 protected:
     virtual ~IDocumentTimerAccess() {};
 };
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index b12d2f8d821b..7476a3665f20 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -223,9 +223,6 @@ namespace sfx2 {
 
 void SetAllScriptItem( SfxItemSet& rSet, const SfxPoolItem& rItem );
 
-// global function to start grammar checking in the document
-void StartGrammarChecking( SwDoc &rDoc );
-
 using SwRubyList = std::vector<std::unique_ptr<SwRubyListEntry>>;
 
 // Represents the model of a Writer document.
@@ -1630,6 +1627,12 @@ public:
                       rTable.end());
     }
 
+    /**
+     * @param bSkipStart don't actually start the jobs, just check
+     * @returns true if new background checking jobs were started
+     */
+    bool StartGrammarChecking( bool bSkipStart = false );
+
 private:
     // Copies master header to left / first one, if necessary - used by ChgPageDesc().
     void CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &pDesc, bool bLeft, bool bFirst);
diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx
index ec4874ea9ecc..5429c6edbda6 100644
--- a/sw/source/core/doc/DocumentTimerManager.cxx
+++ b/sw/source/core/doc/DocumentTimerManager.cxx
@@ -80,27 +80,16 @@ void DocumentTimerManager::StartBackgroundJobs()
         maDocIdle.Start();
 }
 
-IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+DocumentTimerManager::IdleJob DocumentTimerManager::GetNextIdleJob() const
 {
-#ifdef TIMELOG
-    static ::rtl::Logfile* pModLogFile = 0;
-    if( !pModLogFile )
-        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
-#endif
-
     SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
     if( pTmpRoot &&
         !SfxProgress::GetActiveProgress( m_rDoc.GetDocShell() ) )
     {
         SwViewShell* pShell(m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell());
         for(SwViewShell& rSh : pShell->GetRingContainer())
-        {
             if( rSh.ActionPend() )
-            {
-                pIdle->Start();
-                return;
-            }
-        }
+                return IdleJob::Busy;
 
         if( pTmpRoot->IsNeedGrammarCheck() )
         {
@@ -109,59 +98,93 @@ IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
             SvtLinguConfig().GetProperty( OUString(
                         UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
 
-            if (bIsOnlineSpell && bIsAutoGrammar)
-                StartGrammarChecking( m_rDoc );
+            if( bIsOnlineSpell && bIsAutoGrammar && m_rDoc.StartGrammarChecking( true ) )
+                return IdleJob::Grammar;
         }
-        std::set<SwRootFrame*> aAllLayouts = m_rDoc.GetAllLayouts();
-        std::set<SwRootFrame*>::iterator pLayIter = aAllLayouts.begin();
-        for ( ;pLayIter != aAllLayouts.end();++pLayIter )
+
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
         {
-            if ((*pLayIter)->IsIdleFormat())
-            {
-                (*pLayIter)->GetCurrShell()->LayoutIdle();
-                // Defer the remaining work.
-                pIdle->Start();
-                return;
-            }
+            if( pLayout->IsIdleFormat() )
+                return IdleJob::Layout;
         }
 
         SwFieldUpdateFlags nFieldUpdFlag = m_rDoc.GetDocumentSettingManager().getFieldUpdateFlags(true);
         if( ( AUTOUPD_FIELD_ONLY == nFieldUpdFlag
-                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag ) &&
-                m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty()
-                // If we switch the field name the Fields are not updated.
-                // So the "background update" should always be carried out
-                /* && !pStartSh->GetViewOptions()->IsFieldName()*/ )
+                    || AUTOUPD_FIELD_AND_CHARTS == nFieldUpdFlag )
+                && m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsFieldsDirty() )
         {
-            if ( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields() ||
-                      m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+            if( m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().IsInUpdateFields()
+                    || m_rDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+                return IdleJob::Busy;
+            return IdleJob::Fields;
+        }
+    }
+
+    return IdleJob::None;
+}
+
+IMPL_LINK( DocumentTimerManager, DoIdleJobs, Timer*, pIdle, void )
+{
+#ifdef TIMELOG
+    static ::rtl::Logfile* pModLogFile = 0;
+    if( !pModLogFile )
+        pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
+#endif
+
+    IdleJob eJob = GetNextIdleJob();
+
+    switch ( eJob )
+    {
+    case IdleJob::Grammar:
+        m_rDoc.StartGrammarChecking();
+        break;
+
+    case IdleJob::Layout:
+        for ( auto pLayout : m_rDoc.GetAllLayouts() )
+            if( pLayout->IsIdleFormat() )
             {
-                pIdle->Start();
-                return;
+                pLayout->GetCurrShell()->LayoutIdle();
+                break;
             }
+         break;
 
-            //  Action brackets!
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
+    case IdleJob::Fields:
+    {
+        SwViewShell* pShell( m_rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() );
+        SwRootFrame* pTmpRoot = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
 
-            pTmpRoot->StartAllAction();
+        //  Action brackets!
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( true );
 
-            // no jump on update of fields #i85168#
-            const bool bOldLockView = pShell->IsViewLocked();
-            pShell->LockView( true );
+        pTmpRoot->StartAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );    // ChapterField
-            m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );      // Updates ExpressionFields
-            m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);                // Tables
-            m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();                // References
+        // no jump on update of fields #i85168#
+        const bool bOldLockView = pShell->IsViewLocked();
+        pShell->LockView( true );
 
-            pTmpRoot->EndAllAction();
+        m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter )->ModifyNotification( nullptr, nullptr );  // ChapterField
+        m_rDoc.getIDocumentFieldsAccess().UpdateExpFields( nullptr, false );  // Updates ExpressionFields
+        m_rDoc.getIDocumentFieldsAccess().UpdateTableFields(nullptr);  // Tables
+        m_rDoc.getIDocumentFieldsAccess().UpdateRefFields();  // References
 
-            pShell->LockView( bOldLockView );
+        pTmpRoot->EndAllAction();
 
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
-            m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
-        }
+        pShell->LockView( bOldLockView );
+
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetInUpdateFields( false );
+        m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().SetFieldsDirty( false );
+        break;
     }
+
+    case IdleJob::Busy:
+        break;
+    case IdleJob::None:
+        break;
+    }
+
+    if ( IdleJob::None != eJob )
+        pIdle->Start();
+
 #ifdef TIMELOG
     if( pModLogFile && 1 != (long)pModLogFile )
         delete pModLogFile, static_cast<long&>(pModLogFile) = 1;
diff --git a/sw/source/core/doc/SwDocIdle.cxx b/sw/source/core/doc/SwDocIdle.cxx
index 9461807943d8..5987274a6b3d 100644
--- a/sw/source/core/doc/SwDocIdle.cxx
+++ b/sw/source/core/doc/SwDocIdle.cxx
@@ -24,6 +24,7 @@
 #include <vcl/scheduler.hxx>
 
 #include "SwDocIdle.hxx"
+#include "IDocumentTimerAccess.hxx"
 
 namespace sw
 {
@@ -31,12 +32,17 @@ namespace sw
 sal_uInt64 SwDocIdle::UpdateMinPeriod( sal_uInt64 /* nMinPeriod */, sal_uInt64 /* nTimeNow */ ) const
 {
     bool bReadyForSchedule = true;
+
     SwView* pView = m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetView() : nullptr;
     if( pView )
     {
         SwWrtShell& rWrtShell = pView->GetWrtShell();
         bReadyForSchedule = rWrtShell.GetViewOptions()->IsIdle();
     }
+
+    if( bReadyForSchedule && !m_rDoc.getIDocumentTimerAccess().IsDocIdle() )
+        bReadyForSchedule = false;
+
     return bReadyForSchedule
         ? Scheduler::ImmediateTimeoutMs : Scheduler::InfiniteTimeoutMs;
 }
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 883fcbac9047..9e2a82d3083c 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -141,11 +141,12 @@ using namespace ::com::sun::star::document;
     return m_xGCIterator;
 }
 
-void StartGrammarChecking( SwDoc &rDoc )
+bool SwDoc::StartGrammarChecking( bool bSkipStart )
 {
     // check for a visible view
     bool bVisible = false;
-    const SwDocShell *pDocShell = rDoc.GetDocShell();
+    bool bStarted = false;
+    const SwDocShell *pDocShell = GetDocShell();
     SfxViewFrame     *pFrame = SfxViewFrame::GetFirst( pDocShell, false );
     while (pFrame && !bVisible)
     {
@@ -160,17 +161,23 @@ void StartGrammarChecking( SwDoc &rDoc )
     //!! a uno reference to them)
     if (bVisible)
     {
-        uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( rDoc.GetGCIterator() );
+        uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( GetGCIterator() );
         if ( xGCIterator.is() )
         {
-            uno::Reference< lang::XComponent >  xDoc( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
+            uno::Reference< lang::XComponent >  xDoc( GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
             uno::Reference< text::XFlatParagraphIteratorProvider >  xFPIP( xDoc, uno::UNO_QUERY );
 
             // start automatic background checking if not active already
             if ( xFPIP.is() && !xGCIterator->isProofreading( xDoc ) )
-                xGCIterator->startProofreading( xDoc, xFPIP );
+            {
+                bStarted = true;
+                if ( !bSkipStart )
+                    xGCIterator->startProofreading( xDoc, xFPIP );
+            }
         }
     }
+
+    return bStarted;
 }
 
 /*
diff --git a/sw/source/core/inc/DocumentTimerManager.hxx b/sw/source/core/inc/DocumentTimerManager.hxx
index 698762ab087e..d8c1a76b2a14 100644
--- a/sw/source/core/inc/DocumentTimerManager.hxx
+++ b/sw/source/core/inc/DocumentTimerManager.hxx
@@ -34,8 +34,17 @@ namespace sw
 class DocumentTimerManager : public IDocumentTimerAccess
 {
 public:
+    enum class IdleJob
+    {
+        None, ///< document has no idle jobs to do
+        Busy, ///< document is busy and idle jobs are postponed
+        Grammar,
+        Layout,
+        Fields,
+    };
 
     DocumentTimerManager( SwDoc& i_rSwdoc );
+    virtual ~DocumentTimerManager() override;
 
     void StartIdling() override;
 
@@ -47,15 +56,16 @@ public:
 
     void StartBackgroundJobs() override;
 
-    DECL_LINK( DoIdleJobs, Timer *, void );
-
-    virtual ~DocumentTimerManager() override;
+    bool IsDocIdle() const override;
 
 private:
-
     DocumentTimerManager(DocumentTimerManager const&) = delete;
     DocumentTimerManager& operator=(DocumentTimerManager const&) = delete;
 
+    DECL_LINK( DoIdleJobs, Timer *, void );
+
+    IdleJob GetNextIdleJob() const;
+
     SwDoc& m_rDoc;
 
     bool mbStartIdleTimer; //< idle timer mode start/stop
@@ -63,6 +73,11 @@ private:
     SwDocIdle maDocIdle;
 };
 
+inline bool DocumentTimerManager::IsDocIdle() const
+{
+    return( GetNextIdleJob() != IdleJob::Busy );
+}
+
 }
 
 #endif
diff --git a/sw/source/uibase/uiview/view0.cxx b/sw/source/uibase/uiview/view0.cxx
index 8f859fafd6c2..491017981728 100644
--- a/sw/source/uibase/uiview/view0.cxx
+++ b/sw/source/uibase/uiview/view0.cxx
@@ -524,7 +524,7 @@ void SwView::ExecViewOptions(SfxRequest &rReq)
                 aCfg.GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bIsAutoGrammar;
 
                 if (pDoc && bIsAutoGrammar)
-                    StartGrammarChecking( *pDoc );
+                    pDoc->StartGrammarChecking();
             }
         }
         break;


More information about the Libreoffice-commits mailing list