File indexing completed on 2024-05-19 16:09:32
0001 /* This file is part of the KDE project 0002 Copyright (C) 2006-2010 Thorsten Zachmann <zachmann@kde.org> 0003 Copyright (C) 2010 Benjamin Port <port.benjamin@gmail.com> 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 "KPrDocument.h" 0022 0023 0024 #include "KPrView.h" 0025 #include "KPresenter.h" 0026 #include "KPrPage.h" 0027 #include "KPrMasterPage.h" 0028 #include "KPrShapeApplicationData.h" 0029 #include "KPrFactory.h" 0030 #include "KPrViewModeNotes.h" 0031 #include "KPrPlaceholderShapeFactory.h" 0032 #include "KPrSoundCollection.h" 0033 #include "KPrDeclarations.h" 0034 #include "pagelayout/KPrPageLayouts.h" 0035 #include "tools/KPrPlaceholderToolFactory.h" 0036 #include "commands/KPrDeleteSlidesCommand.h" 0037 #include <KoPASavingContext.h> 0038 #include <KoPALoadingContext.h> 0039 #include <KoShapeLoadingContext.h> 0040 #include <KoShapeRegistry.h> 0041 #include <KoToolRegistry.h> 0042 #include <KoXmlNS.h> 0043 #include <KoXmlWriter.h> 0044 0045 #include <kconfig.h> 0046 #include <kconfiggroup.h> 0047 #include <KSharedConfig> 0048 0049 #include <QTimer> 0050 #include <QCoreApplication> 0051 #include <QGlobalStatic> 0052 #include <QStandardPaths> 0053 0054 class InitOnce 0055 { 0056 public: 0057 InitOnce() 0058 { 0059 KoToolRegistry * toolRegistry = KoToolRegistry::instance(); 0060 toolRegistry->add( new KPrPlaceholderToolFactory() ); 0061 KoShapeRegistry * registry = KoShapeRegistry::instance(); 0062 registry->addFactory( new KPrPlaceholderShapeFactory() ); 0063 } 0064 }; 0065 0066 Q_GLOBAL_STATIC( InitOnce, s_initOnce ); 0067 0068 KPrDocument::KPrDocument(KoPart *part) 0069 : KoPADocument(part) 0070 , m_customSlideShows(new KPrCustomSlideShows()) 0071 , m_presentationMonitor( 0 ) 0072 , m_presenterViewEnabled( false ) 0073 , m_declarations( new KPrDeclarations() ) 0074 { 0075 // TODO: revisit if this is the place where that initialization should happen 0076 InitOnce * initOnce = s_initOnce; 0077 // have this is as otherwise we get a warning from the compiler 0078 // the variable is used and the way it is done is to only call it once 0079 Q_UNUSED( initOnce ); 0080 0081 KoShapeLoadingContext::addAdditionalAttributeData( KoShapeLoadingContext::AdditionalAttributeData( 0082 KoXmlNS::presentation, "placeholder", 0083 "presentation:placeholder" ) ); 0084 0085 KoShapeLoadingContext::addAdditionalAttributeData( KoShapeLoadingContext::AdditionalAttributeData( 0086 KoXmlNS::presentation, "class", 0087 "presentation:class" ) ); 0088 0089 QVariant variant; 0090 variant.setValue(new KPrSoundCollection(this)); 0091 resourceManager()->setResource(KPresenter::SoundCollection, variant); 0092 0093 variant.setValue(new KPrPageLayouts(this)); 0094 resourceManager()->setResource(KPresenter::PageLayouts, variant); 0095 0096 loadKPrConfig(); 0097 } 0098 0099 KPrDocument::~KPrDocument() 0100 { 0101 saveKPrConfig(); 0102 delete m_customSlideShows; 0103 delete m_declarations; 0104 } 0105 0106 const char * KPrDocument::odfTagName( bool withNamespace ) 0107 { 0108 return withNamespace ? "office:presentation": "presentation"; 0109 } 0110 0111 bool KPrDocument::saveOdfProlog( KoPASavingContext & context ) 0112 { 0113 if ( !KoPADocument::saveOdfProlog( context ) ) 0114 return false; 0115 m_declarations->saveOdf( context ); 0116 return true; 0117 } 0118 0119 bool KPrDocument::saveOdfEpilogue( KoPASavingContext & context ) 0120 { 0121 context.xmlWriter().startElement( "presentation:settings" ); 0122 if ( !m_activeCustomSlideShow.isEmpty() && m_customSlideShows->names().contains( m_activeCustomSlideShow ) ) { 0123 context.xmlWriter().addAttribute( "presentation:show", m_activeCustomSlideShow ); 0124 } 0125 m_customSlideShows->saveOdf( context ); 0126 context.xmlWriter().endElement();//presentation:settings 0127 return true; 0128 } 0129 0130 void KPrDocument::saveOdfDocumentStyles( KoPASavingContext & context ) 0131 { 0132 KoPADocument::saveOdfDocumentStyles( context ); 0133 KPrPageLayouts *layouts = resourceManager()->resource(KPresenter::PageLayouts).value<KPrPageLayouts*>(); 0134 0135 Q_ASSERT( layouts ); 0136 if ( layouts ) { 0137 layouts->saveOdf( context ); 0138 } 0139 } 0140 0141 bool KPrDocument::loadOdfEpilogue( const KoXmlElement & body, KoPALoadingContext & context ) 0142 { 0143 const KoXmlElement & presentationSettings( KoXml::namedItemNS( body, KoXmlNS::presentation, "settings" ) ); 0144 if ( !presentationSettings.isNull() ) { 0145 m_customSlideShows->loadOdf( presentationSettings, context ); 0146 } 0147 0148 m_activeCustomSlideShow = QString( "" ); 0149 if ( presentationSettings.hasAttributeNS( KoXmlNS::presentation, "show" ) ) { 0150 QString show = presentationSettings.attributeNS( KoXmlNS::presentation, "show" ); 0151 if ( m_customSlideShows->names().contains( show ) ) { 0152 m_activeCustomSlideShow = show; 0153 } 0154 } 0155 0156 return true; 0157 } 0158 0159 bool KPrDocument::loadOdfDocumentStyles( KoPALoadingContext & context ) 0160 { 0161 KPrPageLayouts *layouts = resourceManager()->resource(KPresenter::PageLayouts).value<KPrPageLayouts*>(); 0162 if ( layouts ) { 0163 layouts->loadOdf( context ); 0164 } 0165 return true; 0166 } 0167 0168 KoPAPage * KPrDocument::newPage( KoPAMasterPage * masterPage ) 0169 { 0170 Q_ASSERT(masterPage); 0171 return new KPrPage( masterPage, this ); 0172 } 0173 0174 KoPAMasterPage * KPrDocument::newMasterPage() 0175 { 0176 return new KPrMasterPage(this); 0177 } 0178 0179 KoOdf::DocumentType KPrDocument::documentType() const 0180 { 0181 return KoOdf::Presentation; 0182 } 0183 0184 void KPrDocument::addAnimation( KPrShapeAnimation * animation ) 0185 { 0186 KoShape * shape = animation->shape(); 0187 0188 KPrShapeAnimations & animations( animationsByPage( pageByShape( shape ) ) ); 0189 0190 // add animation to the list of animations 0191 animations.add( animation ); 0192 0193 // add animation to the shape animation data so that it can be regenerated on delete shape and undo 0194 KPrShapeApplicationData * applicationData = dynamic_cast<KPrShapeApplicationData*>( shape->applicationData() ); 0195 if ( applicationData == 0 ) { 0196 applicationData = new KPrShapeApplicationData(); 0197 shape->setApplicationData( applicationData ); 0198 } 0199 applicationData->animations().insert( animation ); 0200 applicationData->setDeleteAnimations(false); 0201 } 0202 0203 void KPrDocument::removeAnimation( KPrShapeAnimation * animation, bool removeFromApplicationData ) 0204 { 0205 KoShape * shape = animation->shape(); 0206 0207 KPrShapeAnimations & animations( animationsByPage( pageByShape( shape ) ) ); 0208 0209 // remove animation from the list of animations 0210 animations.remove( animation ); 0211 0212 KPrShapeApplicationData *applicationData = dynamic_cast<KPrShapeApplicationData*>(shape->applicationData()); 0213 Q_ASSERT(applicationData); 0214 if (removeFromApplicationData) { 0215 // remove animation from the shape animation data 0216 applicationData->animations().remove(animation); 0217 } else { 0218 applicationData->setDeleteAnimations(true); 0219 } 0220 } 0221 0222 void KPrDocument::replaceAnimation(KPrShapeAnimation *oldAnimation, KPrShapeAnimation *newAnimation) 0223 { 0224 KoShape *shape = oldAnimation->shape(); 0225 KPrShapeAnimations &animations(animationsByPage(pageByShape(shape))); 0226 0227 // remove animation from the list of animations 0228 animations.replaceAnimation(oldAnimation, newAnimation); 0229 } 0230 0231 void KPrDocument::postAddShape( KoPAPageBase * page, KoShape * shape ) 0232 { 0233 Q_UNUSED( page ); 0234 KPrShapeApplicationData * applicationData = dynamic_cast<KPrShapeApplicationData*>( shape->applicationData() ); 0235 if ( applicationData ) { 0236 // reinsert animations. this is needed on undo of a delete shape that had a animations 0237 QSet<KPrShapeAnimation *> animations = applicationData->animations(); 0238 for ( QSet<KPrShapeAnimation *>::const_iterator it( animations.begin() ); it != animations.end(); ++it ) { 0239 addAnimation( *it ); 0240 } 0241 } 0242 } 0243 0244 void KPrDocument::postRemoveShape( KoPAPageBase * page, KoShape * shape ) 0245 { 0246 Q_UNUSED( page ); 0247 KPrShapeApplicationData * applicationData = dynamic_cast<KPrShapeApplicationData*>( shape->applicationData() ); 0248 if ( applicationData ) { 0249 QSet<KPrShapeAnimation *> animations = applicationData->animations(); 0250 for ( QSet<KPrShapeAnimation *>::const_iterator it( animations.begin() ); it != animations.end(); ++it ) { 0251 // remove animations, don't remove from shape application data so that it can be reinserted on undo. 0252 removeAnimation( *it, false ); 0253 } 0254 } 0255 } 0256 0257 void KPrDocument::removePages(QList<KoPAPageBase *> &pages) 0258 { 0259 KPrDeleteSlidesCommand *command = new KPrDeleteSlidesCommand(this, pages); 0260 addCommand(command); 0261 } 0262 0263 void KPrDocument::loadKPrConfig() 0264 { 0265 KSharedConfigPtr config = KSharedConfig::openConfig(); 0266 0267 if ( config->hasGroup( "SlideShow" ) ) { 0268 KConfigGroup configGroup = config->group( "SlideShow" ); 0269 m_presentationMonitor = configGroup.readEntry<int>( "PresentationMonitor", 0 ); 0270 m_presenterViewEnabled = configGroup.readEntry<bool>( "PresenterViewEnabled", false ); 0271 } 0272 } 0273 0274 void KPrDocument::saveKPrConfig() 0275 { 0276 KSharedConfigPtr config = KSharedConfig::openConfig(); 0277 KConfigGroup configGroup = config->group( "SlideShow" ); 0278 0279 configGroup.writeEntry( "PresentationMonitor", m_presentationMonitor ); 0280 configGroup.writeEntry( "PresenterViewEnabled", m_presenterViewEnabled ); 0281 } 0282 0283 KoPageApp::PageType KPrDocument::pageType() const 0284 { 0285 return KoPageApp::Slide; 0286 } 0287 0288 void KPrDocument::initEmpty() 0289 { 0290 QString fileName(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("calligrastage/templates/Screen/.source/emptyLandscape.otp"))); 0291 setModified( true ); 0292 bool ok = loadNativeFormat( fileName ); 0293 if ( !ok ) { 0294 // use initEmpty from kopageapp 0295 showLoadingErrorDialog(); 0296 KoPADocument::initEmpty(); 0297 } 0298 resetURL(); 0299 } 0300 0301 KPrShapeAnimations & KPrDocument::animationsByPage( KoPAPageBase * page ) 0302 { 0303 KPrPageData * pageData = dynamic_cast<KPrPageData *>( page ); 0304 Q_ASSERT( pageData ); 0305 return pageData->animations(); 0306 } 0307 0308 KPrCustomSlideShows* KPrDocument::customSlideShows() 0309 { 0310 return m_customSlideShows; 0311 } 0312 0313 void KPrDocument::setCustomSlideShows( KPrCustomSlideShows* replacement ) 0314 { 0315 m_customSlideShows = replacement; 0316 emit customSlideShowsModified(); 0317 } 0318 0319 int KPrDocument::presentationMonitor() 0320 { 0321 return m_presentationMonitor; 0322 } 0323 0324 void KPrDocument::setPresentationMonitor( int monitor ) 0325 { 0326 m_presentationMonitor = monitor; 0327 } 0328 0329 bool KPrDocument::isPresenterViewEnabled() 0330 { 0331 return m_presenterViewEnabled; 0332 } 0333 0334 void KPrDocument::setPresenterViewEnabled( bool enabled ) 0335 { 0336 m_presenterViewEnabled = enabled; 0337 } 0338 0339 QList<KoPAPageBase*> KPrDocument::slideShow() const 0340 { 0341 if ( !m_activeCustomSlideShow.isEmpty() && 0342 m_customSlideShows->names().contains( m_activeCustomSlideShow ) ) { 0343 return m_customSlideShows->getByName( m_activeCustomSlideShow ); 0344 } 0345 0346 return pages(); 0347 } 0348 0349 QString KPrDocument::activeCustomSlideShow() const 0350 { 0351 return m_activeCustomSlideShow; 0352 } 0353 0354 void KPrDocument::setActiveCustomSlideShow( const QString &customSlideShow ) 0355 { 0356 if ( customSlideShow != m_activeCustomSlideShow ) { 0357 m_activeCustomSlideShow = customSlideShow; 0358 emit activeCustomSlideShowChanged( customSlideShow ); 0359 } 0360 } 0361 0362 bool KPrDocument::loadOdfProlog( const KoXmlElement & body, KoPALoadingContext & context ) 0363 { 0364 if ( !KoPADocument::loadOdfProlog( body, context ) ) 0365 return false; 0366 return m_declarations->loadOdf( body, context ); 0367 } 0368 0369 KPrDeclarations * KPrDocument::declarations() const 0370 { 0371 return m_declarations; 0372 }