Skip to content

Commit

Permalink
Allow the use of expressions inside a composer label
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugo Mercier committed Sep 26, 2012
1 parent cc452d1 commit f076c2e
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 17 deletions.
3 changes: 3 additions & 0 deletions src/app/composer/qgscomposer.cpp
Expand Up @@ -650,6 +650,7 @@ void QgsComposer::on_mActionExportAsPDF_triggered()

if ( progress.wasCanceled() )
{
atlasRender.end();
break;
}
try
Expand Down Expand Up @@ -717,6 +718,7 @@ void QgsComposer::on_mActionPrint_triggered()

if ( progress.wasCanceled() )
{
atlasRender.end();
break;
}
try
Expand Down Expand Up @@ -893,6 +895,7 @@ void QgsComposer::on_mActionExportAsImage_triggered()

if ( progress.wasCanceled() )
{
atlasRender.end();
break;
}
try
Expand Down
29 changes: 29 additions & 0 deletions src/app/composer/qgscomposerlabelwidget.cpp
Expand Up @@ -18,6 +18,8 @@
#include "qgscomposerlabelwidget.h"
#include "qgscomposerlabel.h"
#include "qgscomposeritemwidget.h"
#include "qgsexpressionbuilderdialog.h"

#include <QColorDialog>
#include <QFontDialog>
#include <QWidget>
Expand Down Expand Up @@ -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 )
Expand Down
1 change: 1 addition & 0 deletions src/app/composer/qgscomposerlabelwidget.h
Expand Up @@ -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();
Expand Down
15 changes: 12 additions & 3 deletions src/core/composer/qgscomposerlabel.cpp
Expand Up @@ -16,12 +16,15 @@
***************************************************************************/

#include "qgscomposerlabel.h"
#include "qgsexpression.h"
#include <QDate>
#include <QDomElement>
#include <QPainter>

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 );
Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions src/core/composer/qgscomposerlabel.h
Expand Up @@ -19,6 +19,9 @@

#include "qgscomposeritem.h"

class QgsVectorLayer;
class QgsFeature;

/** \ingroup MapComposer
* A label that can be placed onto a map composition.
*/
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
53 changes: 51 additions & 2 deletions src/core/composer/qgscomposition.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -57,6 +58,8 @@ struct QgsAtlasRendering::QgsAtlasRenderingImpl
QgsRectangle origExtent;
bool restoreLayer;
std::auto_ptr<QgsExpression> filenameExpr;
size_t pageNumber;
size_t numberOfPages;
};

QgsAtlasRendering::QgsAtlasRendering( QgsComposition* composition )
Expand Down Expand Up @@ -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 )
Expand All @@ -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() )
{
Expand Down Expand Up @@ -204,21 +212,42 @@ void QgsAtlasRendering::prepareForFeature( size_t featureI )
new_extent.scale( 1 + impl->composition->atlasMap()->atlasMargin() );
}
}
impl->composition->atlasMap()->setNewExtent( new_extent );

// evaluate label expressions
QList<QgsComposerLabel*> labels;
impl->composition->composerItems( labels );
QgsExpression::setSpecialColumn( "$feature", QVariant( (int)featureI + 1 ) );
for ( QList<QgsComposerLabel*>::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
{
return impl->nFeatures;
}

QString QgsAtlasRendering::currentFilename() const
const QString& QgsAtlasRendering::currentFilename() const
{
return impl->currentFilename;
}

void QgsAtlasRendering::end()
{
// reset label expression contexts
QList<QgsComposerLabel*> labels;
impl->composition->composerItems( labels );
for ( QList<QgsComposerLabel*>::iterator lit = labels.begin(); lit != labels.end(); ++lit )
{
(*lit)->setExpressionContext( 0, 0 );
}

// restore the coverage visibility
if ( impl->restoreLayer )
{
Expand All @@ -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():
Expand All @@ -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()
Expand Down Expand Up @@ -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<QgsComposerItem*> QgsComposition::selectedComposerItems()
{
QList<QgsComposerItem*> composerItemList;
Expand Down
9 changes: 8 additions & 1 deletion src/core/composer/qgscomposition.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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<QgsComposerItem*> selectedComposerItems();

/**Returns pointers to all composer maps in the scene*/
Expand Down
7 changes: 7 additions & 0 deletions src/gui/qgsexpressionbuilderwidget.cpp
Expand Up @@ -97,6 +97,13 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
registerItem( func.mGroup, func.mName, " " + name + " " );
}

QList<QgsExpression::FunctionDef> 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
Expand Down
29 changes: 18 additions & 11 deletions src/ui/qgscomposerlabelwidgetbase.ui
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>274</width>
<height>488</height>
<width>307</width>
<height>525</height>
</rect>
</property>
<property name="sizePolicy">
Expand All @@ -30,8 +30,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>271</width>
<height>470</height>
<width>276</width>
<height>503</height>
</rect>
</property>
<attribute name="label">
Expand All @@ -45,14 +45,14 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="mFontColorButton">
<property name="text">
<string>Font color...</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="buttonGroup1">
<property name="title">
<string>Horizontal Alignment:</string>
Expand Down Expand Up @@ -98,7 +98,7 @@
</layout>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QGroupBox" name="buttonGroup2">
<property name="title">
<string>Vertical Alignment:</string>
Expand Down Expand Up @@ -141,7 +141,7 @@
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="QDoubleSpinBox" name="mMarginDoubleSpinBox">
<property name="prefix">
<string>Margin </string>
Expand All @@ -151,7 +151,7 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="mRotationLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
Expand All @@ -170,14 +170,14 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="QDoubleSpinBox" name="mRotationSpinBox">
<property name="maximum">
<double>360.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<item row="2" column="0" colspan="2">
<widget class="QPushButton" name="mFontButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand All @@ -190,6 +190,13 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="mInsertExpressionButton">
<property name="text">
<string>Insert an expression</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
Expand Down

0 comments on commit f076c2e

Please sign in to comment.