android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / doc / DocumentStatisticsManager.cxx
blob79df62ff1dd5fb67a2b6a876411ade2bc20e7340
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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 <fmtfld.hxx>
29 #include <rootfrm.hxx>
30 #include <docufld.hxx>
31 #include <docstat.hxx>
32 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
35 using namespace ::com::sun::star;
37 namespace sw
40 DocumentStatisticsManager::DocumentStatisticsManager( SwDoc& i_rSwdoc )
41 : m_rDoc( i_rSwdoc ),
42 mpDocStat( new SwDocStat ),
43 mbInitialized( false ),
44 maStatsUpdateIdle( i_rSwdoc, "sw::DocumentStatisticsManager maStatsUpdateIdle" )
46 maStatsUpdateIdle.SetPriority( TaskPriority::LOWEST );
47 maStatsUpdateIdle.SetInvokeHandler( LINK( this, DocumentStatisticsManager, DoIdleStatsUpdate ) );
50 void DocumentStatisticsManager::DocInfoChgd(bool const isEnableSetModified)
52 m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::DocInfo )->UpdateFields();
53 m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::TemplateName )->UpdateFields();
54 if (isEnableSetModified)
56 m_rDoc.getIDocumentState().SetModified();
60 const SwDocStat& DocumentStatisticsManager::GetDocStat() const
62 return *mpDocStat;
65 void DocumentStatisticsManager::SetDocStatModified(bool bSet)
67 mpDocStat->bModified = bSet;
70 const SwDocStat& DocumentStatisticsManager::GetUpdatedDocStat( bool bCompleteAsync, bool bFields )
72 if( mpDocStat->bModified || !mbInitialized)
74 UpdateDocStat( bCompleteAsync, bFields );
76 return *mpDocStat;
79 void DocumentStatisticsManager::SetDocStat( const SwDocStat& rStat )
81 *mpDocStat = rStat;
82 mbInitialized = true;
85 void DocumentStatisticsManager::UpdateDocStat( bool bCompleteAsync, bool bFields )
87 if( !mpDocStat->bModified && mbInitialized)
88 return;
90 if (!bCompleteAsync)
92 maStatsUpdateIdle.Stop();
93 while (IncrementalDocStatCalculate(
94 std::numeric_limits<tools::Long>::max(), bFields)) {}
96 else if (IncrementalDocStatCalculate(5000, bFields))
97 maStatsUpdateIdle.Start();
98 else
99 maStatsUpdateIdle.Stop();
102 // returns true while there is more to do
103 bool DocumentStatisticsManager::IncrementalDocStatCalculate(tools::Long nChars, bool bFields)
105 mbInitialized = true;
106 mpDocStat->Reset();
107 mpDocStat->nPara = 0; // default is 1!
109 // This is the inner loop - at least while the paras are dirty.
110 for( SwNodeOffset i = m_rDoc.GetNodes().Count(); i > SwNodeOffset(0) && nChars > 0; )
112 SwNode* pNd = m_rDoc.GetNodes()[ --i ];
113 switch( pNd->GetNodeType() )
115 case SwNodeType::Text:
117 tools::Long const nOldChars(mpDocStat->nChar);
118 SwTextNode *pText = static_cast< SwTextNode * >( pNd );
119 if (pText->CountWords(*mpDocStat, 0, pText->GetText().getLength()))
121 nChars -= (mpDocStat->nChar - nOldChars);
123 break;
125 case SwNodeType::Table: ++mpDocStat->nTable; break;
126 case SwNodeType::Grf: ++mpDocStat->nGrf; break;
127 case SwNodeType::Ole: ++mpDocStat->nOLE; break;
128 case SwNodeType::Section: break;
129 default: break;
133 // #i93174#: notes contain paragraphs that are not nodes
135 SwFieldType * const pPostits( m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit) );
136 std::vector<SwFormatField*> vFields;
137 pPostits->GatherFields(vFields);
138 for(auto pFormatField : vFields)
140 const auto pField = static_cast<SwPostItField const*>(pFormatField->GetField());
141 mpDocStat->nAllPara += pField->GetNumberOfParagraphs();
145 mpDocStat->nPage = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ? m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum() : 0;
146 SetDocStatModified( false );
148 css::uno::Sequence < css::beans::NamedValue > aStat( mpDocStat->nPage ? 8 : 7);
149 auto pStat = aStat.getArray();
150 sal_Int32 n=0;
151 pStat[n].Name = "TableCount";
152 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nTable);
153 pStat[n].Name = "ImageCount";
154 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nGrf);
155 pStat[n].Name = "ObjectCount";
156 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nOLE);
157 if ( mpDocStat->nPage )
159 pStat[n].Name = "PageCount";
160 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nPage);
162 pStat[n].Name = "ParagraphCount";
163 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nPara);
164 pStat[n].Name = "WordCount";
165 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nWord);
166 pStat[n].Name = "CharacterCount";
167 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nChar);
168 pStat[n].Name = "NonWhitespaceCharacterCount";
169 pStat[n++].Value <<= static_cast<sal_Int32>(mpDocStat->nCharExcludingSpaces);
171 // For e.g. autotext documents there is no pSwgInfo (#i79945)
172 SwDocShell* pObjShell(m_rDoc.GetDocShell());
173 if (pObjShell)
175 const uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
176 pObjShell->GetModel(), uno::UNO_QUERY_THROW);
177 const uno::Reference<document::XDocumentProperties> xDocProps(
178 xDPS->getDocumentProperties());
179 // #i96786#: do not set modified flag when updating statistics
180 const bool bDocWasModified( m_rDoc.getIDocumentState().IsModified() );
181 const ModifyBlocker_Impl b(pObjShell);
182 // rhbz#1081176: don't jump to cursor pos because of (temporary)
183 // activation of modified flag triggering move to input position
184 auto aViewGuard(pObjShell->LockAllViews());
185 xDocProps->setDocumentStatistics(aStat);
186 if (!bDocWasModified)
188 m_rDoc.getIDocumentState().ResetModified();
192 // optionally update stat. fields
193 if (bFields)
195 SwFieldType *pType = m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocStat);
196 pType->UpdateFields();
199 return nChars < 0;
202 IMPL_LINK( DocumentStatisticsManager, DoIdleStatsUpdate, Timer *, pIdle, void )
204 if (IncrementalDocStatCalculate(32000))
205 pIdle->Start();
206 SwView* pView = m_rDoc.GetDocShell() ? m_rDoc.GetDocShell()->GetView() : nullptr;
207 if( pView )
208 pView->UpdateDocStats();
211 DocumentStatisticsManager::~DocumentStatisticsManager()
213 maStatsUpdateIdle.Stop();
217 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */