Warning, file /office/calligra/libs/textlayout/IndexGeneratorManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2011 Ko GmbH <cbo@kogmbh.com> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Library General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Library General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "IndexGeneratorManager.h" 0021 0022 #include "KoTextDocumentLayout.h" 0023 #include "ToCGenerator.h" 0024 0025 #include <KoTextDocument.h> 0026 #include <KoParagraphStyle.h> 0027 #include <KoTableOfContentsGeneratorInfo.h> 0028 0029 #include <QTextDocument> 0030 #include <TextLayoutDebug.h> 0031 0032 IndexGeneratorManager::IndexGeneratorManager(QTextDocument *document) 0033 : QObject(document) 0034 , m_document(document) 0035 , m_state(FirstRunNeeded) 0036 { 0037 m_documentLayout = static_cast<KoTextDocumentLayout *>(document->documentLayout()); 0038 0039 // connect to layoutIsDirty 0040 connect(m_documentLayout, SIGNAL(layoutIsDirty()), this, SLOT(requestGeneration())); 0041 0042 // connect to FinishedLayout 0043 connect(m_documentLayout, SIGNAL(finishedLayout()), this, SLOT(startDoneTimer())); 0044 0045 connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(timeout())); 0046 m_updateTimer.setInterval(5000); // after 5 seconds of pause we update 0047 m_updateTimer.setSingleShot(true); 0048 0049 connect(&m_doneTimer, SIGNAL(timeout()), this, SLOT(layoutDone())); 0050 m_doneTimer.setInterval(1000); // after 1 seconds of silence we assume layout is done 0051 m_doneTimer.setSingleShot(true); 0052 } 0053 0054 IndexGeneratorManager::~IndexGeneratorManager() 0055 { 0056 } 0057 0058 IndexGeneratorManager *IndexGeneratorManager::instance(QTextDocument *document) 0059 { 0060 QVariant resource = document->resource(KoTextDocument::IndexGeneratorManager, KoTextDocument::IndexGeneratorManagerUrl); 0061 0062 IndexGeneratorManager *igm = resource.value<IndexGeneratorManager *>(); 0063 0064 if (!igm) { 0065 igm = new IndexGeneratorManager(document); 0066 0067 resource.setValue(igm); 0068 0069 document->addResource(KoTextDocument::IndexGeneratorManager, KoTextDocument::IndexGeneratorManagerUrl, resource); 0070 } 0071 0072 return igm; 0073 } 0074 0075 void IndexGeneratorManager::requestGeneration() 0076 { 0077 if (m_state == FirstRun || m_state == SecondRun) { 0078 return; 0079 } 0080 if (m_document->characterCount() < 2) { 0081 return; 0082 } 0083 m_updateTimer.stop(); 0084 m_updateTimer.start(); 0085 } 0086 0087 void IndexGeneratorManager::startDoneTimer() 0088 { 0089 //we delay acting on the finishedLayout signal by 1 second. This way we 0090 // don't act on it until every header has had a chance to be layouted 0091 // in words (we assume that a new finishedLayout signal will arrive within that 0092 // 1 second) 0093 m_doneTimer.start(); 0094 } 0095 0096 void IndexGeneratorManager::timeout() 0097 { 0098 m_updateTimer.stop(); 0099 m_state = FirstRunNeeded; 0100 m_documentLayout->scheduleLayout(); 0101 } 0102 0103 bool IndexGeneratorManager::generate() 0104 { 0105 if (m_state == Resting || m_state == FirstRunLayouting || m_state == SecondRunLayouting) { 0106 return false; 0107 } 0108 0109 if (m_state == FirstRun || m_state == SecondRun) { 0110 return true; 0111 } 0112 0113 if (m_document->characterCount() < 2) { 0114 return false; 0115 } 0116 0117 if (m_state == FirstRunNeeded) { 0118 m_state = FirstRun; 0119 } 0120 0121 if (m_state == SecondRunNeeded) { 0122 m_state = SecondRun; 0123 } 0124 0125 QTextBlock block = m_document->firstBlock(); 0126 0127 bool success = true; 0128 while (block.isValid()) { 0129 QTextBlockFormat format = block.blockFormat(); 0130 0131 if (format.hasProperty(KoParagraphStyle::TableOfContentsData)) { 0132 QVariant data = format.property(KoParagraphStyle::TableOfContentsData); 0133 KoTableOfContentsGeneratorInfo *tocInfo = data.value<KoTableOfContentsGeneratorInfo *>(); 0134 0135 data = format.property(KoParagraphStyle::GeneratedDocument); 0136 QTextDocument *tocDocument = data.value<QTextDocument *>(); 0137 0138 ToCGenerator *generator = m_generators[tocInfo]; 0139 if (!generator) { 0140 generator = new ToCGenerator(tocDocument, tocInfo); 0141 m_generators[tocInfo] = generator; 0142 } 0143 0144 generator->setBlock(block); 0145 success &= generator->generate(); 0146 } 0147 block = block.next(); 0148 } 0149 0150 0151 if (m_state == FirstRun) { 0152 m_state = FirstRunLayouting; 0153 } 0154 0155 if (m_state == SecondRun) { 0156 if (success) { 0157 m_state = SecondRunLayouting; 0158 } else { 0159 m_state = FirstRunLayouting; 0160 } 0161 } 0162 0163 return false; 0164 } 0165 0166 void IndexGeneratorManager::layoutDone() 0167 { 0168 switch (m_state) { 0169 case FirstRunLayouting: 0170 m_state = SecondRunNeeded; 0171 m_documentLayout->scheduleLayout(); 0172 break; 0173 case SecondRunLayouting: 0174 m_state = Resting; 0175 break; 0176 default: 0177 break; 0178 } 0179 }