File indexing completed on 2024-05-19 16:09:58
0001 /* This file is part of the Calligra project 0002 * Copyright (C) 2005-2010 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2008 Pierre Ducroquet <pinaraf@pinaraf.info> 0004 * Copyright (C) 2008,2011 Sebastian Sauer <mail@dipe.org> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 #include "KWPageManager.h" 0022 #include "KWPageManager_p.h" 0023 #include "KWPageStyle_p.h" 0024 #include "KWPage.h" 0025 #include "KWDocument.h" 0026 0027 #include <KoShape.h> 0028 0029 #include <WordsDebug.h> 0030 0031 #define DEBUG_PAGES 0032 0033 KWPageManagerPrivate::KWPageManagerPrivate() 0034 : lastId(0), 0035 defaultPageStyle(QLatin1String("Standard")) // don't translate, used as identifier! 0036 { 0037 } 0038 0039 qreal KWPageManagerPrivate::pageOffset(int pageNum/*, bool bottom*/) const 0040 { 0041 #if 0 0042 Q_ASSERT(pageNum >= 0); 0043 qreal offset = 0.0; 0044 const qreal totalPadding = padding.top + padding.bottom; 0045 0046 QMap<int, int>::const_iterator iter = pageNumbers.constBegin(); 0047 for (;iter != pageNumbers.constEnd(); ++iter) { 0048 const KWPageManagerPrivate::Page &page = pages[iter.value()]; 0049 if (page.pageSide == KWPage::PageSpread && iter.key() % 2 == 1) 0050 continue; 0051 if (iter.key() == pageNum) { 0052 if (bottom) 0053 offset += page.style.pageLayout().height; 0054 break; 0055 } 0056 offset += page.style.priv()->pageLayout.height + totalPadding; 0057 } 0058 return offset; 0059 #else 0060 //Q_ASSERT(pageOffsets.contains(pageNum)); 0061 qreal offset = pageOffsets.value(pageNum); 0062 //debugWords << "pageNum=" << pageNum << "offset=" << offset; 0063 return offset; 0064 #endif 0065 } 0066 0067 void KWPageManagerPrivate::setPageOffset(int pageNum, qreal offset) 0068 { 0069 pageOffsets[pageNum] = offset; 0070 } 0071 0072 void KWPageManagerPrivate::setVisiblePageNumber(int pageId, int newPageNumber) 0073 { 0074 #if 0 0075 if (pageNumbers.isEmpty() || ! pages.contains(pageId)) 0076 return; 0077 const int oldPageNumber = pages[pageId].pageNumber; 0078 int diff = newPageNumber - oldPageNumber; 0079 int from = oldPageNumber; 0080 int to = newPageNumber; 0081 if (from > to) 0082 qSwap(from, to); 0083 0084 QMap<int, int> oldPageNumbers = pageNumbers; // backup 0085 QHash<int, Page> oldPages = pages; // backup 0086 0087 pageNumbers.clear(); 0088 pages.clear(); 0089 0090 foreach (int id, oldPages.keys()) { 0091 Page page = oldPages[id]; 0092 if (diff < 0 && page.pageNumber >= from && page.pageNumber < to) { 0093 warnWords << "you requested to change the page number to a number that already exist, all will end soon"; 0094 return; 0095 } 0096 #ifdef DEBUG_PAGES 0097 const int oldPageNumber = page.pageNumber; // debug only 0098 #endif 0099 if (page.pageNumber >= from) 0100 page.pageNumber += diff; 0101 #ifdef DEBUG_PAGES 0102 debugWords << "adjusting page number from" << oldPageNumber << "to" << page.pageNumber << "side" << page.pageSide; 0103 #endif 0104 if (page.pageSide == KWPage::PageSpread) { 0105 if (page.pageNumber % 2 == 1) { // pagespreads can only be on even pageNumbers 0106 page.pageNumber++; 0107 diff++; 0108 } 0109 pageNumbers.insert(page.pageNumber + 1, id); 0110 } 0111 else { 0112 page.pageSide = page.pageNumber % 2 == 0 ? KWPage::Left : KWPage::Right; 0113 } 0114 pageNumbers.insert(page.pageNumber, id); 0115 pages.insert(id, page); 0116 } 0117 0118 Q_ASSERT(pages.count() == oldPages.count()); // don't loose anything :) 0119 #else 0120 if (newPageNumber >= 0) 0121 visiblePageNumbers[pageId] = newPageNumber; 0122 else 0123 visiblePageNumbers.remove(pageId); 0124 #endif 0125 } 0126 0127 void KWPageManagerPrivate::insertPage(const Page &newPage) 0128 { 0129 #ifdef DEBUG_PAGES 0130 debugWords << "pageNumber=" << newPage.pageNumber; 0131 #endif 0132 0133 // increase the pagenumbers of pages following the pageNumber 0134 if (!pageNumbers.isEmpty()) { 0135 const QMap<int, int> numbers = pageNumbers; 0136 QMap<int, int>::ConstIterator iter = numbers.end(); 0137 do { 0138 --iter; 0139 0140 if (iter.key() < newPage.pageNumber) 0141 break; 0142 KWPageManagerPrivate::Page page = pages[iter.value()]; 0143 pageNumbers.remove(iter.key()); 0144 page.pageNumber += 1; 0145 pages.insert(iter.value(), page); 0146 pageNumbers.insert(iter.key() + 1, iter.value()); 0147 } while (iter != numbers.begin()); 0148 } 0149 0150 pages.insert(++lastId, newPage); 0151 Q_ASSERT(! pageNumbers.contains(newPage.pageNumber)); 0152 pageNumbers.insert(newPage.pageNumber, lastId); 0153 } 0154 0155 /////////// 0156 0157 KWPageManager::KWPageManager() 0158 : d (new KWPageManagerPrivate()) 0159 { 0160 addPageStyle(d->defaultPageStyle); 0161 } 0162 0163 KWPageManager::~KWPageManager() 0164 { 0165 delete d; 0166 } 0167 0168 int KWPageManager::pageNumber(const QPointF &point) const 0169 { 0170 qreal startOfpage = 0.0; 0171 int answer = -1; 0172 QMap<int, int>::const_iterator iter = d->pageNumbers.constBegin(); 0173 for (;iter != d->pageNumbers.constEnd(); ++iter) { 0174 const KWPageManagerPrivate::Page page = d->pages[iter.value()]; 0175 startOfpage += page.style.pageLayout().height + d->padding.top + d->padding.bottom; 0176 answer = iter.key(); 0177 if (startOfpage >= point.y()) 0178 break; 0179 } 0180 return answer; 0181 } 0182 0183 int KWPageManager::pageNumber(const KoShape *shape) const 0184 { 0185 return pageNumber(shape->absolutePosition()); 0186 } 0187 0188 int KWPageManager::pageNumber(const qreal y) const 0189 { 0190 return pageNumber(QPointF(0, y)); 0191 } 0192 0193 int KWPageManager::pageCount() const 0194 { 0195 int count = 0; 0196 QHash<int,KWPageManagerPrivate::Page>::const_iterator iter = d->pages.constBegin(); 0197 while (iter != d->pages.constEnd()) { 0198 ++count; 0199 ++iter; 0200 } 0201 return count; 0202 } 0203 0204 KWPage KWPageManager::page(int pageNum) const 0205 { 0206 if (d->pageNumbers.contains(pageNum)) 0207 return KWPage(d, d->pageNumbers.value(pageNum)); 0208 0209 #ifdef DEBUG_PAGES 0210 warnWords << "KWPageManager::page(" << pageNum << ") failed; Requested page does not exist"; 0211 #endif 0212 return KWPage(); 0213 } 0214 0215 KWPage KWPageManager::page(const KoShape *shape) const 0216 { 0217 return page(pageNumber(shape)); 0218 } 0219 0220 KWPage KWPageManager::page(const QPointF &point) const 0221 { 0222 return page(pageNumber(point)); 0223 } 0224 0225 KWPage KWPageManager::page(qreal y) const 0226 { 0227 return page(pageNumber(y)); 0228 } 0229 0230 KWPage KWPageManager::insertPage(int pageNumber, const KWPageStyle &pageStyle) 0231 { 0232 if (pageNumber <= 0 || d->pages.isEmpty() || pageNumber > last().pageNumber()) 0233 return appendPage(pageStyle); 0234 0235 #ifdef DEBUG_PAGES 0236 debugWords << "pageNumber=" << pageNumber << "pageStyle=" << (pageStyle.isValid() ? pageStyle.name() : QString()); 0237 #endif 0238 0239 KWPageManagerPrivate::Page newPage; 0240 newPage.style = pageStyle; 0241 0242 KWPage prevPage = page(pageNumber - 1); 0243 if (prevPage.isValid()) { 0244 if (! newPage.style.isValid()) 0245 newPage.style = prevPage.pageStyle(); 0246 } 0247 0248 if (! newPage.style.isValid()) 0249 newPage.style = defaultPageStyle(); 0250 newPage.pageNumber = pageNumber; 0251 if (newPage.pageNumber % 2 == 0) { 0252 newPage.pageSide = KWPage::Left; 0253 } else { 0254 newPage.pageSide = KWPage::Right; 0255 } 0256 0257 d->insertPage(newPage); 0258 0259 return KWPage(d, d->lastId); 0260 } 0261 0262 KWPage KWPageManager::appendPage(const KWPageStyle &pageStyle) 0263 { 0264 KWPageManagerPrivate::Page page; 0265 0266 if (! d->pages.isEmpty()) { 0267 QMap<int, int>::ConstIterator end = d->pageNumbers.constEnd(); 0268 --end; // last one is one before the imaginary 'end' 0269 KWPageManagerPrivate::Page lastPage = d->pages[end.value()]; 0270 page = lastPage; 0271 ++page.pageNumber; 0272 } else { 0273 page.pageNumber = 1; 0274 } 0275 0276 if (pageStyle.isValid()) { 0277 page.style = pageStyle; 0278 } else { 0279 if (page.style.isValid()) { 0280 QString nextPageMasterStyleName = page.style.nextStyleName(); 0281 KWPageStyle nextPageMasterStyle = this->pageStyle(nextPageMasterStyleName); 0282 if (nextPageMasterStyle.isValid()) { 0283 page.style = nextPageMasterStyle; 0284 } 0285 } 0286 } 0287 if (!page.style.isValid()) { 0288 page.style = defaultPageStyle(); 0289 } 0290 0291 if (page.pageNumber % 2 == 0) { 0292 page.pageSide = KWPage::Left; 0293 } else { 0294 page.pageSide = KWPage::Right; 0295 } 0296 0297 d->pages.insert(++d->lastId, page); 0298 d->pageNumbers.insert(page.pageNumber, d->lastId); 0299 0300 #ifdef DEBUG_PAGES 0301 debugWords << "pageNumber=" << page.pageNumber << "pageCount=" << pageCount() << "pageStyle=" << (pageStyle.isValid() ? pageStyle.name() : QString()); 0302 #endif 0303 0304 return KWPage(d, d->lastId); 0305 } 0306 0307 qreal KWPageManager::topOfPage(int pageNum) const 0308 { 0309 return d->pageOffset(pageNum); 0310 } 0311 0312 qreal KWPageManager::bottomOfPage(int pageNum) const 0313 { 0314 KWPage p = page(pageNum); 0315 Q_ASSERT(p.isValid()); 0316 return d->pageOffset(pageNum) + p.height(); 0317 } 0318 0319 void KWPageManager::removePage(int pageNumber) 0320 { 0321 removePage(page(pageNumber)); 0322 } 0323 0324 void KWPageManager::removePage(const KWPage &page) 0325 { 0326 Q_ASSERT(page.isValid()); 0327 debugWords << page.pageNumber(); 0328 0329 const int removedPageNumber = page.pageNumber(); 0330 d->pages.remove(d->pageNumbers[removedPageNumber]); 0331 d->visiblePageNumbers.remove(removedPageNumber); 0332 0333 // decrease the pagenumbers of pages following the pageNumber 0334 const QMap<int, int> pageNumbers = d->pageNumbers; 0335 QMap<int, int>::ConstIterator iter = pageNumbers.begin(); 0336 while (iter != pageNumbers.end()) { 0337 if (iter.key() < removedPageNumber) { 0338 // don't touch those 0339 } else if (iter.key() > removedPageNumber) { 0340 KWPageManagerPrivate::Page page = d->pages[iter.value()]; 0341 d->pageNumbers.remove(iter.key()); 0342 page.pageNumber--; 0343 d->pages.insert(iter.value(), page); 0344 d->pageNumbers.insert(page.pageNumber, iter.value()); 0345 } else { 0346 d->pageNumbers.remove(iter.key()); 0347 } 0348 ++iter; 0349 } 0350 0351 #ifdef DEBUG_PAGES 0352 debugWords << "pageNumber=" << removedPageNumber << "pageCount=" << pageCount(); 0353 #endif 0354 } 0355 0356 QVector<KWPage> KWPageManager::pages(const QString &pageStyle) const 0357 { 0358 QVector<KWPage> answer; 0359 const bool checkForStyle = !pageStyle.isEmpty(); 0360 QHash<int, KWPageManagerPrivate::Page>::ConstIterator it = d->pages.constBegin(); 0361 QHash<int, KWPageManagerPrivate::Page>::ConstIterator end = d->pages.constEnd(); 0362 for(; it != end; ++it) { 0363 if (checkForStyle && it.value().style.name() != pageStyle) 0364 continue; 0365 answer << KWPage(d, it.key()); 0366 } 0367 std::sort(answer.begin(), answer.end()); 0368 return answer; 0369 } 0370 0371 QHash<QString, KWPageStyle> KWPageManager::pageStyles() const 0372 { 0373 return d->pageStyles; 0374 } 0375 0376 KWPageStyle KWPageManager::pageStyle(const QString &name) const 0377 { 0378 if (d->pageStyles.contains(name)) 0379 return d->pageStyles[name]; 0380 if (d->pageStyleNames.contains(name)) 0381 return d->pageStyles[d->pageStyleNames[name]]; 0382 return KWPageStyle(); 0383 } 0384 0385 void KWPageManager::addPageStyle(const KWPageStyle &pageStyle) 0386 { 0387 Q_ASSERT(!pageStyle.name().isEmpty()); 0388 Q_ASSERT(pageStyle.isValid()); 0389 d->pageStyles.insert(pageStyle.name(), pageStyle); 0390 if (!pageStyle.displayName().isEmpty()) 0391 d->pageStyleNames.insert(pageStyle.displayName(), pageStyle.name()); 0392 } 0393 0394 void KWPageManager::removePageStyle(const KWPageStyle &pageStyle) 0395 { 0396 KWPageStyle style = d->pageStyles.value(pageStyle.name()); 0397 Q_ASSERT(style == pageStyle); 0398 d->pageStyles.remove(pageStyle.name()); 0399 Q_ASSERT(!d->pageStyleNames.contains(pageStyle.displayName()) || d->pageStyleNames[pageStyle.displayName()] == pageStyle.name()); 0400 d->pageStyleNames.remove(pageStyle.displayName()); 0401 } 0402 0403 KWPageStyle KWPageManager::defaultPageStyle() const 0404 { 0405 return d->defaultPageStyle; 0406 } 0407 0408 void KWPageManager::clearPageStyles() 0409 { 0410 d->pageStyles.clear(); 0411 d->pageStyleNames.clear(); 0412 d->defaultPageStyle = KWPageStyle(QLatin1String("Standard")); // don't translate, used as identifier! 0413 addPageStyle(d->defaultPageStyle); 0414 } 0415 0416 const KWPage KWPageManager::begin() const 0417 { 0418 if (d->pages.isEmpty() || d->pageNumbers.empty()) 0419 return KWPage(); 0420 return KWPage(d, d->pageNumbers.constBegin().value()); 0421 } 0422 0423 const KWPage KWPageManager::last() const 0424 { 0425 if (d->pages.isEmpty() || d->pageNumbers.empty()) 0426 return KWPage(); 0427 QMap<int, int>::ConstIterator end = d->pageNumbers.constEnd(); 0428 --end; // last one is one before the imaginary 'end' 0429 return KWPage(d, end.value()); 0430 } 0431 0432 KWPage KWPageManager::begin() 0433 { 0434 if (d->pages.isEmpty() || d->pageNumbers.empty()) 0435 return KWPage(); 0436 return KWPage(d, d->pageNumbers.begin().value()); 0437 } 0438 0439 KWPage KWPageManager::last() 0440 { 0441 if (d->pages.isEmpty() || d->pageNumbers.empty()) 0442 return KWPage(); 0443 QMap<int, int>::ConstIterator end = d->pageNumbers.constEnd(); 0444 --end; // last one is one before the imaginary 'end' 0445 return KWPage(d, end.value()); 0446 } 0447 0448 KoInsets KWPageManager::padding() const 0449 { 0450 return d->padding; 0451 } 0452 0453 void KWPageManager::setPadding(const KoInsets &padding) 0454 { 0455 d->padding = padding; 0456 }