Line data Source code
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 : #include <DocumentStatisticsManager.hxx>
20 : #include <doc.hxx>
21 : #include <fldbas.hxx>
22 : #include <docsh.hxx>
23 : #include <IDocumentFieldsAccess.hxx>
24 : #include <IDocumentState.hxx>
25 : #include <IDocumentLayoutAccess.hxx>
26 : #include <view.hxx>
27 : #include <ndtxt.hxx>
28 : #include <switerator.hxx>
29 : #include <fmtfld.hxx>
30 : #include <rootfrm.hxx>
31 : #include <docufld.hxx>
32 : #include <docstat.hxx>
33 : #include <vector>
34 : #include <viewsh.hxx>
35 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
36 :
37 : using namespace ::com::sun::star;
38 :
39 : namespace
40 : {
41 : class LockAllViews
42 : {
43 : std::vector<SwViewShell*> m_aViewWasUnLocked;
44 : SwViewShell* m_pViewShell;
45 : public:
46 1303 : LockAllViews(SwViewShell *pViewShell)
47 1303 : : m_pViewShell(pViewShell)
48 : {
49 1303 : if (!m_pViewShell)
50 1319 : return;
51 1287 : SwViewShell *pSh = m_pViewShell;
52 1287 : do
53 : {
54 1287 : if (!pSh->IsViewLocked())
55 : {
56 1227 : m_aViewWasUnLocked.push_back(pSh);
57 1227 : pSh->LockView(true);
58 : }
59 1287 : pSh = (SwViewShell*)pSh->GetNext();
60 1287 : } while (pSh != m_pViewShell);
61 : }
62 1303 : ~LockAllViews()
63 1303 : {
64 2530 : for (std::vector<SwViewShell*>::iterator aI = m_aViewWasUnLocked.begin(); aI != m_aViewWasUnLocked.end(); ++aI)
65 : {
66 1227 : SwViewShell *pSh = *aI;
67 1227 : pSh->LockView(false);
68 : }
69 1303 : }
70 : };
71 : }
72 :
73 : namespace sw
74 : {
75 :
76 5052 : DocumentStatisticsManager::DocumentStatisticsManager( SwDoc& i_rSwdoc ) : m_rSwdoc( i_rSwdoc ),
77 5052 : mpDocStat( new SwDocStat )
78 : {
79 5052 : maStatsUpdateTimer.SetTimeout( 100 );
80 5052 : maStatsUpdateTimer.SetTimeoutHdl( LINK( this, DocumentStatisticsManager, DoIdleStatsUpdate ) );
81 5052 : }
82 :
83 6211 : void DocumentStatisticsManager::DocInfoChgd( )
84 : {
85 6211 : m_rSwdoc.getIDocumentFieldsAccess().GetSysFldType( RES_DOCINFOFLD )->UpdateFlds();
86 6211 : m_rSwdoc.getIDocumentFieldsAccess().GetSysFldType( RES_TEMPLNAMEFLD )->UpdateFlds();
87 6211 : m_rSwdoc.getIDocumentState().SetModified();
88 6211 : }
89 :
90 12857 : const SwDocStat& DocumentStatisticsManager::GetDocStat() const
91 : {
92 12857 : return *mpDocStat;
93 : }
94 :
95 1662588 : SwDocStat& DocumentStatisticsManager::GetDocStat()
96 : {
97 1662588 : return *mpDocStat;
98 : }
99 :
100 1129 : const SwDocStat& DocumentStatisticsManager::GetUpdatedDocStat( bool bCompleteAsync, bool bFields )
101 : {
102 1129 : if( mpDocStat->bModified )
103 : {
104 1085 : UpdateDocStat( bCompleteAsync, bFields );
105 : }
106 1129 : return *mpDocStat;
107 : }
108 :
109 308 : void DocumentStatisticsManager::SetDocStat( const SwDocStat& rStat )
110 : {
111 308 : *mpDocStat = rStat;
112 308 : }
113 :
114 1295 : void DocumentStatisticsManager::UpdateDocStat( bool bCompleteAsync, bool bFields )
115 : {
116 1295 : if( mpDocStat->bModified )
117 : {
118 1295 : if (!bCompleteAsync)
119 : {
120 480 : while (IncrementalDocStatCalculate(
121 240 : ::std::numeric_limits<long>::max(), bFields)) {}
122 240 : maStatsUpdateTimer.Stop();
123 : }
124 1055 : else if (IncrementalDocStatCalculate(5000, bFields))
125 8 : maStatsUpdateTimer.Start();
126 : }
127 1295 : }
128 :
129 : // returns true while there is more to do
130 1303 : bool DocumentStatisticsManager::IncrementalDocStatCalculate(long nChars, bool bFields)
131 : {
132 1303 : mpDocStat->Reset();
133 1303 : mpDocStat->nPara = 0; // default is 1!
134 : SwNode* pNd;
135 :
136 : // This is the inner loop - at least while the paras are dirty.
137 25834 : for( sal_uLong i = m_rSwdoc.GetNodes().Count(); i > 0 && nChars > 0; )
138 : {
139 23228 : switch( ( pNd = m_rSwdoc.GetNodes()[ --i ])->GetNodeType() )
140 : {
141 : case ND_TEXTNODE:
142 : {
143 6601 : long const nOldChars(mpDocStat->nChar);
144 6601 : SwTxtNode *pTxt = static_cast< SwTxtNode * >( pNd );
145 6601 : if (pTxt->CountWords(*mpDocStat, 0, pTxt->GetTxt().getLength()))
146 : {
147 970 : nChars -= (mpDocStat->nChar - nOldChars);
148 : }
149 6601 : break;
150 : }
151 69 : case ND_TABLENODE: ++mpDocStat->nTbl; break;
152 43 : case ND_GRFNODE: ++mpDocStat->nGrf; break;
153 26 : case ND_OLENODE: ++mpDocStat->nOLE; break;
154 137 : case ND_SECTIONNODE: break;
155 : }
156 : }
157 :
158 : // #i93174#: notes contain paragraphs that are not nodes
159 : {
160 1303 : SwFieldType * const pPostits( m_rSwdoc.getIDocumentFieldsAccess().GetSysFldType(RES_POSTITFLD) );
161 1303 : SwIterator<SwFmtFld,SwFieldType> aIter( *pPostits );
162 1352 : for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
163 : {
164 49 : if (pFmtFld->IsFldInDoc())
165 : {
166 : SwPostItField const * const pField(
167 49 : static_cast<SwPostItField const*>(pFmtFld->GetField()));
168 49 : mpDocStat->nAllPara += pField->GetNumberOfParagraphs();
169 : }
170 1303 : }
171 : }
172 :
173 1303 : mpDocStat->nPage = m_rSwdoc.getIDocumentLayoutAccess().GetCurrentLayout() ? m_rSwdoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum() : 0;
174 1303 : mpDocStat->bModified = false;
175 :
176 1303 : com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aStat( mpDocStat->nPage ? 8 : 7);
177 1303 : sal_Int32 n=0;
178 1303 : aStat[n].Name = "TableCount";
179 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nTbl;
180 1303 : aStat[n].Name = "ImageCount";
181 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nGrf;
182 1303 : aStat[n].Name = "ObjectCount";
183 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nOLE;
184 1303 : if ( mpDocStat->nPage )
185 : {
186 1287 : aStat[n].Name = "PageCount";
187 1287 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nPage;
188 : }
189 1303 : aStat[n].Name = "ParagraphCount";
190 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nPara;
191 1303 : aStat[n].Name = "WordCount";
192 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nWord;
193 1303 : aStat[n].Name = "CharacterCount";
194 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nChar;
195 1303 : aStat[n].Name = "NonWhitespaceCharacterCount";
196 1303 : aStat[n++].Value <<= (sal_Int32)mpDocStat->nCharExcludingSpaces;
197 :
198 : // For e.g. autotext documents there is no pSwgInfo (#i79945)
199 1303 : SwDocShell* pObjShell(m_rSwdoc.GetDocShell());
200 1303 : if (pObjShell)
201 : {
202 : const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
203 1303 : pObjShell->GetModel(), uno::UNO_QUERY_THROW);
204 : const uno::Reference<document::XDocumentProperties> xDocProps(
205 2606 : xDPS->getDocumentProperties());
206 : // #i96786#: do not set modified flag when updating statistics
207 1303 : const bool bDocWasModified( m_rSwdoc.getIDocumentState().IsModified() );
208 2606 : const ModifyBlocker_Impl b(pObjShell);
209 : // rhbz#1081176: don't jump to cursor pos because of (temporary)
210 : // activation of modified flag triggering move to input position
211 2606 : LockAllViews aViewGuard((SwViewShell*)pObjShell->GetWrtShell());
212 1303 : xDocProps->setDocumentStatistics(aStat);
213 1303 : if (!bDocWasModified)
214 : {
215 922 : m_rSwdoc.getIDocumentState().ResetModified();
216 1303 : }
217 : }
218 :
219 : // optionally update stat. fields
220 1303 : if (bFields)
221 : {
222 248 : SwFieldType *pType = m_rSwdoc.getIDocumentFieldsAccess().GetSysFldType(RES_DOCSTATFLD);
223 248 : pType->UpdateFlds();
224 : }
225 :
226 1303 : return nChars <= 0;
227 : }
228 :
229 16 : IMPL_LINK( DocumentStatisticsManager, DoIdleStatsUpdate, Timer *, pTimer )
230 : {
231 : (void)pTimer;
232 8 : if (IncrementalDocStatCalculate(32000))
233 0 : maStatsUpdateTimer.Start();
234 :
235 8 : SwView* pView = m_rSwdoc.GetDocShell() ? m_rSwdoc.GetDocShell()->GetView() : NULL;
236 8 : if( pView )
237 8 : pView->UpdateDocStats();
238 8 : return 0;
239 : }
240 :
241 15135 : DocumentStatisticsManager::~DocumentStatisticsManager()
242 : {
243 5045 : maStatsUpdateTimer.Stop();
244 5045 : delete mpDocStat;
245 10090 : }
246 :
247 270 : }
248 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|