diff --git a/src/app/composer/qgscomposer.cpp b/src/app/composer/qgscomposer.cpp index 9ed4266f1fc..809859bab87 100644 --- a/src/app/composer/qgscomposer.cpp +++ b/src/app/composer/qgscomposer.cpp @@ -650,6 +650,7 @@ void QgsComposer::on_mActionExportAsPDF_triggered() if ( progress.wasCanceled() ) { + atlasRender.end(); break; } try @@ -717,6 +718,7 @@ void QgsComposer::on_mActionPrint_triggered() if ( progress.wasCanceled() ) { + atlasRender.end(); break; } try @@ -893,6 +895,7 @@ void QgsComposer::on_mActionExportAsImage_triggered() if ( progress.wasCanceled() ) { + atlasRender.end(); break; } try diff --git a/src/app/composer/qgscomposerlabelwidget.cpp b/src/app/composer/qgscomposerlabelwidget.cpp index ac25c877f5a..180360d8f2a 100644 --- a/src/app/composer/qgscomposerlabelwidget.cpp +++ b/src/app/composer/qgscomposerlabelwidget.cpp @@ -18,6 +18,8 @@ #include "qgscomposerlabelwidget.h" #include "qgscomposerlabel.h" #include "qgscomposeritemwidget.h" +#include "qgsexpressionbuilderdialog.h" + #include #include #include @@ -98,6 +100,33 @@ void QgsComposerLabelWidget::on_mFontColorButton_clicked() mComposerLabel->endCommand(); } +void QgsComposerLabelWidget::on_mInsertExpressionButton_clicked() +{ + if ( !mComposerLabel) + { + return; + } + + QString selText = mTextEdit->textCursor().selectedText(); + + // edit the selected expression if there's one + if ( selText.startsWith( "[%" ) && selText.endsWith( "%]" ) ) + selText = selText.mid( 2, selText.size() - 4 ); + + QgsExpressionBuilderDialog exprDlg( /* layer = */ 0, selText, this ); + exprDlg.setWindowTitle( tr( "Insert expression" ) ); + if ( exprDlg.exec() == QDialog::Accepted ) + { + QString expression = exprDlg.expressionText(); + if ( !expression.isEmpty() ) + { + mComposerLabel->beginCommand( tr( "Insert expression" ) ); + mTextEdit->insertPlainText( "[%" + expression + "%]" ); + mComposerLabel->endCommand(); + } + } +} + void QgsComposerLabelWidget::on_mCenterRadioButton_clicked() { if ( mComposerLabel ) diff --git a/src/app/composer/qgscomposerlabelwidget.h b/src/app/composer/qgscomposerlabelwidget.h index 22caf341730..5ae989016d5 100644 --- a/src/app/composer/qgscomposerlabelwidget.h +++ b/src/app/composer/qgscomposerlabelwidget.h @@ -34,6 +34,7 @@ class QgsComposerLabelWidget: public QWidget, private Ui::QgsComposerLabelWidget public slots: void on_mTextEdit_textChanged(); void on_mFontButton_clicked(); + void on_mInsertExpressionButton_clicked(); void on_mMarginDoubleSpinBox_valueChanged( double d ); void on_mFontColorButton_clicked(); void on_mCenterRadioButton_clicked(); diff --git a/src/core/composer/qgscomposerlabel.cpp b/src/core/composer/qgscomposerlabel.cpp index 89c88677e61..9aacbce6710 100644 --- a/src/core/composer/qgscomposerlabel.cpp +++ b/src/core/composer/qgscomposerlabel.cpp @@ -16,12 +16,15 @@ ***************************************************************************/ #include "qgscomposerlabel.h" +#include "qgsexpression.h" #include #include #include -QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ): QgsComposerItem( composition ), mMargin( 1.0 ), mFontColor( QColor( 0, 0, 0 ) ), - mHAlignment( Qt::AlignLeft ), mVAlignment( Qt::AlignTop ) +QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ): + QgsComposerItem( composition ), mMargin( 1.0 ), mFontColor( QColor( 0, 0, 0 ) ), + mHAlignment( Qt::AlignLeft ), mVAlignment( Qt::AlignTop ), + mExpressionFeature( 0 ), mExpressionLayer( 0 ) { //default font size is 10 point mFont.setPointSizeF( 10 ); @@ -75,11 +78,17 @@ void QgsComposerLabel::setText( const QString& text ) emit itemChanged(); } +void QgsComposerLabel::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer ) +{ + mExpressionFeature = feature; + mExpressionLayer = layer; +} + QString QgsComposerLabel::displayText() const { QString displayText = mText; replaceDateText( displayText ); - return displayText; + return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer ); } void QgsComposerLabel::replaceDateText( QString& text ) const diff --git a/src/core/composer/qgscomposerlabel.h b/src/core/composer/qgscomposerlabel.h index 603545f2e41..45ecb5f9568 100644 --- a/src/core/composer/qgscomposerlabel.h +++ b/src/core/composer/qgscomposerlabel.h @@ -19,6 +19,9 @@ #include "qgscomposeritem.h" +class QgsVectorLayer; +class QgsFeature; + /** \ingroup MapComposer * A label that can be placed onto a map composition. */ @@ -45,6 +48,8 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem @note this function was added in version 1.2*/ QString displayText() const; + void setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer ); + QFont font() const; void setFont( const QFont& f ); /** Accessor for the vertical alignment of the label @@ -120,6 +125,9 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem double mTextBoxWidth; /**Height of the text box. This is different to rectangle().height() in case there is rotation*/ double mTextBoxHeight; + + QgsFeature* mExpressionFeature; + QgsVectorLayer* mExpressionLayer; }; #endif diff --git a/src/core/composer/qgscomposition.cpp b/src/core/composer/qgscomposition.cpp index 1c11b6a8d9d..e563a5b3839 100644 --- a/src/core/composer/qgscomposition.cpp +++ b/src/core/composer/qgscomposition.cpp @@ -28,6 +28,7 @@ #include "qgscomposerpicture.h" #include "qgscomposerscalebar.h" #include "qgscomposershape.h" +#include "qgscomposerlabel.h" #include "qgscomposerattributetable.h" #include "qgsaddremovemultiframecommand.h" #include "qgscomposermultiframecommand.h" @@ -57,6 +58,8 @@ struct QgsAtlasRendering::QgsAtlasRenderingImpl QgsRectangle origExtent; bool restoreLayer; std::auto_ptr filenameExpr; + size_t pageNumber; + size_t numberOfPages; }; QgsAtlasRendering::QgsAtlasRendering( QgsComposition* composition ) @@ -125,6 +128,10 @@ void QgsAtlasRendering::begin( const QString& filenamePattern ) layerSet.removeAt( removeAt ); } } + + // special columns for expressions + QgsExpression::setSpecialColumn( "$numfeatures", QVariant( (int)impl->nFeatures ) ); + QgsExpression::setSpecialColumn( "$numpages", QVariant( (int)impl->composition->numPages() ) ); } void QgsAtlasRendering::prepareForFeature( size_t featureI ) @@ -133,6 +140,7 @@ void QgsAtlasRendering::prepareForFeature( size_t featureI ) if ( impl->filenamePattern.size() > 0 ) { + QgsExpression::setSpecialColumn( "$feature", QVariant( (int)featureI + 1 ) ); QVariant filenameRes = impl->filenameExpr->evaluate( &*fit ); if ( impl->filenameExpr->hasEvalError() ) { @@ -204,7 +212,20 @@ void QgsAtlasRendering::prepareForFeature( size_t featureI ) new_extent.scale( 1 + impl->composition->atlasMap()->atlasMargin() ); } } - impl->composition->atlasMap()->setNewExtent( new_extent ); + + // evaluate label expressions + QList labels; + impl->composition->composerItems( labels ); + QgsExpression::setSpecialColumn( "$feature", QVariant( (int)featureI + 1 ) ); + for ( QList::iterator lit = labels.begin(); lit != labels.end(); ++lit ) + { + QgsExpression::setSpecialColumn( "$page", QVariant( (int)impl->composition->itemPageNumber( *lit ) + 1 ) ); + (*lit)->setExpressionContext( fit, impl->composition->atlasMap()->atlasCoverageLayer() ); + } + + + // set the new extent (and render) + impl->composition->atlasMap()->setNewExtent( new_extent ); } size_t QgsAtlasRendering::numFeatures() const @@ -212,13 +233,21 @@ size_t QgsAtlasRendering::numFeatures() const return impl->nFeatures; } -QString QgsAtlasRendering::currentFilename() const +const QString& QgsAtlasRendering::currentFilename() const { return impl->currentFilename; } void QgsAtlasRendering::end() { + // reset label expression contexts + QList labels; + impl->composition->composerItems( labels ); + for ( QList::iterator lit = labels.begin(); lit != labels.end(); ++lit ) + { + (*lit)->setExpressionContext( 0, 0 ); + } + // restore the coverage visibility if ( impl->restoreLayer ) { @@ -242,6 +271,11 @@ QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer ) : mPrintResolution = 300; //hardcoded default loadSettings(); + + QgsExpression::setSpecialColumn( "$page", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$feature", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$numpages", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$numfeatures", QVariant((int)0) ); } QgsComposition::QgsComposition(): @@ -250,6 +284,11 @@ QgsComposition::QgsComposition(): mAtlasMap( 0 ) { loadSettings(); + + QgsExpression::setSpecialColumn( "$page", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$feature", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$numpages", QVariant((int)0) ); + QgsExpression::setSpecialColumn( "$numfeatures", QVariant((int)0) ); } QgsComposition::~QgsComposition() @@ -341,6 +380,16 @@ QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position ) return 0; } +int QgsComposition::pageNumberAt( const QPointF& position ) const +{ + return position.y() / (paperHeight() + spaceBetweenPages() ); +} + +int QgsComposition::itemPageNumber( const QgsComposerItem* item ) const +{ + return pageNumberAt( QPointF( item->transform().dx(), item->transform().dy()) ); +} + QList QgsComposition::selectedComposerItems() { QList composerItemList; diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h index 223de4f8af5..de2f0a5c043 100644 --- a/src/core/composer/qgscomposition.h +++ b/src/core/composer/qgscomposition.h @@ -59,7 +59,8 @@ class QgsAtlasRendering size_t numFeatures() const; void prepareForFeature( size_t i ); - QString currentFilename() const; + + const QString& currentFilename() const; private: struct QgsAtlasRenderingImpl; @@ -136,6 +137,12 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene /**Returns the topmost composer item. Ignores mPaperItem*/ QgsComposerItem* composerItemAt( const QPointF & position ); + /** Returns the page number (0-bsaed) given a coordinate */ + int pageNumberAt( const QPointF& position ) const; + + /** Returns on which page number (0-based) is displayed an item */ + int itemPageNumber( const QgsComposerItem* ) const; + QList selectedComposerItems(); /**Returns pointers to all composer maps in the scene*/ diff --git a/src/gui/qgsexpressionbuilderwidget.cpp b/src/gui/qgsexpressionbuilderwidget.cpp index 2c81cd1b663..727e57eaddd 100644 --- a/src/gui/qgsexpressionbuilderwidget.cpp +++ b/src/gui/qgsexpressionbuilderwidget.cpp @@ -97,6 +97,13 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent ) registerItem( func.mGroup, func.mName, " " + name + " " ); } + QList specials = QgsExpression::specialColumns(); + for ( int i = 0; i < specials.size(); ++i ) + { + QString name = specials[i].mName; + registerItem( specials[i].mGroup, name, " " + name + " " ); + } + #if QT_VERSION >= 0x040700 txtSearchEdit->setPlaceholderText( tr( "Search" ) ); #endif diff --git a/src/ui/qgscomposerlabelwidgetbase.ui b/src/ui/qgscomposerlabelwidgetbase.ui index 9cd8ce9cfe7..638530c00b2 100644 --- a/src/ui/qgscomposerlabelwidgetbase.ui +++ b/src/ui/qgscomposerlabelwidgetbase.ui @@ -6,8 +6,8 @@ 0 0 - 274 - 488 + 307 + 525 @@ -30,8 +30,8 @@ 0 0 - 271 - 470 + 276 + 503 @@ -45,14 +45,14 @@ - + Font color... - + Horizontal Alignment: @@ -98,7 +98,7 @@ - + Vertical Alignment: @@ -141,7 +141,7 @@ - + Margin @@ -151,7 +151,7 @@ - + @@ -170,14 +170,14 @@ - + 360.000000000000000 - + @@ -190,6 +190,13 @@ + + + + Insert an expression + + +