From 93fa94f913556e9d6eb77b6642ac76e3cc680e35 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 7 May 2014 07:54:07 +1000 Subject: [PATCH] [FEATURE][composer] Add button to create new frame when using composer items in Use Existing Frames mode --- .../core/composer/qgscomposermultiframe.sip | 28 +++++++++++- python/core/composer/qgscomposition.sip | 5 +++ src/app/composer/qgscomposerhtmlwidget.cpp | 27 ++++++++++++ src/app/composer/qgscomposerhtmlwidget.h | 1 + src/core/composer/qgscomposermultiframe.cpp | 44 +++++++++++++------ src/core/composer/qgscomposermultiframe.h | 23 +++++++++- src/core/composer/qgscomposition.cpp | 7 +++ src/core/composer/qgscomposition.h | 5 +++ src/ui/qgscomposerhtmlwidgetbase.ui | 27 ++++++------ 9 files changed, 137 insertions(+), 30 deletions(-) diff --git a/python/core/composer/qgscomposermultiframe.sip b/python/core/composer/qgscomposermultiframe.sip index b12859f1aa56..00ae5387a609 100644 --- a/python/core/composer/qgscomposermultiframe.sip +++ b/python/core/composer/qgscomposermultiframe.sip @@ -22,6 +22,13 @@ class QgsComposerMultiFrame: QObject virtual void addFrame( QgsComposerFrame* frame, bool recalcFrameSizes = true ) = 0; + /**Finds the optimal position to break a frame at. + * @param yPos maximum vertical position for break + * @returns the optimal breakable position which occurs in the multi frame close + * to and before the specified yPos + * @note added in version 2.3*/ + virtual double findNearbyPageBreak( double yPos ); + void removeFrame( int i ); void update(); @@ -49,8 +56,27 @@ class QgsComposerMultiFrame: QObject int frameCount() const; QgsComposerFrame* frame( int i ); - protected slots: + /**Creates a new frame and adds it to the multi frame and composition. + * @param currentFrame an existing QgsComposerFrame from which to copy the size + * and general frame properties (eg frame style, background, rendering settings). + * @param pos position of top-left corner of the new frame + * @param size size of the new frame + * @returns new QgsComposerFrame + * @note added in version 2.3 + */ + QgsComposerFrame* createNewFrame(QgsComposerFrame* currentFrame, QPointF pos, QSizeF size); + + public slots: + + /**Recalculates the portion of the multiframe item which is shown in each of it's + * component frames. If the resize mode is set to anything but UseExistingFrames then + * this may cause new frames to be added or frames to be removed, in order to fit + * the current size of the multiframe's content. + */ void recalculateFrameSizes(); + + protected slots: + /**Called before a frame is going to be removed (update frame list)*/ void handleFrameRemoval( QgsComposerItem* item ); /**Adapts to changed number of pages if resize type is RepeatOnEveryPage*/ diff --git a/python/core/composer/qgscomposition.sip b/python/core/composer/qgscomposition.sip index 5d1f72546dab..17c0eea242b2 100644 --- a/python/core/composer/qgscomposition.sip +++ b/python/core/composer/qgscomposition.sip @@ -413,6 +413,11 @@ class QgsComposition : QGraphicsScene * to refresh their contents. @note added in version 2.3*/ void refreshItems(); + + /**Clears any selected items and sets an item as the current selection. + * @param item item to set as selected + * @note added in version 2.3*/ + void setSelectedItem( QgsComposerItem* item ); protected: void init(); diff --git a/src/app/composer/qgscomposerhtmlwidget.cpp b/src/app/composer/qgscomposerhtmlwidget.cpp index f969b49c0474..7caef5ee73ee 100644 --- a/src/app/composer/qgscomposerhtmlwidget.cpp +++ b/src/app/composer/qgscomposerhtmlwidget.cpp @@ -113,6 +113,8 @@ void QgsComposerHtmlWidget::on_mResizeModeComboBox_currentIndexChanged( int inde mHtml->setResizeMode(( QgsComposerMultiFrame::ResizeMode )mResizeModeComboBox->itemData( index ).toInt() ); composition->endMultiFrameCommand(); } + + mAddFramePushButton->setEnabled( mHtml->resizeMode() == QgsComposerMultiFrame::UseExistingFrames ); } void QgsComposerHtmlWidget::on_mUseSmartBreaksCheckBox_stateChanged( int state ) @@ -143,6 +145,29 @@ void QgsComposerHtmlWidget::on_mReloadPushButton_clicked() mHtml->loadHtml(); } +void QgsComposerHtmlWidget::on_mAddFramePushButton_clicked() +{ + if ( !mHtml || !mFrame ) + { + return; + } + + //create a new frame based on the current frame + QPointF pos = mFrame->pos(); + //shift new frame so that it sits 10 units below current frame + pos.ry() += mFrame->rect().height() + 10; + + QgsComposerFrame * newFrame = mHtml->createNewFrame( mFrame, pos, mFrame->rect().size() ); + mHtml->recalculateFrameSizes(); + + //set new frame as selection + QgsComposition* composition = mHtml->composition(); + if ( composition ) + { + composition->setSelectedItem( newFrame ); + } +} + void QgsComposerHtmlWidget::setGuiElementValues() { if ( !mHtml ) @@ -154,5 +179,7 @@ void QgsComposerHtmlWidget::setGuiElementValues() mUrlLineEdit->setText( mHtml->url().toString() ); mResizeModeComboBox->setCurrentIndex( mResizeModeComboBox->findData( mHtml->resizeMode() ) ); mUseSmartBreaksCheckBox->setChecked( mHtml->useSmartBreaks() ); + + mAddFramePushButton->setEnabled( mHtml->resizeMode() == QgsComposerMultiFrame::UseExistingFrames ); blockSignals( false ); } diff --git a/src/app/composer/qgscomposerhtmlwidget.h b/src/app/composer/qgscomposerhtmlwidget.h index b3e62f227391..f2b1e36fe44b 100644 --- a/src/app/composer/qgscomposerhtmlwidget.h +++ b/src/app/composer/qgscomposerhtmlwidget.h @@ -33,6 +33,7 @@ class QgsComposerHtmlWidget: public QWidget, private Ui::QgsComposerHtmlWidgetBa void on_mResizeModeComboBox_currentIndexChanged( int index ); void on_mUseSmartBreaksCheckBox_stateChanged( int state ); void on_mReloadPushButton_clicked(); + void on_mAddFramePushButton_clicked(); /**Sets the GUI elements to the values of mHtmlItem*/ void setGuiElementValues(); diff --git a/src/core/composer/qgscomposermultiframe.cpp b/src/core/composer/qgscomposermultiframe.cpp index 3cd1ee1e85d8..5b61587dae35 100644 --- a/src/core/composer/qgscomposermultiframe.cpp +++ b/src/core/composer/qgscomposermultiframe.cpp @@ -137,9 +137,12 @@ void QgsComposerMultiFrame::recalculateFrameSizes() { newFrameY += currentItem->pos().y() - ( page - 1 ) * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() ); } - QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, currentItem->pos().x(), - newFrameY, - currentItem->rect().width(), frameHeight ); + + //create new frame + QgsComposerFrame* newFrame = createNewFrame( currentItem, + QPointF( currentItem->pos().x(), newFrameY ), + QSizeF( currentItem->rect().width(), frameHeight ) ); + if ( mResizeMode == RepeatOnEveryPage ) { newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) ); @@ -148,23 +151,36 @@ void QgsComposerMultiFrame::recalculateFrameSizes() { newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), newFrame->rect().height() ) ); } - - //copy some settings from the parent frame - newFrame->setBackgroundColor( currentItem->backgroundColor() ); - newFrame->setBackgroundEnabled( currentItem->hasBackground() ); - newFrame->setBlendMode( currentItem->blendMode() ); - newFrame->setFrameEnabled( currentItem->hasFrame() ); - newFrame->setFrameJoinStyle( currentItem->frameJoinStyle() ); - newFrame->setFrameOutlineWidth( currentItem->frameOutlineWidth() ); - newFrame->setOpacity( currentItem->opacity() ); - currentY += frameHeight; currentItem = newFrame; - addFrame( newFrame, false ); } } } +QgsComposerFrame* QgsComposerMultiFrame::createNewFrame( QgsComposerFrame* currentFrame, QPointF pos, QSizeF size ) +{ + if ( !currentFrame ) + { + return 0; + } + + QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, pos.x(), + pos.y(), size.width(), size.height() ); + + //copy some settings from the parent frame + newFrame->setBackgroundColor( currentFrame->backgroundColor() ); + newFrame->setBackgroundEnabled( currentFrame->hasBackground() ); + newFrame->setBlendMode( currentFrame->blendMode() ); + newFrame->setFrameEnabled( currentFrame->hasFrame() ); + newFrame->setFrameJoinStyle( currentFrame->frameJoinStyle() ); + newFrame->setFrameOutlineWidth( currentFrame->frameOutlineWidth() ); + newFrame->setOpacity( currentFrame->opacity() ); + + addFrame( newFrame, false ); + + return newFrame; +} + void QgsComposerMultiFrame::handleFrameRemoval( QgsComposerItem* item ) { QgsComposerFrame* frame = dynamic_cast( item ); diff --git a/src/core/composer/qgscomposermultiframe.h b/src/core/composer/qgscomposermultiframe.h index f4949c06a9ba..e7fe3fa1c6c5 100644 --- a/src/core/composer/qgscomposermultiframe.h +++ b/src/core/composer/qgscomposermultiframe.h @@ -18,6 +18,7 @@ #include #include +#include class QgsComposerFrame; class QgsComposerItem; @@ -52,7 +53,7 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject * @param yPos maximum vertical position for break * @returns the optimal breakable position which occurs in the multi frame close * to and before the specified yPos - * Note: added in version 2.3*/ + * @note added in version 2.3*/ virtual double findNearbyPageBreak( double yPos ) { return yPos; } void removeFrame( int i ); @@ -82,6 +83,25 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject int frameCount() const { return mFrameItems.size(); } QgsComposerFrame* frame( int i ) const; + /**Creates a new frame and adds it to the multi frame and composition. + * @param currentFrame an existing QgsComposerFrame from which to copy the size + * and general frame properties (eg frame style, background, rendering settings). + * @param pos position of top-left corner of the new frame + * @param size size of the new frame + * @returns new QgsComposerFrame + * @note added in version 2.3 + */ + QgsComposerFrame* createNewFrame( QgsComposerFrame* currentFrame, QPointF pos, QSizeF size ); + + public slots: + + /**Recalculates the portion of the multiframe item which is shown in each of it's + * component frames. If the resize mode is set to anything but UseExistingFrames then + * this may cause new frames to be added or frames to be removed, in order to fit + * the current size of the multiframe's content. + */ + void recalculateFrameSizes(); + protected: QgsComposition* mComposition; QList mFrameItems; @@ -90,7 +110,6 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject bool mCreateUndoCommands; protected slots: - void recalculateFrameSizes(); /**Called before a frame is going to be removed (update frame list)*/ void handleFrameRemoval( QgsComposerItem* item ); /**Adapts to changed number of pages if resize type is RepeatOnEveryPage*/ diff --git a/src/core/composer/qgscomposition.cpp b/src/core/composer/qgscomposition.cpp index 21742e2921bc..4d4e52fad388 100644 --- a/src/core/composer/qgscomposition.cpp +++ b/src/core/composer/qgscomposition.cpp @@ -186,6 +186,13 @@ void QgsComposition::refreshItems() emit refreshItemsTriggered(); } +void QgsComposition::setSelectedItem( QgsComposerItem *item ) +{ + clearSelection(); + item->setSelected( true ); + emit selectedItemChanged( item ); +} + QRectF QgsComposition::compositionBounds() const { //start with an empty rectangle diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h index a1ac7960d0d5..d12820209bbb 100644 --- a/src/core/composer/qgscomposition.h +++ b/src/core/composer/qgscomposition.h @@ -470,6 +470,11 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene @note added in version 2.3*/ void refreshItems(); + /**Clears any selected items and sets an item as the current selection. + * @param item item to set as selected + * @note added in version 2.3*/ + void setSelectedItem( QgsComposerItem* item ); + protected: void init(); diff --git a/src/ui/qgscomposerhtmlwidgetbase.ui b/src/ui/qgscomposerhtmlwidgetbase.ui index be4705971b62..ea0e69bdda30 100644 --- a/src/ui/qgscomposerhtmlwidgetbase.ui +++ b/src/ui/qgscomposerhtmlwidgetbase.ui @@ -63,12 +63,6 @@ false - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - @@ -93,7 +87,14 @@ - + + + + Refresh HTML + + + + Resize mode @@ -103,20 +104,20 @@ - + - + - Use smart page breaks + Add Frame - - + + - Refresh HTML + Use smart page breaks