summaryrefslogtreecommitdiffstats
path: root/sw
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2013-02-13 11:35:13 +0000
committerMichael Meeks <michael.meeks@suse.com>2013-02-13 12:13:56 +0000
commitc138a8aec8dccb97948a7d7993e6869da4079b32 (patch)
tree51efecacb1aad23c2a965fda20d1ac319501386f /sw
parentadd headers to new files (diff)
downloadcore-c138a8aec8dccb97948a7d7993e6869da4079b32.tar.gz
core-c138a8aec8dccb97948a7d7993e6869da4079b32.zip
asynchronous word-count.
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/IDocumentStatistics.hxx17
-rw-r--r--sw/inc/doc.hxx16
-rw-r--r--sw/inc/ndtxt.hxx4
-rw-r--r--sw/source/core/doc/doc.cxx181
-rw-r--r--sw/source/core/doc/docnew.cxx4
-rw-r--r--sw/source/core/txtnode/txtedt.cxx18
-rw-r--r--sw/source/ui/dialog/wordcountdialog.cxx2
-rw-r--r--sw/source/ui/inc/view.hxx6
-rw-r--r--sw/source/ui/uiview/view.cxx1
-rw-r--r--sw/source/ui/uiview/view2.cxx9
10 files changed, 163 insertions, 95 deletions
diff --git a/sw/inc/IDocumentStatistics.hxx b/sw/inc/IDocumentStatistics.hxx
index 4ec926a15d2c..2c5a05019ccb 100644
--- a/sw/inc/IDocumentStatistics.hxx
+++ b/sw/inc/IDocumentStatistics.hxx
@@ -35,13 +35,26 @@
/** Document - Statistics
*/
+ /// Returns a reference to the existing document statistics
virtual const SwDocStat &GetDocStat() const = 0;
- virtual const SwDocStat &GetUpdatedDocStat() = 0;
+ /**
+ * Updates the document statistics if the document has been
+ * modified and returns a reference to the result.
+ * \param bCompleteAsync if true will return a partial result,
+ * and potentially trigger a timeout to complete the work.
+ */
+ virtual const SwDocStat &GetUpdatedDocStat(bool bCompleteAsync) = 0;
+ /// Set the document statistics
virtual void SetDocStat(const SwDocStat& rStat) = 0;
- virtual void UpdateDocStat() = 0;
+ /**
+ * Updates the internal document's statistics
+ * \param bCompleteAsync if true it may do part of the
+ * work and trigger a timeout to complete it.
+ */
+ virtual void UpdateDocStat(bool bCompleteAsync) = 0;
protected:
virtual ~IDocumentStatistics() {};
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index c67f79fb8ce6..ccebf5c7985a 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -282,6 +282,7 @@ class SW_DLLPUBLIC SwDoc :
*/
Timer aIdleTimer; ///< Own IdleTimer
Timer aOLEModifiedTimer; ///< Timer for update modified OLE-Objecs
+ Timer aStatsUpdateTimer; ///< Timer for asynchronous stats calculation
SwDBData aDBData; ///< database descriptor
::com::sun::star::uno::Sequence <sal_Int8 > aRedlinePasswd;
String sTOIAutoMarkURL; ///< ::com::sun::star::util::URL of table of index AutoMark file
@@ -909,9 +910,9 @@ public:
*/
virtual void DocInfoChgd();
virtual const SwDocStat &GetDocStat() const;
- virtual const SwDocStat &GetUpdatedDocStat();
+ virtual const SwDocStat &GetUpdatedDocStat(bool bCompleteAsync = false);
virtual void SetDocStat(const SwDocStat& rStat);
- virtual void UpdateDocStat();
+ virtual void UpdateDocStat(bool bCompleteAsync = false);
/** IDocumentState
*/
@@ -2071,6 +2072,17 @@ private:
void CopyMasterHeader(const SwPageDesc &rChged, const SwFmtHeader &rHead, SwPageDesc *pDesc, bool bLeft);
/// Copies master footer to left / first one, if necessary - used by ChgPageDesc().
void CopyMasterFooter(const SwPageDesc &rChged, const SwFmtFooter &rFoot, SwPageDesc *pDesc, bool bLeft);
+
+ /** continue computing a chunk of document statistics
+ * \param nTextNodes number of paragraphs to calculate before
+ * exiting
+ *
+ * returns false when there is no more to calculate
+ */
+ bool IncrementalDocStatCalculate(long nTextNodes = 250);
+
+ /// Our own 'StatsUpdateTimer' calls the following method
+ DECL_LINK( DoIdleStatsUpdate, Timer * );
};
// This method is called in Dtor of SwDoc and deletes cache of ContourObjects.
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 18c2b0287462..5a47fb237883 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -745,8 +745,8 @@ public:
xub_StrLen nStart, xub_StrLen nEnd,
SwUndoTransliterate* pUndo = 0 );
- /// count words in given range
- void CountWords( SwDocStat& rStat, xub_StrLen nStart, xub_StrLen nEnd ) const;
+ /// count words in given range - returns true if we refreshed out count
+ bool CountWords( SwDocStat& rStat, xub_StrLen nStart, xub_StrLen nEnd ) const;
/** Checks some global conditions like loading or destruction of document
to economize notifications */
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index cd71cf5e6b27..0470ef3a2551 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -55,6 +55,7 @@
#include <editeng/rsiditem.hxx>
#include <unotools/charclass.hxx>
#include <unotools/localedatawrapper.hxx>
+#include <vcl/timer.hxx>
#include <swatrset.hxx>
#include <swmodule.hxx>
@@ -112,6 +113,7 @@
#include <shellres.hxx>
#include <txtfrm.hxx>
#include <attrhint.hxx>
+#include <view.hxx>
#include <wdocsh.hxx> // SwWebDocShell
#include <prtopt.hxx> // SwPrintOptions
@@ -1146,10 +1148,6 @@ bool SwDoc::UpdateParRsid( SwTxtNode *pTxtNode, sal_uInt32 nVal )
return pTxtNode->SetAttr( aRsid );
}
-
-/*************************************************************************
- * void SetDocStat( const SwDocStat& rStat );
- *************************************************************************/
void SwDoc::SetDocStat( const SwDocStat& rStat )
{
*pDocStat = rStat;
@@ -1160,11 +1158,11 @@ const SwDocStat& SwDoc::GetDocStat() const
return *pDocStat;
}
-const SwDocStat& SwDoc::GetUpdatedDocStat()
+const SwDocStat& SwDoc::GetUpdatedDocStat( bool bCompleteAsync )
{
- if (pDocStat->bModified)
+ if( pDocStat->bModified )
{
- UpdateDocStat();
+ UpdateDocStat( bCompleteAsync );
}
return *pDocStat;
}
@@ -1686,92 +1684,117 @@ void SwDoc::CalculatePagePairsForProspectPrinting(
// thus we are done here.
}
-/*************************************************************************
- * void UpdateDocStat();
- *************************************************************************/
-void SwDoc::UpdateDocStat()
+// returns true while there is more to do
+bool SwDoc::IncrementalDocStatCalculate( long nTextNodes )
{
- if( pDocStat->bModified )
- {
- pDocStat->Reset();
- pDocStat->nPara = 0; // default is 1!
- SwNode* pNd;
+ pDocStat->Reset();
+ pDocStat->nPara = 0; // default is 1!
+ SwNode* pNd;
- for( sal_uLong i = GetNodes().Count(); i; )
+ // This is the inner loop - at least while the paras are dirty.
+ for( sal_uLong i = GetNodes().Count(); i > 0 && nTextNodes > 0; )
+ {
+ switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
{
- switch( ( pNd = GetNodes()[ --i ])->GetNodeType() )
- {
- case ND_TEXTNODE:
- ((SwTxtNode*)pNd)->CountWords( *pDocStat, 0, ((SwTxtNode*)pNd)->GetTxt().Len() );
- break;
- case ND_TABLENODE: ++pDocStat->nTbl; break;
- case ND_GRFNODE: ++pDocStat->nGrf; break;
- case ND_OLENODE: ++pDocStat->nOLE; break;
- case ND_SECTIONNODE: break;
- }
+ case ND_TEXTNODE:
+ {
+ SwTxtNode *pTxt = static_cast< SwTxtNode * >( pNd );
+ if( pTxt->CountWords( *pDocStat, 0, pTxt->GetTxt().Len() ) )
+ nTextNodes--;
+ break;
+ }
+ case ND_TABLENODE: ++pDocStat->nTbl; break;
+ case ND_GRFNODE: ++pDocStat->nGrf; break;
+ case ND_OLENODE: ++pDocStat->nOLE; break;
+ case ND_SECTIONNODE: break;
}
+ }
- // #i93174#: notes contain paragraphs that are not nodes
+ // #i93174#: notes contain paragraphs that are not nodes
+ {
+ SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
+ SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
+ for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
{
- SwFieldType * const pPostits( GetSysFldType(RES_POSTITFLD) );
- SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
- for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
+ if (pFmtFld->IsFldInDoc())
{
- if (pFmtFld->IsFldInDoc())
- {
- SwPostItField const * const pField(
- static_cast<SwPostItField const*>(pFmtFld->GetFld()));
- pDocStat->nAllPara += pField->GetNumberOfParagraphs();
- }
+ SwPostItField const * const pField(
+ static_cast<SwPostItField const*>(pFmtFld->GetFld()));
+ pDocStat->nAllPara += pField->GetNumberOfParagraphs();
}
}
+ }
- pDocStat->nPage = GetCurrentLayout() ? GetCurrentLayout()->GetPageNum() : 0; //swmod 080218
- pDocStat->bModified = sal_False;
-
- com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( pDocStat->nPage ? 8 : 7);
- sal_Int32 n=0;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nTbl;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nGrf;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ObjectCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nOLE;
- if ( pDocStat->nPage )
- {
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PageCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nPage;
- }
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParagraphCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nPara;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WordCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nWord;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharacterCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nChar;
- aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NonWhitespaceCharacterCount"));
- aStat[n++].Value <<= (sal_Int32)pDocStat->nCharExcludingSpaces;
-
- // For e.g. autotext documents there is no pSwgInfo (#i79945)
- SfxObjectShell * const pObjShell( GetDocShell() );
- if (pObjShell)
- {
- const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocStat->nPage = GetCurrentLayout() ? GetCurrentLayout()->GetPageNum() : 0;
+ pDocStat->bModified = sal_False;
+
+ com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( pDocStat->nPage ? 8 : 7);
+ sal_Int32 n=0;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TableCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nTbl;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ImageCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nGrf;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ObjectCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nOLE;
+ if ( pDocStat->nPage )
+ {
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("PageCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nPage;
+ }
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParagraphCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nPara;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WordCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nWord;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharacterCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nChar;
+ aStat[n].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NonWhitespaceCharacterCount"));
+ aStat[n++].Value <<= (sal_Int32)pDocStat->nCharExcludingSpaces;
+
+ // For e.g. autotext documents there is no pSwgInfo (#i79945)
+ SfxObjectShell * const pObjShell( GetDocShell() );
+ if (pObjShell)
+ {
+ const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
pObjShell->GetModel(), uno::UNO_QUERY_THROW);
- const uno::Reference<document::XDocumentProperties> xDocProps(
+ const uno::Reference<document::XDocumentProperties> xDocProps(
xDPS->getDocumentProperties());
- // #i96786#: do not set modified flag when updating statistics
- const bool bDocWasModified( IsModified() );
- const ModifyBlocker_Impl b(pObjShell);
- xDocProps->setDocumentStatistics(aStat);
- if (!bDocWasModified)
- {
- ResetModified();
- }
+ // #i96786#: do not set modified flag when updating statistics
+ const bool bDocWasModified( IsModified() );
+ const ModifyBlocker_Impl b(pObjShell);
+ xDocProps->setDocumentStatistics(aStat);
+ if (!bDocWasModified)
+ {
+ ResetModified();
}
+ }
+
+ // optionally update stat. fields
+ SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
+ pType->UpdateFlds();
+
+ return nTextNodes <= 0;
+}
+
+IMPL_LINK( SwDoc, DoIdleStatsUpdate, Timer *, pTimer )
+{
+ (void)pTimer;
+ if( IncrementalDocStatCalculate( 1000 ) )
+ aStatsUpdateTimer.Start();
- // optionally update stat. fields
- SwFieldType *pType = GetSysFldType(RES_DOCSTATFLD);
- pType->UpdateFlds();
+ SwView* pView = GetDocShell() ? GetDocShell()->GetView() : NULL;
+ if( pView )
+ pView->UpdateDocStats();
+ return 0;
+}
+
+void SwDoc::UpdateDocStat( bool bCompleteAsync )
+{
+ if( pDocStat->bModified )
+ {
+ if (!bCompleteAsync)
+ while (IncrementalDocStatCalculate()) {}
+ else if (IncrementalDocStatCalculate())
+ aStatsUpdateTimer.Start();
}
}
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 949cab186a13..7b1faa60025e 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -403,6 +403,9 @@ SwDoc::SwDoc()
aOLEModifiedTimer.SetTimeout( 1000 );
aOLEModifiedTimer.SetTimeoutHdl( LINK( this, SwDoc, DoUpdateModifiedOLE ));
+ aStatsUpdateTimer.SetTimeout( 100 );
+ aStatsUpdateTimer.SetTimeoutHdl( LINK( this, SwDoc, DoIdleStatsUpdate ) );
+
// Create DBMgr
pNewDBMgr = new SwNewDBMgr;
@@ -508,6 +511,7 @@ SwDoc::~SwDoc()
SetDefault(aCharFmt);
StopIdling(); // stop idle timer
+ aStatsUpdateTimer.Stop();
delete pUnoCallBack, pUnoCallBack = 0;
delete pURLStateChgd;
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index d91bf7dd9d15..3c8503bab834 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -1854,22 +1854,24 @@ void SwTxtNode::ReplaceTextOnly( xub_StrLen nPos, xub_StrLen nLen,
NotifyClients( 0, &aHint );
}
-void SwTxtNode::CountWords( SwDocStat& rStat,
+// the return values allows us to see if we did the heavy-
+// lifting required to actually break and count the words.
+bool SwTxtNode::CountWords( SwDocStat& rStat,
xub_StrLen nStt, xub_StrLen nEnd ) const
{
if( nStt > nEnd )
{ // bad call
- return;
+ return false;
}
if (IsInRedlines())
{ //not counting txtnodes used to hold deleted redline content
- return;
+ return false;
}
bool bCountAll = ( (0 == nStt) && (GetTxt().Len() == nEnd) );
++rStat.nAllPara; // #i93174#: count _all_ paragraphs
if ( IsHidden() )
{ // not counting hidden paras
- return;
+ return false;
}
// count words in numbering string if started at beginning of para:
bool bCountNumbering = nStt == 0;
@@ -1886,7 +1888,7 @@ void SwTxtNode::CountWords( SwDocStat& rStat,
if( nStt == nEnd && !bCountNumbering)
{ // unnumbered empty node or empty selection
- return;
+ return false;
}
// count of non-empty paras
@@ -1900,7 +1902,7 @@ void SwTxtNode::CountWords( SwDocStat& rStat,
rStat.nAsianWord += GetParaNumberOfAsianWords();
rStat.nChar += GetParaNumberOfChars();
rStat.nCharExcludingSpaces += GetParaNumberOfCharsExcludingSpaces();
- return;
+ return false;
}
// ConversionMap to expand fields, remove invisible and redline deleted text for scanner
@@ -1914,7 +1916,7 @@ void SwTxtNode::CountWords( SwDocStat& rStat,
if (aExpandText.isEmpty() && !bCountNumbering)
{
OSL_ENSURE(aExpandText.getLength() >= 0, "Node text expansion error: length < 0." );
- return;
+ return false;
}
//do the count
@@ -2002,6 +2004,8 @@ void SwTxtNode::CountWords( SwDocStat& rStat,
rStat.nAsianWord += nTmpAsianWords;
rStat.nChar += nTmpChars;
rStat.nCharExcludingSpaces += nTmpCharsExcludingSpaces;
+
+ return true;
}
//
diff --git a/sw/source/ui/dialog/wordcountdialog.cxx b/sw/source/ui/dialog/wordcountdialog.cxx
index ff777ace9502..6d8d738b25bf 100644
--- a/sw/source/ui/dialog/wordcountdialog.cxx
+++ b/sw/source/ui/dialog/wordcountdialog.cxx
@@ -32,7 +32,7 @@
#include <vcl/msgbox.hxx>
IMPL_LINK_NOARG(SwWordCountFloatDlg, CloseHdl)
-{
+{
SfxViewFrame* pVFrame = ::GetActiveView()->GetViewFrame();
if (pVFrame != NULL)
{
diff --git a/sw/source/ui/inc/view.hxx b/sw/source/ui/inc/view.hxx
index 2cfcf389fdae..d0a542bdcc35 100644
--- a/sw/source/ui/inc/view.hxx
+++ b/sw/source/ui/inc/view.hxx
@@ -358,7 +358,9 @@ class SW_DLLPUBLIC SwView: public SfxViewShell
SW_DLLPRIVATE virtual void Move();
- SW_DLLPRIVATE sal_Bool InsertGraphicDlg( SfxRequest& );
+ SW_DLLPRIVATE sal_Bool InsertGraphicDlg( SfxRequest& );
+
+ SW_DLLPRIVATE void DocumentStatsChanged();
protected:
@@ -656,6 +658,8 @@ public:
// exhibition hack (MA,MBA)
void SelectShellForDrop();
+
+ void UpdateDocStats();
};
// ----------------- inline Methoden ----------------------
diff --git a/sw/source/ui/uiview/view.cxx b/sw/source/ui/uiview/view.cxx
index 1ad946c0863b..26a135da34bd 100644
--- a/sw/source/ui/uiview/view.cxx
+++ b/sw/source/ui/uiview/view.cxx
@@ -1055,6 +1055,7 @@ SwView::~SwView()
bInDtor = sal_True;
pEditWin->Hide(); // damit kein Paint Aerger machen kann!
// An der SwDocShell den Pointer auf die View ruecksetzen
+
SwDocShell* pDocSh = GetDocShell();
if( pDocSh && pDocSh->GetView() == this )
pDocSh->SetView( 0 );
diff --git a/sw/source/ui/uiview/view2.cxx b/sw/source/ui/uiview/view2.cxx
index f5aff2af3675..0414f685589d 100644
--- a/sw/source/ui/uiview/view2.cxx
+++ b/sw/source/ui/uiview/view2.cxx
@@ -1203,6 +1203,13 @@ void SwView::UpdatePageNums(sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, const Strin
rBnd.Update( FN_STAT_PAGE );
}
+void SwView::UpdateDocStats()
+{
+ SfxBindings &rBnd = GetViewFrame()->GetBindings();
+ rBnd.Invalidate( FN_STAT_WORDCOUNT );
+ rBnd.Update( FN_STAT_WORDCOUNT );
+}
+
/*--------------------------------------------------------------------
Beschreibung: Status der Stauszeile
--------------------------------------------------------------------*/
@@ -1241,7 +1248,7 @@ void SwView::StateStatusLine(SfxItemSet &rSet)
SwDocStat documentStats;
{
rShell.CountWords(selectionStats);
- documentStats = rShell.GetDoc()->GetUpdatedDocStat();
+ documentStats = rShell.GetDoc()->GetUpdatedDocStat( true /* complete-async */ );
}
const sal_uInt32 stringId = selectionStats.nWord? STR_STATUSBAR_WORDCOUNT : STR_STATUSBAR_WORDCOUNT_NO_SELECTION;