Warning, file /office/calligra/libs/pageapp/KoPAPageBase.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-2010 Thorsten Zachmann <zachmann@kde.org>
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 "KoPAPageBase.h"
0021 
0022 #include "KoPASavingContext.h"
0023 #include "KoPALoadingContext.h"
0024 #include "KoPAPixmapCache.h"
0025 #include "KoPAPageContainerModel.h"
0026 #include "KoPAUtil.h"
0027 
0028 #include <KoXmlNS.h>
0029 #include <KoPageLayout.h>
0030 #include <KoStyleStack.h>
0031 #include <KoGenStyle.h>
0032 #include <KoGenStyles.h>
0033 #include <KoOdfLoadingContext.h>
0034 #include <KoViewConverter.h>
0035 #include <KoShapeLayer.h>
0036 #include <KoShapeRegistry.h>
0037 #include <KoShapeBackground.h>
0038 #include <KoZoomHandler.h>
0039 
0040 #include <PageAppDebug.h>
0041 
0042 #include <QPainter>
0043 #include <QPainterPath>
0044 
0045 #include <algorithm>
0046 
0047 KoPAPageBase::KoPAPageBase()
0048 : KoShapeContainer( new KoPAPageContainerModel() )
0049 {
0050     // Add a default layer
0051     KoShapeLayer* layer = new KoShapeLayer;
0052     addShape(layer);
0053 }
0054 
0055 KoPAPageBase::~KoPAPageBase()
0056 {
0057 }
0058 
0059 void KoPAPageBase::paintComponent(QPainter& painter, const KoViewConverter& converter, KoShapePaintingContext &)
0060 {
0061     Q_UNUSED(painter);
0062     Q_UNUSED(converter);
0063 }
0064 
0065 void KoPAPageBase::paintBackground( QPainter & painter, const KoViewConverter & converter, KoShapePaintingContext &paintContext )
0066 {
0067     painter.save();
0068     applyConversion( painter, converter );
0069     KoPageLayout layout = pageLayout();
0070     painter.setPen(QPen(Qt::black, 0));
0071 
0072     if (background()) {
0073         QPainterPath p;
0074         p.addRect( QRectF( 0.0, 0.0, layout.width, layout.height ) );
0075         background()->paint( painter, converter, paintContext, p );
0076     }
0077     else {
0078         painter.setBrush(Qt::white);
0079         painter.drawRect(QRectF(0.0, 0.0, layout.width, layout.height));
0080     }
0081 
0082     painter.restore();
0083 }
0084 
0085 void KoPAPageBase::saveOdfPageContent( KoPASavingContext & paContext ) const
0086 {
0087     saveOdfLayers(paContext);
0088     saveOdfShapes( paContext );
0089     saveOdfAnimations( paContext );
0090     saveOdfPresentationNotes( paContext );
0091 }
0092 
0093 void KoPAPageBase::saveOdfLayers(KoPASavingContext &paContext) const
0094 {
0095     QList<KoShape*> shapes(this->shapes());
0096     std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex);
0097     foreach(KoShape* shape, shapes) {
0098         KoShapeLayer *layer = dynamic_cast<KoShapeLayer*>(shape);
0099         if (layer) {
0100             paContext.addLayerForSaving(layer);
0101         }
0102         else {
0103             Q_ASSERT(layer);
0104             warnPageApp << "Page contains non layer where a layer is expected";
0105         }
0106     }
0107     paContext.saveLayerSet(paContext.xmlWriter());
0108     paContext.clearLayers();
0109 }
0110 
0111 void KoPAPageBase::saveOdfShapes( KoShapeSavingContext &context ) const
0112 {
0113     QList<KoShape*> shapes(this->shapes());
0114     QList<KoShape*> tlshapes( shapes );
0115 
0116     std::sort( tlshapes.begin(), tlshapes.end(), KoShape::compareShapeZIndex );
0117 
0118     foreach( KoShape *shape, tlshapes ) {
0119         shape->saveOdf( context );
0120     }
0121 }
0122 
0123 QString KoPAPageBase::saveOdfPageStyle( KoPASavingContext &paContext ) const
0124 {
0125     KoGenStyle style( KoGenStyle::DrawingPageAutoStyle, "drawing-page" );
0126 
0127     if ( paContext.isSet( KoShapeSavingContext::AutoStyleInStyleXml ) ) {
0128         style.setAutoStyleInStylesDotXml( true );
0129     }
0130 
0131     saveOdfPageStyleData( style, paContext );
0132 
0133     return paContext.mainStyles().insert( style, "dp" );
0134 }
0135 
0136 void KoPAPageBase::saveOdfPageStyleData( KoGenStyle &style, KoPASavingContext &paContext ) const
0137 {
0138     QSharedPointer<KoShapeBackground>  bg = background();
0139     if( bg )
0140         bg->fillStyle( style, paContext );
0141 }
0142 
0143 bool KoPAPageBase::saveOdfAnimations( KoPASavingContext & paContext ) const
0144 {
0145     Q_UNUSED( paContext );
0146     return true;
0147 }
0148 
0149 bool KoPAPageBase::saveOdfPresentationNotes(KoPASavingContext &paContext) const
0150 {
0151     Q_UNUSED( paContext );
0152     return true;
0153 }
0154 
0155 bool KoPAPageBase::loadOdf( const KoXmlElement &element, KoShapeLoadingContext & loadingContext )
0156 {
0157     KoPALoadingContext &paContext = static_cast<KoPALoadingContext&>( loadingContext );
0158 
0159     KoStyleStack& styleStack = loadingContext.odfLoadingContext().styleStack();
0160     styleStack.save();
0161     loadingContext.odfLoadingContext().fillStyleStack( element, KoXmlNS::draw, "style-name", "drawing-page" );
0162     styleStack.setTypeProperties( "drawing-page" );
0163 
0164     loadOdfPageTag(element, paContext);
0165     styleStack.restore();
0166 
0167     // load layers and shapes
0168     const KoXmlElement & pageLayerSet = KoXml::namedItemNS( element, KoXmlNS::draw, "layer-set" );
0169 
0170     const KoXmlElement & usedPageLayerSet = pageLayerSet.isNull() ? loadingContext.odfLoadingContext().stylesReader().layerSet(): pageLayerSet;
0171 
0172     int layerZIndex = 0;
0173     bool first = true;
0174     KoXmlElement layerElement;
0175     forEachElement( layerElement, usedPageLayerSet ) {
0176         KoShapeLayer * layer = 0;
0177         if ( first ) {
0178             first = false;
0179             layer = dynamic_cast<KoShapeLayer *>( shapes().first() );
0180             Q_ASSERT( layer );
0181         }
0182         else {
0183             layer = new KoShapeLayer();
0184             addShape( layer );
0185         }
0186         if ( layer ) {
0187             layer->setZIndex( layerZIndex++ );
0188             layer->loadOdf( layerElement, loadingContext );
0189         }
0190     }
0191 
0192     KoShapeLayer * layer = dynamic_cast<KoShapeLayer *>( shapes().first() );
0193     if ( layer )
0194     {
0195         KoXmlElement child;
0196         forEachElement( child, element )
0197         {
0198             debugPageApp <<"loading shape" << child.localName();
0199 
0200             KoShape * shape = KoShapeRegistry::instance()->createShapeFromOdf( child, loadingContext );
0201             if ( shape ) {
0202                 if( ! shape->parent() ) {
0203                     layer->addShape( shape );
0204                 }
0205             }
0206         }
0207     }
0208 
0209     loadOdfPageExtra(element, paContext);
0210 
0211     return true;
0212 }
0213 
0214 void KoPAPageBase::loadOdfPageTag( const KoXmlElement &element,
0215                                    KoPALoadingContext &loadingContext )
0216 {
0217     Q_UNUSED(element);
0218     KoStyleStack& styleStack = loadingContext.odfLoadingContext().styleStack();
0219 
0220     if ( styleStack.hasProperty( KoXmlNS::draw, "fill" ) ) {
0221         setBackground(loadOdfFill(loadingContext));
0222     }
0223 }
0224 
0225 void KoPAPageBase::loadOdfPageExtra( const KoXmlElement &element, KoPALoadingContext & loadingContext )
0226 {
0227     Q_UNUSED( element );
0228     Q_UNUSED( loadingContext );
0229 }
0230 
0231 QSizeF KoPAPageBase::size() const
0232 {
0233     const KoPageLayout layout = pageLayout();
0234     return QSize( layout.width, layout.height );
0235 }
0236 
0237 QRectF KoPAPageBase::boundingRect() const
0238 {
0239     //return KoShapeContainer::boundingRect();
0240     return contentRect().united(QRectF(QPointF(0, 0), size() ));
0241 }
0242 
0243 QRectF KoPAPageBase::contentRect() const
0244 {
0245     QRectF bb;
0246     foreach (KoShape* layer, shapes()) {
0247         if (bb.isNull()) {
0248             bb = layer->boundingRect();
0249         }
0250         else {
0251             bb = bb.united(layer->boundingRect());
0252         }
0253     }
0254 
0255     return bb;
0256 }
0257 
0258 void KoPAPageBase::shapeAdded( KoShape * shape )
0259 {
0260     Q_UNUSED( shape );
0261 }
0262 
0263 void KoPAPageBase::shapeRemoved( KoShape * shape )
0264 {
0265     Q_UNUSED( shape );
0266 }
0267 
0268 KoPageApp::PageType KoPAPageBase::pageType() const
0269 {
0270     return KoPageApp::Page;
0271 }
0272 
0273 QPixmap KoPAPageBase::thumbnail( const QSize& size )
0274 {
0275 #ifdef CACHE_PAGE_THUMBNAILS
0276     QString key = thumbnailKey();
0277     QPixmap pm;
0278     if ( !KoPAPixmapCache::instance()->find( key, size, pm ) ) {
0279         pm = generateThumbnail( size );
0280         KoPAPixmapCache::instance()->insert( key, pm, size );
0281         debugPageApp << "create thumbnail" << this << key << size;
0282     }
0283     else {
0284         //debugPageApp << "thumbnail in cache " << this;
0285     }
0286     return pm;
0287 #else
0288     return generateThumbnail( size );
0289 #endif
0290 }
0291 
0292 QPixmap KoPAPageBase::generateThumbnail(const QSize &size)
0293 {
0294     // don't paint null pixmap
0295     if ( size.isEmpty() ) // either width or height is <= 0
0296         return QPixmap();
0297 
0298     KoZoomHandler zoomHandler;
0299     QSize thumbnailSize(size);
0300 
0301     KoPAUtil::setSizeAndZoom(pageLayout(), thumbnailSize, zoomHandler);
0302 
0303     QPixmap pixmap(thumbnailSize);
0304     // paint white as default page background
0305     pixmap.fill(Qt::white);
0306     QPainter painter(&pixmap);
0307     painter.setClipRect(QRect(QPoint(0, 0), thumbnailSize));
0308     painter.setRenderHint(QPainter::Antialiasing);
0309 
0310     paintPage(painter, zoomHandler);
0311 
0312     return pixmap;
0313 }
0314 
0315 QImage KoPAPageBase::thumbImage(const QSize &size)
0316 {
0317     if (size.isEmpty()) {
0318         return QImage();
0319     }
0320 
0321     KoZoomHandler zoomHandler;
0322     QSize thumbnailSize(size);
0323 
0324     KoPAUtil::setSizeAndZoom(pageLayout(), thumbnailSize, zoomHandler);
0325 
0326     QImage image(thumbnailSize, QImage::Format_RGB32);
0327     // paint white as default page background
0328     image.fill(QColor(Qt::white).rgb());
0329     QPainter painter(&image);
0330     painter.setClipRect(QRect(QPoint(0, 0), thumbnailSize));
0331     painter.setRenderHint(QPainter::Antialiasing);
0332 
0333     paintPage(painter, zoomHandler);
0334 
0335     return image;
0336 }
0337 
0338 void KoPAPageBase::pageUpdated()
0339 {
0340     KoPAPixmapCache::instance()->remove( thumbnailKey() );
0341 }
0342 
0343 QString KoPAPageBase::thumbnailKey() const
0344 {
0345      QString key;
0346      key.sprintf( "%p", static_cast<const void *>( this ) );
0347      return key;
0348 }
0349 
0350 KoShapeManagerPaintingStrategy * KoPAPageBase::getPaintingStrategy() const
0351 {
0352     return 0;
0353 }