Warning, file /office/calligra/libs/pageapp/KoPADocument.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) 2006-2011 Thorsten Zachmann <zachmann@kde.org> 0003 Copyright (C) 2007 Thomas Zander <zander@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KoPADocument.h" 0022 0023 #include "KoPAView.h" 0024 #include "KoPAPage.h" 0025 #include "KoPAMasterPage.h" 0026 #include "KoPASavingContext.h" 0027 #include "KoPALoadingContext.h" 0028 #include "KoPAPageProvider.h" 0029 #include "commands/KoPAPageDeleteCommand.h" 0030 0031 #include <KoStore.h> 0032 #include <KoXmlWriter.h> 0033 #include <KoOdfReadStore.h> 0034 #include <KoOdfWriteStore.h> 0035 #include <KoOdfLoadingContext.h> 0036 #include <KoOasisSettings.h> 0037 #include <KoStoreDevice.h> 0038 #include <KoGenStyles.h> 0039 #include <KoShapeController.h> 0040 #include <KoDocumentResourceManager.h> 0041 #include <KoGridData.h> 0042 #include <KoGuidesData.h> 0043 #include <KoText.h> 0044 #include <KoTextSharedLoadingData.h> 0045 #include <KoInlineTextObjectManager.h> 0046 #include <KoStyleManager.h> 0047 #include <KoXmlNS.h> 0048 #include <KoProgressUpdater.h> 0049 #include <KoUpdater.h> 0050 #include <KoDocumentInfo.h> 0051 #include <KoVariableManager.h> 0052 #include <KoPart.h> 0053 #include <KoUnit.h> 0054 0055 #include <PageAppDebug.h> 0056 #include <kconfig.h> 0057 #include <kconfiggroup.h> 0058 #include <KSharedConfig> 0059 0060 #include <QPainter> 0061 0062 class Q_DECL_HIDDEN KoPADocument::Private 0063 { 0064 public: 0065 QList<KoPAPageBase*> pages; 0066 QList<KoPAPageBase*> masterPages; 0067 KoInlineTextObjectManager *inlineTextObjectManager; 0068 bool rulersVisible; 0069 KoPAPageProvider *pageProvider; 0070 QPointer<KoUpdater> odfProgressUpdater; 0071 QPointer<KoUpdater> odfMasterPageProgressUpdater; 0072 QPointer<KoUpdater> odfPageProgressUpdater; 0073 QString defaultStylesResourcePath; 0074 bool showPageMargins; 0075 }; 0076 0077 KoPADocument::KoPADocument(KoPart *part) 0078 : KoDocument(part), 0079 d(new Private()) 0080 { 0081 d->inlineTextObjectManager = resourceManager()->resource(KoText::InlineTextObjectManager).value<KoInlineTextObjectManager*>(); 0082 // Do not assert, it should be possible to run wo InlineTextObjectManager 0083 // This is used by unit tests, so these will fail 0084 // Q_ASSERT(d->inlineTextObjectManager); 0085 if (d->inlineTextObjectManager) { 0086 connect(documentInfo(), SIGNAL(infoUpdated(QString,QString)), 0087 d->inlineTextObjectManager, SLOT(documentInformationUpdated(QString,QString))); 0088 } else { 0089 warnPageApp<<"Could not find resource 'KoText::InlineTextObjectManager'"; 0090 } 0091 d->rulersVisible = false; 0092 resourceManager()->setUndoStack(undoStack()); 0093 resourceManager()->setOdfDocument(this); 0094 // this is needed so the text shape have a shape controller set when loaded, it is needed for copy and paste 0095 new KoShapeController(0, this); 0096 QVariant variant; 0097 d->pageProvider = new KoPAPageProvider(); 0098 variant.setValue<void*>(d->pageProvider); 0099 resourceManager()->setResource(KoText::PageProvider, variant); 0100 loadConfig(); 0101 } 0102 0103 KoPADocument::~KoPADocument() 0104 { 0105 saveConfig(); 0106 qDeleteAll( d->pages ); 0107 qDeleteAll( d->masterPages ); 0108 delete d->pageProvider; 0109 delete d; 0110 } 0111 0112 QPixmap KoPADocument::generatePreview(const QSize& size) 0113 { 0114 // use first page as preview for all pages 0115 KoPAPageBase *page = pageByIndex(0, false); 0116 Q_ASSERT( page ); 0117 return pageThumbnail(page, size); 0118 } 0119 0120 void KoPADocument::paintContent( QPainter &painter, const QRect &rect) 0121 { 0122 KoPAPageBase * page = pageByIndex( 0, false ); 0123 Q_ASSERT( page ); 0124 QPixmap thumbnail( pageThumbnail( page, rect.size() ) ); 0125 painter.drawPixmap( rect, thumbnail ); 0126 } 0127 0128 bool KoPADocument::loadXML( const KoXmlDocument & doc, KoStore * ) 0129 { 0130 Q_UNUSED( doc ); 0131 0132 //Perhaps not necessary if we use filter import/export for old file format 0133 //only needed as it is in the base class will be removed. 0134 return true; 0135 } 0136 0137 void KoPADocument::setupOpenFileSubProgress() 0138 { 0139 if (progressUpdater()) { 0140 d->odfProgressUpdater = progressUpdater()->startSubtask(1, "KoPADocument::loadOdf"); 0141 d->odfMasterPageProgressUpdater = progressUpdater()->startSubtask(1, "KoPADocument::loadOdfMasterPages"); 0142 d->odfPageProgressUpdater = progressUpdater()->startSubtask(5, "KoPADocument::loadOdfPages"); 0143 } 0144 } 0145 0146 bool KoPADocument::loadOdf( KoOdfReadStore & odfStore) 0147 { 0148 updateDocumentURL(); 0149 0150 if (d->odfProgressUpdater) { 0151 d->odfProgressUpdater->setProgress(0); 0152 } 0153 KoOdfLoadingContext loadingContext( odfStore.styles(), odfStore.store(), defaultStylesResourcePath()); 0154 KoPALoadingContext paContext(loadingContext, resourceManager()); 0155 0156 KoXmlElement content = odfStore.contentDoc().documentElement(); 0157 KoXmlElement realBody ( KoXml::namedItemNS( content, KoXmlNS::office, "body" ) ); 0158 0159 if ( realBody.isNull() ) { 0160 errorPageApp << "No body tag found!" << endl; 0161 return false; 0162 } 0163 0164 KoXmlElement body = KoXml::namedItemNS(realBody, KoXmlNS::office, odfTagName( false )); 0165 0166 if ( body.isNull() ) { 0167 errorPageApp << "No office:" << odfTagName( false ) << " tag found!" << endl; 0168 return false; 0169 } 0170 0171 // Load text styles before the corresponding text shapes try to use them! 0172 KoTextSharedLoadingData * sharedData = new KoTextSharedLoadingData(); 0173 paContext.addSharedData( KOTEXT_SHARED_LOADING_ID, sharedData ); 0174 KoStyleManager *styleManager = resourceManager()->resource(KoText::StyleManager).value<KoStyleManager*>(); 0175 0176 sharedData->loadOdfStyles(paContext, styleManager); 0177 if (d->odfProgressUpdater) { 0178 d->odfProgressUpdater->setProgress(20); 0179 } 0180 0181 d->masterPages = loadOdfMasterPages( odfStore.styles().masterPages(), paContext ); 0182 if ( !loadOdfProlog( body, paContext ) ) { 0183 return false; 0184 } 0185 d->pages = loadOdfPages( body, paContext ); 0186 0187 // create pages if there are none 0188 if (d->masterPages.empty()) { 0189 d->masterPages.append(newMasterPage()); 0190 } 0191 if (d->pages.empty()) { 0192 d->pages.append(newPage(static_cast<KoPAMasterPage*>(d->masterPages.first()))); 0193 } 0194 0195 if ( !loadOdfEpilogue( body, paContext ) ) { 0196 return false; 0197 } 0198 0199 loadOdfDocumentStyles( paContext ); 0200 0201 if ( d->pages.size() > 1 ) { 0202 emit actionsPossible(KoPAView::ActionDeletePage, false); 0203 } 0204 0205 updatePageCount(); 0206 0207 loadOdfSettings(odfStore.settingsDoc()); 0208 0209 if (d->odfProgressUpdater) { 0210 d->odfProgressUpdater->setProgress(100); 0211 } 0212 return true; 0213 } 0214 0215 bool KoPADocument::saveOdf( SavingContext & documentContext ) 0216 { 0217 KoXmlWriter* contentWriter = documentContext.odfStore.contentWriter(); 0218 if ( !contentWriter ) 0219 return false; 0220 0221 KoGenStyles mainStyles; 0222 KoXmlWriter * bodyWriter = documentContext.odfStore.bodyWriter(); 0223 0224 KoPASavingContext paContext(*bodyWriter, mainStyles, documentContext.embeddedSaver, 1); 0225 0226 saveOdfDocumentStyles( paContext ); 0227 0228 bodyWriter->startElement( "office:body" ); 0229 bodyWriter->startElement( odfTagName( true ) ); 0230 0231 if ( !saveOdfProlog( paContext ) ) { 0232 return false; 0233 } 0234 0235 if ( !saveOdfPages( paContext, d->pages, d->masterPages ) ) { 0236 return false; 0237 } 0238 0239 if ( ! saveOdfEpilogue( paContext ) ) { 0240 return false; 0241 } 0242 0243 bodyWriter->endElement(); // office:odfTagName() 0244 bodyWriter->endElement(); // office:body 0245 0246 mainStyles.saveOdfStyles( KoGenStyles::DocumentAutomaticStyles, contentWriter ); 0247 0248 documentContext.odfStore.closeContentWriter(); 0249 0250 //add manifest line for content.xml 0251 documentContext.odfStore.manifestWriter()->addManifestEntry( "content.xml", "text/xml" ); 0252 0253 if ( ! mainStyles.saveOdfStylesDotXml( documentContext.odfStore.store(), documentContext.odfStore.manifestWriter() ) ) { 0254 return false; 0255 } 0256 0257 KoStore * store = documentContext.odfStore.store(); 0258 if ( ! store->open( "settings.xml" ) ) { 0259 return false; 0260 } 0261 0262 saveOdfSettings( store ); 0263 0264 if ( ! store->close() ) { 0265 return false; 0266 } 0267 0268 documentContext.odfStore.manifestWriter()->addManifestEntry( "settings.xml", "text/xml" ); 0269 0270 //setModified( false ); 0271 0272 bool retval = paContext.saveDataCenter( documentContext.odfStore.store(), documentContext.odfStore.manifestWriter() ); 0273 0274 if (retval) { 0275 updateDocumentURL(); 0276 } 0277 0278 return retval; 0279 } 0280 0281 QList<KoPAPageBase *> KoPADocument::loadOdfMasterPages( const QHash<QString, KoXmlElement*> masterStyles, KoPALoadingContext & context ) 0282 { 0283 context.odfLoadingContext().setUseStylesAutoStyles( true ); 0284 QList<KoPAPageBase *> masterPages; 0285 0286 if (d->odfMasterPageProgressUpdater) { 0287 d->odfMasterPageProgressUpdater->setProgress(0); 0288 } 0289 0290 QHash<QString, KoXmlElement*>::const_iterator it( masterStyles.constBegin() ); 0291 int count = 0; 0292 for ( ; it != masterStyles.constEnd(); ++it ) 0293 { 0294 KoPAMasterPage * masterPage = newMasterPage(); 0295 masterPage->loadOdf( *( it.value() ), context ); 0296 masterPages.append( masterPage ); 0297 context.addMasterPage( it.key(), masterPage ); 0298 if (d->odfMasterPageProgressUpdater) { 0299 int progress = 100 * ++count / masterStyles.size(); 0300 d->odfMasterPageProgressUpdater->setProgress(progress); 0301 } 0302 } 0303 context.odfLoadingContext().setUseStylesAutoStyles( false ); 0304 if (d->odfMasterPageProgressUpdater) { 0305 d->odfMasterPageProgressUpdater->setProgress(100); 0306 } 0307 return masterPages; 0308 } 0309 0310 QList<KoPAPageBase *> KoPADocument::loadOdfPages( const KoXmlElement & body, KoPALoadingContext & context ) 0311 { 0312 if (d->masterPages.isEmpty()) { // we require at least one master page. Auto create one if the doc was faulty. 0313 d->masterPages << newMasterPage(); 0314 } 0315 0316 int childNodesCount = 0; 0317 int childCount = 0; 0318 if (d->odfPageProgressUpdater) { 0319 d->odfPageProgressUpdater->setProgress(0); 0320 childNodesCount = body.childNodesCount(); 0321 } 0322 0323 QList<KoPAPageBase *> pages; 0324 KoXmlElement element; 0325 forEachElement( element, body ) 0326 { 0327 if ( element.tagName() == "page" && element.namespaceURI() == KoXmlNS::draw ) { 0328 KoPAPage *page = newPage(static_cast<KoPAMasterPage*>(d->masterPages.first())); 0329 page->loadOdf( element, context ); 0330 pages.append( page ); 0331 // in case the page name is pageX where X is the page number remove the name as this is 0332 // remove the page name and show the default page name like Slide X or Page X. 0333 if (page->name() == QString("page%1").arg(pages.size())) { 0334 page->setName(""); 0335 } 0336 } 0337 0338 if (d->odfPageProgressUpdater) { 0339 int progress = 100 * ++childCount / childNodesCount; 0340 d->odfPageProgressUpdater->setProgress(progress); 0341 } 0342 } 0343 if (d->odfPageProgressUpdater) { 0344 d->odfPageProgressUpdater->setProgress(100); 0345 } 0346 return pages; 0347 } 0348 0349 bool KoPADocument::loadOdfEpilogue( const KoXmlElement & body, KoPALoadingContext & context ) 0350 { 0351 Q_UNUSED( body ); 0352 Q_UNUSED( context ); 0353 return true; 0354 } 0355 0356 bool KoPADocument::loadOdfProlog( const KoXmlElement & body, KoPALoadingContext & context ) 0357 { 0358 Q_UNUSED( body ); 0359 Q_UNUSED( context ); 0360 0361 // Load user defined variable declarations 0362 if (KoVariableManager *variableManager = inlineTextObjectManager()->variableManager()) { 0363 variableManager->loadOdf(body); 0364 } 0365 0366 return true; 0367 } 0368 0369 bool KoPADocument::saveOdfPages( KoPASavingContext &paContext, QList<KoPAPageBase *> &pages, QList<KoPAPageBase *> &masterPages ) 0370 { 0371 paContext.addOption( KoPASavingContext::DrawId ); 0372 paContext.addOption( KoPASavingContext::AutoStyleInStyleXml ); 0373 0374 // save master pages 0375 foreach( KoPAPageBase *page, masterPages ) { 0376 if ( paContext.isSetClearDrawIds() ) { 0377 paContext.clearXmlIds("shape"); 0378 } 0379 page->saveOdf( paContext ); 0380 } 0381 0382 paContext.removeOption( KoPASavingContext::AutoStyleInStyleXml ); 0383 0384 // save pages 0385 foreach ( KoPAPageBase *page, pages ) { 0386 page->saveOdf( paContext ); 0387 paContext.incrementPage(); 0388 } 0389 0390 return true; 0391 } 0392 0393 bool KoPADocument::saveOdfProlog( KoPASavingContext & paContext ) 0394 { 0395 Q_UNUSED( paContext ); 0396 0397 // Save user defined variable declarations 0398 if (KoVariableManager *variableManager = inlineTextObjectManager()->variableManager()) { 0399 variableManager->saveOdf(&paContext.xmlWriter()); 0400 } 0401 0402 return true; 0403 } 0404 0405 bool KoPADocument::saveOdfEpilogue( KoPASavingContext & paContext ) 0406 { 0407 Q_UNUSED( paContext ); 0408 return true; 0409 } 0410 0411 bool KoPADocument::saveOdfSettings( KoStore * store ) 0412 { 0413 KoStoreDevice settingsDev( store ); 0414 KoXmlWriter * settingsWriter = KoOdfWriteStore::createOasisXmlWriter( &settingsDev, "office:document-settings" ); 0415 0416 settingsWriter->startElement("office:settings"); 0417 settingsWriter->startElement("config:config-item-set"); 0418 settingsWriter->addAttribute("config:name", "view-settings"); 0419 0420 saveUnitOdf(settingsWriter); 0421 0422 settingsWriter->endElement(); // config:config-item-set 0423 0424 settingsWriter->startElement("config:config-item-set"); 0425 settingsWriter->addAttribute("config:name", "ooo:view-settings"); 0426 settingsWriter->startElement("config:config-item-map-indexed" ); 0427 settingsWriter->addAttribute("config:name", "Views" ); 0428 settingsWriter->startElement("config:config-item-map-entry" ); 0429 0430 guidesData().saveOdfSettings( *settingsWriter ); 0431 gridData().saveOdfSettings( *settingsWriter ); 0432 0433 settingsWriter->endElement(); // config:config-item-map-entry 0434 settingsWriter->endElement(); // config:config-item-map-indexed 0435 settingsWriter->endElement(); // config:config-item-set 0436 0437 settingsWriter->endElement(); // office:settings 0438 settingsWriter->endElement(); // office:document-settings 0439 0440 settingsWriter->endDocument(); 0441 0442 delete settingsWriter; 0443 0444 return true; 0445 } 0446 0447 void KoPADocument::loadOdfSettings( const KoXmlDocument & settingsDoc ) 0448 { 0449 if ( settingsDoc.isNull() ) { 0450 return ; // not an error if some file doesn't have settings.xml 0451 } 0452 0453 KoOasisSettings settings( settingsDoc ); 0454 KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" ); 0455 if ( !viewSettings.isNull() ) { 0456 setUnit(KoUnit::fromSymbol(viewSettings.parseConfigItemString("unit"))); 0457 // FIXME: add other config here. 0458 } 0459 0460 guidesData().loadOdfSettings( settingsDoc ); 0461 gridData().loadOdfSettings( settingsDoc ); 0462 } 0463 0464 void KoPADocument::saveOdfDocumentStyles( KoPASavingContext & context ) 0465 { 0466 KoStyleManager *styleManager = resourceManager()->resource(KoText::StyleManager).value<KoStyleManager*>(); 0467 Q_ASSERT( styleManager ); 0468 styleManager->saveOdf(context); 0469 } 0470 0471 bool KoPADocument::loadOdfDocumentStyles( KoPALoadingContext & context ) 0472 { 0473 Q_UNUSED( context ); 0474 return true; 0475 } 0476 0477 KoPAPageBase* KoPADocument::pageByIndex( int index, bool masterPage ) const 0478 { 0479 if ( masterPage ) 0480 { 0481 return d->masterPages.at( index ); 0482 } 0483 else 0484 { 0485 return d->pages.at( index ); 0486 } 0487 } 0488 0489 int KoPADocument::pageIndex( KoPAPageBase * page ) const 0490 { 0491 const QList<KoPAPageBase*>& pages = dynamic_cast<KoPAMasterPage *>( page ) ? d->masterPages : d->pages; 0492 return pages.indexOf( page ); 0493 } 0494 0495 KoPAPageBase* KoPADocument::pageByNavigation( KoPAPageBase * currentPage, KoPageApp::PageNavigation pageNavigation ) const 0496 { 0497 const QList<KoPAPageBase*>& pages = dynamic_cast<KoPAMasterPage *>( currentPage ) ? d->masterPages : d->pages; 0498 0499 Q_ASSERT( ! pages.isEmpty() ); 0500 0501 KoPAPageBase * newPage = currentPage; 0502 0503 switch ( pageNavigation ) 0504 { 0505 case KoPageApp::PageFirst: 0506 newPage = pages.first(); 0507 break; 0508 case KoPageApp::PageLast: 0509 newPage = pages.last(); 0510 break; 0511 case KoPageApp::PagePrevious: 0512 { 0513 int index = pages.indexOf( currentPage ) - 1; 0514 if ( index >= 0 ) 0515 { 0516 newPage = pages.at( index ); 0517 } 0518 } break; 0519 case KoPageApp::PageNext: 0520 // fall through 0521 default: 0522 { 0523 int index = pages.indexOf( currentPage ) + 1; 0524 if ( index < pages.size() ) 0525 { 0526 newPage = pages.at( index ); 0527 } 0528 break; 0529 } 0530 } 0531 0532 return newPage; 0533 } 0534 0535 void KoPADocument::addShape( KoShape * shape ) 0536 { 0537 if(!shape) 0538 return; 0539 0540 // the KoShapeController sets the active layer as parent 0541 KoPAPageBase *page(pageByShape(shape)); 0542 0543 emit shapeAdded(shape); 0544 0545 // it can happen in Stage notes view that there is no page 0546 if ( page ) { 0547 page->shapeAdded( shape ); 0548 postAddShape( page, shape ); 0549 } 0550 } 0551 0552 void KoPADocument::postAddShape( KoPAPageBase * page, KoShape * shape ) 0553 { 0554 Q_UNUSED( page ); 0555 Q_UNUSED( shape ); 0556 } 0557 0558 void KoPADocument::removeShape(KoShape *shape) 0559 { 0560 if (!shape) 0561 return; 0562 0563 KoPAPageBase *page(pageByShape(shape)); 0564 0565 emit shapeRemoved(shape); 0566 0567 page->shapeRemoved(shape); 0568 postRemoveShape(page, shape); 0569 } 0570 0571 void KoPADocument::postRemoveShape( KoPAPageBase * page, KoShape * shape ) 0572 { 0573 Q_UNUSED( page ); 0574 Q_UNUSED( shape ); 0575 } 0576 0577 void KoPADocument::removePage( KoPAPageBase * page ) 0578 { 0579 KoPAPageDeleteCommand * command = new KoPAPageDeleteCommand( this, page ); 0580 pageRemoved( page, command ); 0581 addCommand( command ); 0582 } 0583 0584 0585 void KoPADocument::removePages(QList<KoPAPageBase *> &pages) 0586 { 0587 KoPAPageDeleteCommand *command = new KoPAPageDeleteCommand(this, pages); 0588 addCommand(command); 0589 } 0590 0591 void KoPADocument::pageRemoved( KoPAPageBase * page, KUndo2Command * parent ) 0592 { 0593 Q_UNUSED( page ); 0594 Q_UNUSED( parent ); 0595 } 0596 0597 KoPAPageBase * KoPADocument::pageByShape( KoShape * shape ) const 0598 { 0599 KoShape * parent = shape; 0600 KoPAPageBase * page = 0; 0601 while ( !page && ( parent = parent->parent() ) ) 0602 { 0603 page = dynamic_cast<KoPAPageBase*>( parent ); 0604 } 0605 return page; 0606 } 0607 0608 //F)XME 0609 /* 0610 void KoPADocument::updateViews(KoPAPageBase *page) 0611 { 0612 if (!page) return; 0613 0614 foreach (KoView *view, views()) { 0615 KoPAView *paView = static_cast<KoPAView *>(view); 0616 if ( paView->activePage() == page ) { 0617 paView->viewMode()->updateActivePage( page ); 0618 } 0619 else if ( dynamic_cast<KoPAMasterPage *>( page ) ) { 0620 // if the page changed is a master page, we need to check whether it is the current page's master page 0621 KoPAPage *activePage = dynamic_cast<KoPAPage *>( paView->activePage() ); 0622 if ( activePage && activePage->masterPage() == page ) { 0623 paView->viewMode()->updateActivePage( activePage ); 0624 } 0625 } 0626 } 0627 } 0628 */ 0629 KoPageApp::PageType KoPADocument::pageType() const 0630 { 0631 return KoPageApp::Page; 0632 } 0633 0634 QPixmap KoPADocument::pageThumbnail(KoPAPageBase* page, const QSize& size) 0635 { 0636 int pageNumber = pageIndex(page) + 1; 0637 d->pageProvider->setPageData(pageNumber, page); 0638 return page->thumbnail(size); 0639 } 0640 0641 QImage KoPADocument::pageThumbImage(KoPAPageBase* page, const QSize& size) 0642 { 0643 int pageNumber = pageIndex(page) + 1; 0644 d->pageProvider->setPageData(pageNumber, page); 0645 return page->thumbImage(size); 0646 } 0647 0648 void KoPADocument::initEmpty() 0649 { 0650 d->masterPages.clear(); 0651 d->pages.clear(); 0652 KoPAMasterPage * masterPage = newMasterPage(); 0653 d->masterPages.append( masterPage ); 0654 KoPAPage * page = newPage( masterPage ); 0655 d->pages.append( page ); 0656 KoDocument::initEmpty(); 0657 } 0658 0659 void KoPADocument::insertPage( KoPAPageBase* page, int index ) 0660 { 0661 if ( !page ) 0662 return; 0663 0664 QList<KoPAPageBase*>& pages = dynamic_cast<KoPAMasterPage *>( page ) ? d->masterPages : d->pages; 0665 0666 if ( index > pages.size() || index < 0 ) 0667 { 0668 index = pages.size(); 0669 } 0670 0671 pages.insert( index, page ); 0672 updatePageCount(); 0673 0674 emit actionsPossible(KoPAView::ActionDeletePage, pages.size() > 1); 0675 0676 emit pageAdded(page); 0677 } 0678 0679 void KoPADocument::insertPage( KoPAPageBase* page, KoPAPageBase* after ) 0680 { 0681 if ( !page ) 0682 return; 0683 0684 QList<KoPAPageBase*>& pages = dynamic_cast<KoPAMasterPage *>( page ) ? d->masterPages : d->pages; 0685 0686 int index = 0; 0687 0688 if ( after != 0 ) 0689 { 0690 index = pages.indexOf( after ) + 1; 0691 0692 // Append the page if after wasn't found in pages 0693 if ( index == 0 ) 0694 index = pages.count(); 0695 } 0696 0697 pages.insert( index, page ); 0698 updatePageCount(); 0699 0700 emit actionsPossible(KoPAView::ActionDeletePage, pages.size() > 1); 0701 0702 emit pageAdded( page ); 0703 } 0704 0705 int KoPADocument::takePage( KoPAPageBase *page ) 0706 { 0707 Q_ASSERT( page ); 0708 0709 QList<KoPAPageBase *>& pages = dynamic_cast<KoPAMasterPage *>( page ) ? d->masterPages : d->pages; 0710 0711 int index = pages.indexOf( page ); 0712 0713 // it should not be possible to delete the last page 0714 Q_ASSERT( pages.size() > 1 ); 0715 0716 if ( index != -1 ) { 0717 pages.removeAt( index ); 0718 0719 // change to previous page when the page is the active one if the first one is delete go to the next one 0720 int newIndex = index == 0 ? 0 : index - 1; 0721 KoPAPageBase * newActivePage = pages.at( newIndex ); 0722 0723 updatePageCount(); 0724 0725 emit replaceActivePage(page, newActivePage); 0726 emit pageRemoved(page, index); 0727 } 0728 0729 if ( pages.size() == 1 ) { 0730 emit actionsPossible(KoPAView::ActionDeletePage, false); 0731 } 0732 0733 0734 return index; 0735 } 0736 0737 QList<KoPAPageBase*> KoPADocument::pages( bool masterPages ) const 0738 { 0739 return masterPages ? d->masterPages : d->pages; 0740 } 0741 0742 KoPAPage * KoPADocument::newPage( KoPAMasterPage * masterPage ) 0743 { 0744 return new KoPAPage( masterPage ); 0745 } 0746 0747 KoPAMasterPage * KoPADocument::newMasterPage() 0748 { 0749 return new KoPAMasterPage(); 0750 } 0751 0752 /// return the inlineTextObjectManager for this document. 0753 KoInlineTextObjectManager *KoPADocument::inlineTextObjectManager() const 0754 { 0755 return d->inlineTextObjectManager; 0756 } 0757 0758 void KoPADocument::loadConfig() 0759 { 0760 KSharedConfigPtr config = KSharedConfig::openConfig(); 0761 0762 if( config->hasGroup( "Grid" ) ) 0763 { 0764 KoGridData defGrid; 0765 KConfigGroup configGroup = config->group( "Grid" ); 0766 bool showGrid = configGroup.readEntry<bool>( "ShowGrid", defGrid.showGrid() ); 0767 gridData().setShowGrid(showGrid); 0768 bool paintGridInBackground = configGroup.readEntry("PaintGridInBackground", defGrid.paintGridInBackground()); 0769 gridData().setPaintGridInBackground(paintGridInBackground); 0770 bool snapToGrid = configGroup.readEntry<bool>( "SnapToGrid", defGrid.snapToGrid() ); 0771 gridData().setSnapToGrid(snapToGrid); 0772 qreal spacingX = configGroup.readEntry<qreal>( "SpacingX", defGrid.gridX() ); 0773 qreal spacingY = configGroup.readEntry<qreal>( "SpacingY", defGrid.gridY() ); 0774 gridData().setGrid( spacingX, spacingY ); 0775 QColor color = configGroup.readEntry( "Color", defGrid.gridColor() ); 0776 gridData().setGridColor( color ); 0777 } 0778 0779 d->showPageMargins = true; 0780 if( config->hasGroup( "Interface" ) ) 0781 { 0782 KConfigGroup configGroup = config->group( "Interface" ); 0783 bool showRulers = configGroup.readEntry<bool>( "ShowRulers", true); 0784 setRulersVisible(showRulers); 0785 0786 bool showPageMargins = configGroup.readEntry<bool>( "ShowPageMargins", true); 0787 setShowPageMargins(showPageMargins); 0788 } 0789 } 0790 0791 void KoPADocument::saveConfig() 0792 { 0793 KSharedConfigPtr config = KSharedConfig::openConfig(); 0794 KConfigGroup configGroup = config->group( "Grid" ); 0795 KoGridData defGrid; 0796 0797 bool showGrid = gridData().showGrid(); 0798 if ((showGrid == defGrid.showGrid()) && !configGroup.hasDefault("ShowGrid")) 0799 configGroup.revertToDefault("ShowGrid"); 0800 else 0801 configGroup.writeEntry("ShowGrid", showGrid); 0802 0803 bool snapToGrid = gridData().snapToGrid(); 0804 if ((snapToGrid == defGrid.snapToGrid()) && !configGroup.hasDefault("SnapToGrid")) 0805 configGroup.revertToDefault("SnapToGrid"); 0806 else 0807 configGroup.writeEntry("SnapToGrid", snapToGrid); 0808 0809 qreal spacingX = gridData().gridX(); 0810 if ((spacingX == defGrid.gridX()) && !configGroup.hasDefault("SpacingX")) 0811 configGroup.revertToDefault("SpacingX"); 0812 else 0813 configGroup.writeEntry("SpacingX", spacingX); 0814 0815 qreal spacingY = gridData().gridY(); 0816 if ((spacingY == defGrid.gridY()) && !configGroup.hasDefault("SpacingY")) 0817 configGroup.revertToDefault("SpacingY"); 0818 else 0819 configGroup.writeEntry("SpacingY", spacingY); 0820 0821 QColor color = gridData().gridColor(); 0822 if ((color == defGrid.gridColor()) && !configGroup.hasDefault("Color")) 0823 configGroup.revertToDefault("Color"); 0824 else 0825 configGroup.writeEntry("Color", color); 0826 0827 configGroup = config->group( "Interface" ); 0828 0829 bool showRulers = rulersVisible(); 0830 if ((showRulers == true) && !configGroup.hasDefault("ShowRulers")) 0831 configGroup.revertToDefault("ShowRulers"); 0832 else 0833 configGroup.writeEntry("ShowRulers", showRulers); 0834 0835 bool showMargins = showPageMargins(); 0836 if ((showMargins == true) && !configGroup.hasDefault("ShowPageMargins")) { 0837 configGroup.revertToDefault("ShowPageMargins"); 0838 } else { 0839 configGroup.writeEntry("ShowPageMargins", showMargins); 0840 } 0841 } 0842 0843 void KoPADocument::setRulersVisible(bool visible) 0844 { 0845 d->rulersVisible = visible; 0846 } 0847 0848 bool KoPADocument::rulersVisible() const 0849 { 0850 return d->rulersVisible; 0851 } 0852 0853 // TODO: the property "defaultStylesResourcePath" for each and every document 0854 // is not nice to have. Instead the info about that path (and similar data like?) 0855 // should be noted at some central component that all document objects etc. know 0856 // about and where the app which uses these classes can configure the path to 0857 // its needs 0858 void KoPADocument::setDefaultStylesResourcePath(const QString& defaultStylesResourcePath) 0859 { 0860 d->defaultStylesResourcePath = defaultStylesResourcePath; 0861 } 0862 0863 QString KoPADocument::defaultStylesResourcePath() const 0864 { 0865 return d->defaultStylesResourcePath; 0866 } 0867 0868 int KoPADocument::pageCount() const 0869 { 0870 return d->pages.count(); 0871 } 0872 0873 void KoPADocument::updatePageCount() 0874 { 0875 if (resourceManager()->hasResource(KoText::InlineTextObjectManager)) { 0876 QVariant var = resourceManager()->resource(KoText::InlineTextObjectManager); 0877 KoInlineTextObjectManager *om = var.value<KoInlineTextObjectManager*>(); 0878 om->setProperty( KoInlineObject::PageCount, pageCount() ); 0879 } 0880 } 0881 0882 void KoPADocument::updateDocumentURL() 0883 { 0884 if (resourceManager()->hasResource(KoText::InlineTextObjectManager)) { 0885 QVariant var = resourceManager()->resource(KoText::InlineTextObjectManager); 0886 KoInlineTextObjectManager *om = var.value<KoInlineTextObjectManager*>(); 0887 om->setProperty(KoInlineObject::DocumentURL, url().url(QUrl::PreferLocalFile)); 0888 } 0889 } 0890 0891 void KoPADocument::setShowPageMargins(bool state) 0892 { 0893 d->showPageMargins = state; 0894 } 0895 0896 bool KoPADocument::showPageMargins() const 0897 { 0898 return d->showPageMargins; 0899 }