| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| /*************************************************************************** | ||
| qgsaddremovemultiframecommand.cpp | ||
| --------------------------------- | ||
| begin : 2012-07-31 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsaddremovemultiframecommand.h" | ||
| #include "qgscomposermultiframe.h" | ||
| #include "qgscomposition.h" | ||
|
|
||
|
|
||
| QgsAddRemoveMultiFrameCommand::QgsAddRemoveMultiFrameCommand( State s, QgsComposerMultiFrame* multiFrame, QgsComposition* c, const QString& text, QUndoCommand* parent ): | ||
| QUndoCommand( text, parent ), mMultiFrame( multiFrame ), mComposition( c ), mState(s), mFirstRun( true ) | ||
| { | ||
| } | ||
|
|
||
| QgsAddRemoveMultiFrameCommand::QgsAddRemoveMultiFrameCommand(): mMultiFrame( 0 ), mComposition( 0 ) | ||
| { | ||
| } | ||
|
|
||
| QgsAddRemoveMultiFrameCommand::~QgsAddRemoveMultiFrameCommand() | ||
| { | ||
| if( mState == Removed ) | ||
| { | ||
| delete mMultiFrame; | ||
| } | ||
| } | ||
|
|
||
| void QgsAddRemoveMultiFrameCommand::redo() | ||
| { | ||
| if( checkFirstRun() ) | ||
| { | ||
| return; | ||
| } | ||
| switchState(); | ||
| } | ||
|
|
||
| void QgsAddRemoveMultiFrameCommand::undo() | ||
| { | ||
| if( checkFirstRun() ) | ||
| { | ||
| return; | ||
| } | ||
| switchState(); | ||
| } | ||
|
|
||
| void QgsAddRemoveMultiFrameCommand::switchState() | ||
| { | ||
| if( mComposition ) | ||
| { | ||
| if( mState == Added ) | ||
| { | ||
| mComposition->removeMultiFrame( mMultiFrame ); | ||
| mState = Removed; | ||
| } | ||
| else | ||
| { | ||
| mComposition->addMultiFrame( mMultiFrame ); | ||
| mState = Added; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| bool QgsAddRemoveMultiFrameCommand::checkFirstRun() | ||
| { | ||
| if( mFirstRun ) | ||
| { | ||
| mFirstRun = false; | ||
| return true; | ||
| } | ||
| else | ||
| { | ||
| return false; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| /*************************************************************************** | ||
| qgsaddremovemultiframecommand.h | ||
| ------------------------------- | ||
| begin : 2012-07-31 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSADDREMOVEMULTIFRAMECOMMAND_H | ||
| #define QGSADDREMOVEMULTIFRAMECOMMAND_H | ||
|
|
||
| #include <QUndoCommand> | ||
|
|
||
| class QgsComposerMultiFrame; | ||
| class QgsComposition; | ||
|
|
||
| class CORE_EXPORT QgsAddRemoveMultiFrameCommand: public QUndoCommand | ||
| { | ||
| public: | ||
|
|
||
| enum State | ||
| { | ||
| Added = 0, | ||
| Removed | ||
| }; | ||
|
|
||
| QgsAddRemoveMultiFrameCommand( State s, QgsComposerMultiFrame* multiFrame, QgsComposition* c, const QString& text, QUndoCommand* parent = 0 ); | ||
| ~QgsAddRemoveMultiFrameCommand(); | ||
| void redo(); | ||
| void undo(); | ||
|
|
||
| private: | ||
| QgsAddRemoveMultiFrameCommand(); | ||
|
|
||
| //changes between added / removed state | ||
| void switchState(); | ||
| bool checkFirstRun(); | ||
|
|
||
| QgsComposerMultiFrame* mMultiFrame; | ||
| QgsComposition* mComposition; | ||
| State mState; | ||
| bool mFirstRun; | ||
| }; | ||
|
|
||
| #endif // QGSADDREMOVEMULTIFRAMECOMMAND_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| /*************************************************************************** | ||
| qgscomposerframe.cpp | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgscomposerframe.h" | ||
| #include "qgscomposermultiframe.h" | ||
|
|
||
| QgsComposerFrame::QgsComposerFrame( QgsComposition* c, QgsComposerMultiFrame* mf, double x, double y, double width, double height ): | ||
| QgsComposerItem( x, y, width, height, c ), mMultiFrame( mf ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerFrame::QgsComposerFrame(): QgsComposerItem( 0, 0, 0, 0, 0 ), mMultiFrame( 0 ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerFrame::~QgsComposerFrame() | ||
| { | ||
| } | ||
|
|
||
| bool QgsComposerFrame::writeXML( QDomElement& elem, QDomDocument & doc ) const | ||
| { | ||
| QDomElement frameElem = doc.createElement( "ComposerFrame" ); | ||
| frameElem.setAttribute( "sectionX", QString::number( mSection.x() ) ); | ||
| frameElem.setAttribute( "sectionY", QString::number( mSection.y() ) ); | ||
| frameElem.setAttribute( "sectionWidth", QString::number( mSection.width() ) ); | ||
| frameElem.setAttribute( "sectionHeight", QString::number( mSection.height() ) ); | ||
| elem.appendChild( frameElem ); | ||
| return _writeXML( frameElem, doc ); | ||
| } | ||
|
|
||
| bool QgsComposerFrame::readXML( const QDomElement& itemElem, const QDomDocument& doc ) | ||
| { | ||
| double x = itemElem.attribute( "sectionX" ).toDouble(); | ||
| double y = itemElem.attribute( "sectionY" ).toDouble(); | ||
| double width = itemElem.attribute( "sectionWidth" ).toDouble(); | ||
| double height = itemElem.attribute( "sectionHeight" ).toDouble(); | ||
| mSection = QRectF( x, y, width, height ); | ||
| QDomElement composerItem = itemElem.firstChildElement( "ComposerItem" ); | ||
| if ( composerItem.isNull() ) | ||
| { | ||
| return false; | ||
| } | ||
| return _readXML( composerItem, doc ); | ||
| } | ||
|
|
||
| void QgsComposerFrame::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ) | ||
| { | ||
| if ( !painter ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| drawBackground( painter ); | ||
| if ( mMultiFrame ) | ||
| { | ||
| mMultiFrame->render( painter, mSection ); | ||
| } | ||
|
|
||
| drawFrame( painter ); | ||
| if ( isSelected() ) | ||
| { | ||
| drawSelectionBoxes( painter ); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerFrame::beginItemCommand( const QString& text ) | ||
| { | ||
| if ( mComposition ) | ||
| { | ||
| mComposition->beginMultiFrameCommand( multiFrame(), text ); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerFrame::endItemCommand() | ||
| { | ||
| if ( mComposition ) | ||
| { | ||
| mComposition->endMultiFrameCommand(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /*************************************************************************** | ||
| qgscomposerframe.h | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSCOMPOSERFRAME_H | ||
| #define QGSCOMPOSERFRAME_H | ||
|
|
||
| #include "qgscomposeritem.h" | ||
|
|
||
| class QgsComposition; | ||
| class QgsComposerMultiFrame; | ||
|
|
||
| /**Frame for html, table, text which can be divided onto several frames*/ | ||
| class QgsComposerFrame: public QgsComposerItem | ||
| { | ||
| public: | ||
| QgsComposerFrame( QgsComposition* c, QgsComposerMultiFrame* mf, qreal x, qreal y, qreal width, qreal height ); | ||
| ~QgsComposerFrame(); | ||
|
|
||
| /**Sets the part of this frame (relative to the total multiframe extent in mm)*/ | ||
| void setContentSection( const QRectF& section ) { mSection = section; } | ||
|
|
||
| void paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ); | ||
|
|
||
| void beginItemCommand( const QString& text ); | ||
| void endItemCommand(); | ||
|
|
||
| bool writeXML( QDomElement& elem, QDomDocument & doc ) const; | ||
| bool readXML( const QDomElement& itemElem, const QDomDocument& doc ); | ||
|
|
||
| int type() const { return ComposerFrame; } | ||
|
|
||
| QgsComposerMultiFrame* multiFrame() { return mMultiFrame; } | ||
|
|
||
|
|
||
| private: | ||
| QgsComposerFrame(); //forbidden | ||
| QgsComposerMultiFrame* mMultiFrame; | ||
| QRectF mSection; | ||
| }; | ||
|
|
||
| #endif // QGSCOMPOSERFRAME_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /*************************************************************************** | ||
| qgscomposerhtml.cpp | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgscomposerhtml.h" | ||
| #include "qgscomposerframe.h" | ||
| #include "qgscomposition.h" | ||
| #include "qgsaddremovemultiframecommand.h" | ||
| #include <QCoreApplication> | ||
| #include <QPainter> | ||
| #include <QWebFrame> | ||
| #include <QWebPage> | ||
|
|
||
| QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands ): QgsComposerMultiFrame( c, createUndoCommands ), | ||
| mWebPage( 0 ), mLoaded( false ), mHtmlUnitsToMM( 1.0 ) | ||
| { | ||
| mHtmlUnitsToMM = htmlUnitsToMM(); | ||
| mWebPage = new QWebPage(); | ||
| QObject::connect( mWebPage, SIGNAL( loadFinished( bool ) ), this, SLOT( frameLoaded( bool ) ) ); | ||
| if ( mComposition ) | ||
| { | ||
| QObject::connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( handleFrameRemoval( QgsComposerItem* ) ) ); | ||
| } | ||
| } | ||
|
|
||
| QgsComposerHtml::QgsComposerHtml(): QgsComposerMultiFrame( 0, false ), mWebPage( 0 ), mLoaded( false ), mHtmlUnitsToMM( 1.0 ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerHtml::~QgsComposerHtml() | ||
| { | ||
| delete mWebPage; | ||
| } | ||
|
|
||
| void QgsComposerHtml::setUrl( const QUrl& url ) | ||
| { | ||
| if ( !mWebPage ) | ||
| { | ||
| return; | ||
| } | ||
| mLoaded = false; | ||
|
|
||
| mUrl = url; | ||
| mWebPage->mainFrame()->load( mUrl ); | ||
| while ( !mLoaded ) | ||
| { | ||
| qApp->processEvents(); | ||
| } | ||
| QSize contentsSize = mWebPage->mainFrame()->contentsSize(); | ||
| mWebPage->setViewportSize( contentsSize ); | ||
|
|
||
| mSize.setWidth( contentsSize.width() / mHtmlUnitsToMM ); | ||
| mSize.setHeight( contentsSize.height() / mHtmlUnitsToMM ); | ||
| recalculateFrameSizes(); | ||
| emit changed(); | ||
| } | ||
|
|
||
| void QgsComposerHtml::frameLoaded( bool ok ) | ||
| { | ||
| Q_UNUSED( ok ); | ||
| mLoaded = true; | ||
| } | ||
|
|
||
| QSizeF QgsComposerHtml::totalSize() const | ||
| { | ||
| return mSize; | ||
| } | ||
|
|
||
| void QgsComposerHtml::render( QPainter* p, const QRectF& renderExtent ) | ||
| { | ||
| if ( !mWebPage ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| p->save(); | ||
| p->scale( 1.0 / mHtmlUnitsToMM, 1.0 / mHtmlUnitsToMM ); | ||
| p->translate( 0.0, -renderExtent.top() * mHtmlUnitsToMM ); | ||
| mWebPage->mainFrame()->render( p, QRegion( renderExtent.left(), renderExtent.top() * mHtmlUnitsToMM, renderExtent.width() * mHtmlUnitsToMM, renderExtent.height() * mHtmlUnitsToMM ) ); | ||
| p->restore(); | ||
| } | ||
|
|
||
| double QgsComposerHtml::htmlUnitsToMM() | ||
| { | ||
| if ( !mComposition ) | ||
| { | ||
| return 1.0; | ||
| } | ||
|
|
||
| return ( mComposition->printResolution() / 96.0 ); //webkit seems to assume a standard dpi of 96 | ||
| } | ||
|
|
||
| void QgsComposerHtml::addFrame( QgsComposerFrame* frame, bool recalcFrameSizes ) | ||
| { | ||
| mFrameItems.push_back( frame ); | ||
| QObject::connect( frame, SIGNAL( sizeChanged() ), this, SLOT( recalculateFrameSizes() ) ); | ||
| if ( mComposition ) | ||
| { | ||
| mComposition->addComposerHtmlFrame( this, frame ); | ||
| } | ||
|
|
||
| if ( recalcFrameSizes ) | ||
| { | ||
| recalculateFrameSizes(); | ||
| } | ||
| } | ||
|
|
||
| bool QgsComposerHtml::writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames ) const | ||
| { | ||
| QDomElement htmlElem = doc.createElement( "ComposerHtml" ); | ||
| htmlElem.setAttribute( "url", mUrl.toString() ); | ||
| bool state = _writeXML( htmlElem, doc, ignoreFrames ); | ||
| elem.appendChild( htmlElem ); | ||
| return state; | ||
| } | ||
|
|
||
| bool QgsComposerHtml::readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames ) | ||
| { | ||
| deleteFrames(); | ||
| QString urlString = itemElem.attribute( "url" ); | ||
| if ( !urlString.isEmpty() ) | ||
| { | ||
| setUrl( QUrl( urlString ) ); | ||
| } | ||
| return _readXML( itemElem, doc, ignoreFrames ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /*************************************************************************** | ||
| qgscomposerhtml.h | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSCOMPOSERHTML_H | ||
| #define QGSCOMPOSERHTML_H | ||
|
|
||
| #include "qgscomposermultiframe.h" | ||
| #include <QUrl> | ||
|
|
||
| class QWebPage; | ||
|
|
||
| class QgsComposerHtml: public QgsComposerMultiFrame | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
| QgsComposerHtml( QgsComposition* c, bool createUndoCommands ); | ||
| QgsComposerHtml(); | ||
| ~QgsComposerHtml(); | ||
|
|
||
| void setUrl( const QUrl& url ); | ||
| const QUrl& url() const { return mUrl; } | ||
|
|
||
| QSizeF totalSize() const; | ||
| void render( QPainter* p, const QRectF& renderExtent ); | ||
|
|
||
| bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const; | ||
| bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false ); | ||
|
|
||
| void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ); | ||
|
|
||
| private slots: | ||
| void frameLoaded( bool ok ); | ||
|
|
||
| private: | ||
| QUrl mUrl; | ||
| QWebPage* mWebPage; | ||
| bool mLoaded; | ||
| QSizeF mSize; //total size in mm | ||
| double mHtmlUnitsToMM; | ||
|
|
||
| double htmlUnitsToMM(); //calculate scale factor | ||
| }; | ||
|
|
||
| #endif // QGSCOMPOSERHTML_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| /*************************************************************************** | ||
| qgscomposermultiframe.cpp | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgscomposermultiframe.h" | ||
| #include "qgscomposerframe.h" | ||
|
|
||
| QgsComposerMultiFrame::QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands ): mComposition( c ), mResizeMode( UseExistingFrames ), mCreateUndoCommands( createUndoCommands ) | ||
| { | ||
| mComposition->addMultiFrame( this ); | ||
| } | ||
|
|
||
| QgsComposerMultiFrame::QgsComposerMultiFrame(): mComposition( 0 ), mResizeMode( UseExistingFrames ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerMultiFrame::~QgsComposerMultiFrame() | ||
| { | ||
| deleteFrames(); | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::setResizeMode( ResizeMode mode ) | ||
| { | ||
| if ( mode != mResizeMode ) | ||
| { | ||
| mResizeMode = mode; | ||
| recalculateFrameSizes(); | ||
| emit changed(); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::recalculateFrameSizes() | ||
| { | ||
| if ( mFrameItems.size() < 1 ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| QSizeF size = totalSize(); | ||
| double totalHeight = size.height(); | ||
|
|
||
| if ( totalHeight < 1 ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| double currentY = 0; | ||
| double currentHeight = 0; | ||
| QgsComposerFrame* currentItem = 0; | ||
|
|
||
| for ( int i = 0; i < mFrameItems.size(); ++i ) | ||
| { | ||
| if ( currentY >= totalHeight ) | ||
| { | ||
| if ( mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode | ||
| { | ||
| for ( int j = mFrameItems.size(); j > i; --j ) | ||
| { | ||
| removeFrame( j - 1 ); | ||
| } | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| currentItem = mFrameItems.value( i ); | ||
| currentHeight = currentItem->rect().height(); | ||
| currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) ); | ||
| currentItem->update(); | ||
| currentY += currentHeight; | ||
| } | ||
|
|
||
| //at end of frames but there is still content left. Add other pages if ResizeMode == | ||
| if ( mResizeMode == ExtendToNextPage ) | ||
| { | ||
| while ( currentY < totalHeight ) | ||
| { | ||
| //find out on which page the lower left point of the last frame is | ||
| int page = currentItem->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() ); | ||
|
|
||
| //add new pages if necessary | ||
| if ( mComposition->numPages() < ( page + 2 ) ) | ||
| { | ||
| mComposition->setNumPages( page + 2 ); | ||
| } | ||
|
|
||
| //copy last frame | ||
| QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, currentItem->transform().dx(), currentItem->transform().dy() + mComposition->paperHeight() + mComposition->spaceBetweenPages(), | ||
| currentItem->rect().width(), currentItem->rect().height() ); | ||
| newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), newFrame->rect().height() ) ); | ||
| currentY += newFrame->rect().height(); | ||
| currentItem = newFrame; | ||
| addFrame( newFrame, false ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::handleFrameRemoval( QgsComposerItem* item ) | ||
| { | ||
| QgsComposerFrame* frame = dynamic_cast<QgsComposerFrame*>( item ); | ||
| if ( !frame ) | ||
| { | ||
| return; | ||
| } | ||
| int index = mFrameItems.indexOf( frame ); | ||
| if ( index == -1 ) | ||
| { | ||
| return; | ||
| } | ||
| mFrameItems.removeAt( index ); | ||
| if ( mFrameItems.size() > 0 ) | ||
| { | ||
| recalculateFrameSizes(); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::removeFrame( int i ) | ||
| { | ||
| QgsComposerFrame* frameItem = mFrameItems[i]; | ||
| if ( mComposition ) | ||
| { | ||
| mComposition->removeComposerItem( frameItem ); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::update() | ||
| { | ||
| QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin(); | ||
| for ( ; frameIt != mFrameItems.end(); ++frameIt ) | ||
| { | ||
| ( *frameIt )->update(); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrame::deleteFrames() | ||
| { | ||
| ResizeMode bkResizeMode = mResizeMode; | ||
| mResizeMode = UseExistingFrames; | ||
| mComposition->blockSignals( true ); | ||
| QList<QgsComposerFrame*>::iterator frameIt = mFrameItems.begin(); | ||
| for ( ; frameIt != mFrameItems.end(); ++frameIt ) | ||
| { | ||
| mComposition->removeComposerItem( *frameIt, false ); | ||
| delete *frameIt; | ||
| } | ||
| mComposition->blockSignals( false ); | ||
| mFrameItems.clear(); | ||
| mResizeMode = bkResizeMode; | ||
| } | ||
|
|
||
| bool QgsComposerMultiFrame::_writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames ) const | ||
| { | ||
| elem.setAttribute( "resizeMode", mResizeMode ); | ||
| if ( !ignoreFrames ) | ||
| { | ||
| QList<QgsComposerFrame*>::const_iterator frameIt = mFrameItems.constBegin(); | ||
| for ( ; frameIt != mFrameItems.constEnd(); ++frameIt ) | ||
| { | ||
| ( *frameIt )->writeXML( elem, doc ); | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| bool QgsComposerMultiFrame::_readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames ) | ||
| { | ||
| mResizeMode = ( ResizeMode )itemElem.attribute( "resizeMode", "0" ).toInt(); | ||
| if ( !ignoreFrames ) | ||
| { | ||
| QDomNodeList frameList = itemElem.elementsByTagName( "ComposerFrame" ); | ||
| for ( int i = 0; i < frameList.size(); ++i ) | ||
| { | ||
| QDomElement frameElem = frameList.at( i ).toElement(); | ||
| QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, 0, 0, 0, 0 ); | ||
| newFrame->readXML( frameElem, doc ); | ||
| addFrame( newFrame ); | ||
| } | ||
| } | ||
| return true; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| /*************************************************************************** | ||
| qgscomposermultiframe.h | ||
| ------------------------------------------------------------ | ||
| begin : July 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSCOMPOSERMULTIFRAME_H | ||
| #define QGSCOMPOSERMULTIFRAME_H | ||
|
|
||
| #include <QObject> | ||
| #include <QSizeF> | ||
|
|
||
| class QgsComposerFrame; | ||
| class QgsComposerItem; | ||
| class QgsComposition; | ||
| class QDomDocument; | ||
| class QDomElement; | ||
| class QRectF; | ||
| class QPainter; | ||
|
|
||
| /**Abstract base class for composer entries with the ability to distribute the content to several frames (items)*/ | ||
| class QgsComposerMultiFrame: public QObject | ||
| { | ||
| Q_OBJECT | ||
| public: | ||
|
|
||
| enum ResizeMode | ||
| { | ||
| UseExistingFrames = 0, | ||
| ExtendToNextPage //duplicates last frame to next page to fit the total size | ||
| }; | ||
|
|
||
| QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands ); | ||
| virtual ~QgsComposerMultiFrame(); | ||
| virtual QSizeF totalSize() const = 0; | ||
| virtual void render( QPainter* p, const QRectF& renderExtent ) = 0; | ||
|
|
||
| virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0; | ||
|
|
||
| void removeFrame( int i ); | ||
|
|
||
| void update(); | ||
|
|
||
| void setResizeMode( ResizeMode mode ); | ||
| ResizeMode resizeMode() const { return mResizeMode; } | ||
|
|
||
| virtual bool writeXML( QDomElement& elem, QDomDocument & doc, bool ignoreFrames = false ) const = 0; | ||
| bool _writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames = false ) const; | ||
|
|
||
| virtual bool readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false ) = 0; | ||
| bool _readXML( const QDomElement& itemElem, const QDomDocument& doc, bool ignoreFrames = false ); | ||
|
|
||
| QgsComposition* composition() { return mComposition; } | ||
|
|
||
| bool createUndoCommands() const { return mCreateUndoCommands; } | ||
| void setCreateUndoCommands( bool enabled ) { mCreateUndoCommands = enabled; } | ||
|
|
||
| /**Removes and deletes all frames from mComposition*/ | ||
| void deleteFrames(); | ||
|
|
||
| int nFrames() const { return mFrameItems.size(); } | ||
|
|
||
| protected: | ||
| QgsComposition* mComposition; | ||
| QList<QgsComposerFrame*> mFrameItems; | ||
| ResizeMode mResizeMode; | ||
| /**True: creates QgsMultiFrameCommands on internal changes (e.g. changing frames )*/ | ||
| bool mCreateUndoCommands; | ||
|
|
||
| protected slots: | ||
| void recalculateFrameSizes(); | ||
| /**Called before a frame is going to be removed (update frame list)*/ | ||
| void handleFrameRemoval( QgsComposerItem* item ); | ||
|
|
||
| private: | ||
| QgsComposerMultiFrame(); //forbidden | ||
|
|
||
| signals: | ||
| void changed(); | ||
| }; | ||
|
|
||
| #endif // QGSCOMPOSERMULTIFRAME_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| /*************************************************************************** | ||
| qgscomposermultiframecommand.cpp | ||
| -------------------------------- | ||
| begin : 2012-08-02 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgscomposermultiframecommand.h" | ||
| #include "qgscomposermultiframe.h" | ||
|
|
||
| QgsComposerMultiFrameCommand::QgsComposerMultiFrameCommand( QgsComposerMultiFrame* multiFrame, const QString& text, QUndoCommand* parent ): | ||
| QUndoCommand( text, parent ), mMultiFrame( multiFrame ), mFirstRun( true ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerMultiFrameCommand::QgsComposerMultiFrameCommand(): QUndoCommand( "", 0 ), mMultiFrame( 0 ), mFirstRun( false ) | ||
| { | ||
| } | ||
|
|
||
| QgsComposerMultiFrameCommand::~QgsComposerMultiFrameCommand() | ||
| { | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::undo() | ||
| { | ||
| restoreState( mPreviousState ); | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::redo() | ||
| { | ||
| if ( checkFirstRun() ) | ||
| { | ||
| return; | ||
| } | ||
| restoreState( mAfterState ); | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::savePreviousState() | ||
| { | ||
| saveState( mPreviousState ); | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::saveAfterState() | ||
| { | ||
| saveState( mAfterState ); | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::saveState( QDomDocument& stateDoc ) | ||
| { | ||
| if ( mMultiFrame ) | ||
| { | ||
| stateDoc.clear(); | ||
| QDomElement documentElement = stateDoc.createElement( "ComposerMultiFrameState" ); | ||
| mMultiFrame->writeXML( documentElement, stateDoc ); | ||
| stateDoc.appendChild( documentElement ); | ||
| } | ||
| } | ||
|
|
||
| void QgsComposerMultiFrameCommand::restoreState( QDomDocument& stateDoc ) | ||
| { | ||
| if ( mMultiFrame ) | ||
| { | ||
| mMultiFrame->readXML( stateDoc.documentElement().firstChild().toElement(), stateDoc ); | ||
| } | ||
| } | ||
|
|
||
| bool QgsComposerMultiFrameCommand::checkFirstRun() | ||
| { | ||
| if ( !mFirstRun ) | ||
| { | ||
| return false; | ||
| } | ||
| mFirstRun = false; | ||
| return true; | ||
| } | ||
|
|
||
| bool QgsComposerMultiFrameCommand::containsChange() const | ||
| { | ||
| return !( mPreviousState.isNull() || mAfterState.isNull() || mPreviousState.toString() == mAfterState.toString() ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /*************************************************************************** | ||
| qgscomposermultiframecommand.h | ||
| ------------------------------ | ||
| begin : 2012-08-02 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco dot hugentobler at sourcepole dot ch | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSCOMPOSERMULTIFRAMECOMMAND_H | ||
| #define QGSCOMPOSERMULTIFRAMECOMMAND_H | ||
|
|
||
| #include <QUndoCommand> | ||
| #include <QDomDocument> | ||
|
|
||
| class QgsComposerMultiFrame; | ||
|
|
||
| class QgsComposerMultiFrameCommand: public QUndoCommand | ||
| { | ||
| public: | ||
| QgsComposerMultiFrameCommand( QgsComposerMultiFrame* multiFrame, const QString& text, QUndoCommand* parent = 0 ); | ||
| ~QgsComposerMultiFrameCommand(); | ||
|
|
||
| void undo(); | ||
| void redo(); | ||
|
|
||
| void savePreviousState(); | ||
| void saveAfterState(); | ||
|
|
||
| /**Returns true if previous state and after state are valid and different*/ | ||
| bool containsChange() const; | ||
|
|
||
| private: | ||
| QgsComposerMultiFrame* mMultiFrame; | ||
|
|
||
| QDomDocument mPreviousState; | ||
| QDomDocument mAfterState; | ||
|
|
||
| bool mFirstRun; | ||
|
|
||
| QgsComposerMultiFrameCommand(); //forbidden | ||
| void saveState( QDomDocument& stateDoc ); | ||
| void restoreState( QDomDocument& stateDoc ); | ||
| bool checkFirstRun(); | ||
| }; | ||
|
|
||
| #endif // QGSCOMPOSERMULTIFRAMECOMMAND_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <ui version="4.0"> | ||
| <class>QgsComposerHtmlWidgetBase</class> | ||
| <widget class="QWidget" name="QgsComposerHtmlWidgetBase"> | ||
| <property name="geometry"> | ||
| <rect> | ||
| <x>0</x> | ||
| <y>0</y> | ||
| <width>243</width> | ||
| <height>116</height> | ||
| </rect> | ||
| </property> | ||
| <property name="windowTitle"> | ||
| <string>Form</string> | ||
| </property> | ||
| <layout class="QGridLayout" name="gridLayout_2"> | ||
| <item row="0" column="0"> | ||
| <widget class="QToolBox" name="mToolBox"> | ||
| <property name="currentIndex"> | ||
| <number>0</number> | ||
| </property> | ||
| <widget class="QWidget" name="page"> | ||
| <property name="geometry"> | ||
| <rect> | ||
| <x>0</x> | ||
| <y>0</y> | ||
| <width>225</width> | ||
| <height>72</height> | ||
| </rect> | ||
| </property> | ||
| <attribute name="label"> | ||
| <string>HTML</string> | ||
| </attribute> | ||
| <layout class="QGridLayout" name="gridLayout"> | ||
| <item row="1" column="2"> | ||
| <widget class="QToolButton" name="mFileToolButton"> | ||
| <property name="text"> | ||
| <string>...</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="1" column="1"> | ||
| <widget class="QLineEdit" name="mUrlLineEdit"/> | ||
| </item> | ||
| <item row="1" column="0"> | ||
| <widget class="QLabel" name="mUrlLabel"> | ||
| <property name="text"> | ||
| <string>URL</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="0" column="0"> | ||
| <widget class="QLabel" name="mResizeModeLabel"> | ||
| <property name="text"> | ||
| <string>Resize mode</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item row="0" column="1" colspan="2"> | ||
| <widget class="QComboBox" name="mResizeModeComboBox"/> | ||
| </item> | ||
| </layout> | ||
| </widget> | ||
| </widget> | ||
| </item> | ||
| </layout> | ||
| </widget> | ||
| <resources/> | ||
| <connections/> | ||
| </ui> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| /*************************************************************************** | ||
| testqgscomposerhtml.cpp | ||
| ----------------------- | ||
| begin : August 2012 | ||
| copyright : (C) 2012 by Marco Hugentobler | ||
| email : marco at sourcepole dot ch | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgscomposerhtml.h" | ||
| #include "qgscomposerframe.h" | ||
| #include "qgscomposition.h" | ||
| #include "qgscompositionchecker.h" | ||
| #include <QObject> | ||
| #include <QtTest> | ||
|
|
||
| class TestQgsComposerHtml: public QObject | ||
| { | ||
| Q_OBJECT; | ||
| private slots: | ||
| void initTestCase();// will be called before the first testfunction is executed. | ||
| void cleanupTestCase();// will be called after the last testfunction was executed. | ||
| void init();// will be called before each testfunction is executed. | ||
| void cleanup();// will be called after every testfunction. | ||
| void table(); //test if rendering of the composition with composr map is correct | ||
| void tableMultiFrame(); //tests multiframe capabilities of composer html | ||
| private: | ||
| QgsComposition* mComposition; | ||
| }; | ||
|
|
||
| void TestQgsComposerHtml::initTestCase() | ||
| { | ||
| mComposition = new QgsComposition( 0 ); | ||
| mComposition->setPaperSize( 297, 210 ); //A4 landscape | ||
| } | ||
|
|
||
| void TestQgsComposerHtml::cleanupTestCase() | ||
| { | ||
| delete mComposition; | ||
| } | ||
|
|
||
| void TestQgsComposerHtml::init() | ||
| { | ||
|
|
||
| } | ||
|
|
||
| void TestQgsComposerHtml::cleanup() | ||
| { | ||
|
|
||
| } | ||
|
|
||
| void TestQgsComposerHtml::table() | ||
| { | ||
| QgsComposerHtml* htmlItem = new QgsComposerHtml( mComposition, false ); | ||
| QgsComposerFrame* htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 ); | ||
| htmlItem->addFrame( htmlFrame ); | ||
| htmlItem->setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir::separator() + "html_table.html" ) ) ); | ||
| QgsCompositionChecker checker( "Composer html table", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() + | ||
| "control_images" + QDir::separator() + "expected_composerhtml" + QDir::separator() + "composerhtml_table.png" ) ); | ||
| bool result = checker.testComposition(); | ||
| mComposition->removeMultiFrame( htmlItem ); | ||
| delete htmlItem; | ||
| QVERIFY( result ); | ||
| } | ||
|
|
||
| void TestQgsComposerHtml::tableMultiFrame() | ||
| { | ||
| QgsComposerHtml* htmlItem = new QgsComposerHtml( mComposition, false ); | ||
| QgsComposerFrame* htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 10, 10, 100, 50 ); | ||
| htmlItem->addFrame( htmlFrame ); | ||
| htmlItem->setResizeMode( QgsComposerMultiFrame::ExtendToNextPage ); | ||
| bool result = true; | ||
| //page1 | ||
| htmlItem->setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir::separator() + "html_table.html" ) ) ); | ||
| QgsCompositionChecker checker1( "Composer html table", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() + | ||
| "control_images" + QDir::separator() + "expected_composerhtml" + QDir::separator() + "composerhtml_table_multiframe1.png" ) ); | ||
| if ( !checker1.testComposition( 0 ) ) | ||
| { | ||
| result = false; | ||
| } | ||
| //page2 | ||
| QgsCompositionChecker checker2( "Composer html table", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() + | ||
| "control_images" + QDir::separator() + "expected_composerhtml" + QDir::separator() + "composerhtml_table_multiframe2.png" ) ); | ||
| if ( !checker2.testComposition( 1 ) ) | ||
| { | ||
| result = false; | ||
| } | ||
| //page 3 | ||
| QgsCompositionChecker checker3( "Composer html table", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() + | ||
| "control_images" + QDir::separator() + "expected_composerhtml" + QDir::separator() + "composerhtml_table_multiframe3.png" ) ); | ||
| if ( !checker3.testComposition( 2 ) ) | ||
| { | ||
| result = false; | ||
| } | ||
|
|
||
| mComposition->removeMultiFrame( htmlItem ); | ||
| delete htmlItem; | ||
| QVERIFY( result ); | ||
| } | ||
|
|
||
|
|
||
| QTEST_MAIN( TestQgsComposerHtml ) | ||
| #include "moc_testqgscomposerhtml.cxx" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <table border="1" style="font-size:12pt; "> | ||
| <tbody> | ||
| <tr><td>1 Foo data</td><td>Bar data</td></tr> | ||
| <tr><td>2 Foo data</td><td>Bar data</td></tr> | ||
| <tr><td>3 Foo data</td><td>Bar data</td></tr> | ||
| <tr><td>4 Foo data</td><td>Bar data</td></tr> | ||
| <tr><td>5 Foo data</td><td>Bar data</td></tr> | ||
| </tbody> | ||
| </table> | ||
| <table> |