Skip to content
Permalink
Browse files

Merge branch 'master', remote-tracking branch 'nathan/expression-labels'

  • Loading branch information
wonder-sk committed Oct 20, 2011
2 parents 3a15509 + 665e92e commit 847204e17a1ec0f90ab1c0286eceb4a2e129c106
@@ -24,18 +24,21 @@

#include "qgspallabeling.h"
#include "qgslabelengineconfigdialog.h"
#include "qgsexpressionbuilderdialog.h"
#include "qgsexpression.h"

#include <QColorDialog>
#include <QFontDialog>

#include <QTextEdit>
#include <iostream>
#include <QApplication>


#include <QMessageBox>

QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QWidget* parent )
: QDialog( parent ), mLBL( lbl ), mLayer( layer ), mMapCanvas( mapCanvas )
{
if ( !layer ) return;

setupUi( this );

connect( btnTextColor, SIGNAL( clicked() ), this, SLOT( changeTextColor() ) );
@@ -44,6 +47,7 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
connect( btnBufferColor, SIGNAL( clicked() ), this, SLOT( changeBufferColor() ) );
connect( spinBufferSize, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
connect( btnEngineSettings, SIGNAL( clicked() ), this, SLOT( showEngineConfigDialog() ) );
connect( btnExpression, SIGNAL(clicked()), this, SLOT( showExpressionDialog()));

// set placement methods page based on geometry type
switch ( layer->geometryType() )
@@ -61,19 +65,27 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
Q_ASSERT( 0 && "NOOOO!" );
}

//mTabWidget->setEnabled( chkEnableLabeling->isChecked() );
chkMergeLines->setEnabled( layer->geometryType() == QGis::Line );
chkAddDirectionSymbol->setEnabled( layer->geometryType() == QGis::Line );
label_19->setEnabled( layer->geometryType() != QGis::Point );
mMinSizeSpinBox->setEnabled( layer->geometryType() != QGis::Point );

populateFieldNames();

// load labeling settings from layer
QgsPalLayerSettings lyr;
lyr.readFromLayer( layer );

populateFieldNames();
populateDataDefinedCombos( lyr );

chkEnableLabeling->setChecked( lyr.enabled );
mTabWidget->setEnabled( lyr.enabled );
cboFieldName->setEnabled( lyr.enabled );
btnExpression->setEnabled( lyr.enabled );

//Add the current expression to the bottom of the list.
if (lyr.isExpression && !lyr.fieldName.isEmpty())
cboFieldName->addItem(lyr.fieldName);

// placement
int distUnitIndex = lyr.distInMapUnits ? 1 : 0;
switch ( lyr.placement )
@@ -200,18 +212,22 @@ QgsLabelingGui::~QgsLabelingGui()

void QgsLabelingGui::apply()
{
layerSettings().writeToLayer( mLayer );
// trigger refresh
if ( mMapCanvas )
{
mMapCanvas->refresh();
}
QgsPalLayerSettings settings = layerSettings();
settings.writeToLayer( mLayer );
// trigger refresh
if ( mMapCanvas )
{
mMapCanvas->refresh();
}
}

QgsPalLayerSettings QgsLabelingGui::layerSettings()
{
QgsPalLayerSettings lyr;
lyr.fieldName = cboFieldName->currentText();
// Check if we are an expression. Also treats expressions with just a column name as non expressions,
// this saves time later so we don't have to parse the expression tree.
lyr.isExpression = mLayer->fieldNameIndex( lyr.fieldName ) == -1 && !lyr.fieldName.isEmpty();

lyr.dist = 0;
lyr.placementFlags = 0;
@@ -328,7 +344,6 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
return lyr;
}


void QgsLabelingGui::populateFieldNames()
{
const QgsFieldMap& fields = mLayer->pendingFields();
@@ -477,6 +492,23 @@ void QgsLabelingGui::showEngineConfigDialog()
dlg.exec();
}

void QgsLabelingGui::showExpressionDialog()
{
//TODO extract this out to a dialog.
QgsExpressionBuilderDialog dlg( mLayer, cboFieldName->currentText() , this );
dlg.setWindowTitle( tr("Expression based label") );
if ( dlg.exec() == QDialog::Accepted )
{
QString expression = dlg.expressionBuilder()->getExpressionString();
//Only add the expression if the user has entered some text.
if (!expression.isEmpty())
{
cboFieldName->addItem(expression);
cboFieldName->setCurrentIndex(cboFieldName->count() - 1);
}
}
}

void QgsLabelingGui::updateUi()
{
// enable/disable scale-based, buffer, decimals
@@ -41,6 +41,7 @@ class QgsLabelingGui : public QDialog, private Ui::QgsLabelingGuiBase
void changeTextColor();
void changeTextFont();
void showEngineConfigDialog();
void showExpressionDialog();
void changeBufferColor();

void updateUi();
@@ -375,40 +375,46 @@ typedef QgsExpression::FunctionDef FnDef;
FnDef QgsExpression::BuiltinFunctions[] =
{
// math
FnDef( "sqrt", 1, fcnSqrt ),
FnDef( "sin", 1, fcnSin ),
FnDef( "cos", 1, fcnCos ),
FnDef( "tan", 1, fcnTan ),
FnDef( "asin", 1, fcnAsin ),
FnDef( "acos", 1, fcnAcos ),
FnDef( "atan", 1, fcnAtan ),
FnDef( "atan2", 2, fcnAtan2 ),
FnDef( "exp", 1, fcnExp ),
FnDef( "ln", 1, fcnLn ),
FnDef( "log10", 1, fcnLog10 ),
FnDef( "log", 2, fcnLog ),
FnDef( "sqrt", 1, fcnSqrt, "Math"),
FnDef( "sin", 1, fcnSin, "Math" ),
FnDef( "cos", 1, fcnCos, "Math"),
FnDef( "tan", 1, fcnTan, "Math" ),
FnDef( "asin", 1, fcnAsin, "Math" ),
FnDef( "acos", 1, fcnAcos, "Math" ),
FnDef( "atan", 1, fcnAtan, "Math" ),
FnDef( "atan2", 2, fcnAtan2, "Math" ),
FnDef( "exp", 1, fcnExp, "Math" ),
FnDef( "ln", 1, fcnLn, "Math" ),
FnDef( "log10", 1, fcnLog10, "Math" ),
FnDef( "log", 2, fcnLog, "Math" ),
// casts
FnDef( "toint", 1, fcnToInt ),
FnDef( "toreal", 1, fcnToReal ),
FnDef( "tostring", 1, fcnToString ),
FnDef( "toint", 1, fcnToInt, "Conversions" ),
FnDef( "toreal", 1, fcnToReal, "Conversions" ),
FnDef( "tostring", 1, fcnToString, "Conversions" ),
// string manipulation
FnDef( "lower", 1, fcnLower ),
FnDef( "upper", 1, fcnUpper ),
FnDef( "length", 1, fcnLength ),
FnDef( "replace", 3, fcnReplace ),
FnDef( "regexp_replace", 3, fcnRegexpReplace ),
FnDef( "substr", 3, fcnSubstr ),
FnDef( "lower", 1, fcnLower, "String", "<b>Convert to lower case</b> "\
"<br> Converts a string to lower case letters. " \
"<br> <i>Usage:</i><br>lower('HELLO WORLD') will return 'hello world'"),
FnDef( "upper", 1, fcnUpper, "String" , "<b>Convert to upper case</b> "\
"<br> Converts a string to upper case letters. " \
"<br> <i>Usage:</i><br>upper('hello world') will return 'HELLO WORLD'"),
FnDef( "length", 1, fcnLength, "String", "<b>Length of string</b> "\
"<br> Returns the legnth of a string. " \
"<br> <i>Usage:</i><br>length('hello') will return 5"),
FnDef( "replace", 3, fcnReplace, "String", "<b>Replace a section of a string.</b> "),
FnDef( "regexp_replace", 3, fcnRegexpReplace, "String" ),
FnDef( "substr", 3, fcnSubstr, "String" ),
// geometry accessors
FnDef( "xat", 1, fcnXat, true ),
FnDef( "yat", 1, fcnYat, true ),
FnDef( "xat", 1, fcnXat, "Geometry", "", true ),
FnDef( "yat", 1, fcnYat, "Geometry", "", true ),
FnDef( "$area", 0, fcnGeomArea, "Geometry", "", true ),
FnDef( "$length", 0, fcnGeomLength, "Geometry", "", true ),
FnDef( "$perimeter", 0, fcnGeomPerimeter, "Geometry", "", true ),
FnDef( "$x", 0, fcnX, "Geometry", "", true ),
FnDef( "$y", 0, fcnY, "Geometry", "" , true ),
// special columns
FnDef( "$rownum", 0, fcnRowNumber ),
FnDef( "$area", 0, fcnGeomArea, true ),
FnDef( "$length", 0, fcnGeomLength, true ),
FnDef( "$perimeter", 0, fcnGeomPerimeter, true ),
FnDef( "$x", 0, fcnX, true ),
FnDef( "$y", 0, fcnY, true ),
FnDef( "$id", 0, fcnFeatureId ),
FnDef( "$rownum", 0, fcnRowNumber, "Record" ),
FnDef( "$id", 0, fcnFeatureId, "Record")
};


@@ -419,7 +425,7 @@ bool QgsExpression::isFunctionName( QString name )

int QgsExpression::functionIndex( QString name )
{
int count = sizeof( BuiltinFunctions ) / sizeof( FunctionDef );
int count = functionCount();
for ( int i = 0; i < count; i++ )
{
if ( QString::compare( name, BuiltinFunctions[i].mName, Qt::CaseInsensitive ) == 0 )
@@ -428,6 +434,11 @@ int QgsExpression::functionIndex( QString name )
return -1;
}

int QgsExpression::functionCount()
{
return ( sizeof( BuiltinFunctions ) / sizeof( FunctionDef) );
}


QgsExpression::QgsExpression( const QString& expr )
: mExpression( expr ), mRowNumber( 0 ), mCalc( NULL )
@@ -30,7 +30,7 @@ The expressions try to follow both syntax and semantics of SQL expressions.
Usage:
QgsExpression exp("gid*2 > 10 and type not in ('D','F');
QgsExpression exp("gid*2 > 10 and type not in ('D','F'));
if (exp.hasParserError())
{
// show error message with parserErrorString() and exit
@@ -170,12 +170,20 @@ class CORE_EXPORT QgsExpression

struct FunctionDef
{
FunctionDef( QString fnname, int params, FcnEval fcn, bool usesGeometry = false )
: mName( fnname ), mParams( params ), mFcn( fcn ), mUsesGeometry( usesGeometry ) {}
FunctionDef( QString fnname, int params, FcnEval fcn, QString group, QString helpText = "", bool usesGeometry = false )
: mName( fnname ), mParams( params ), mFcn( fcn ), mUsesGeometry( usesGeometry ), mGroup( group ), mHelpText( helpText ) {}
/** The name of the function. */
QString mName;
/** The number of parameters this function takes. */
int mParams;
/** Pointer to fucntion. */
FcnEval mFcn;
/** Does this function use a geometry object. */
bool mUsesGeometry;
/** The group the function belongs to. */
QString mGroup;
/** The help text for the function. */
QString mHelpText;
};

static FunctionDef BuiltinFunctions[];
@@ -186,6 +194,11 @@ class CORE_EXPORT QgsExpression
// return index of the function in BuiltinFunctions array
static int functionIndex( QString name );

/** Returns the number of functions defined in the parser
* @return The number of function defined in the parser.
*/
static int functionCount();

//! return quoted column reference (in double quotes)
static QString quotedColumnRef( QString name ) { return QString( "\"%1\"" ).arg( name.replace( "\"", "\"\"" ) ); }

@@ -84,11 +84,9 @@ QString QgsLabel::fieldValue( int attr, QgsFeature &feature )
}

void QgsLabel::renderLabel( QgsRenderContext &renderContext,
QgsFeature &feature,
bool selected,
QgsFeature &feature, bool selected,
QgsLabelAttributes *classAttributes )
{
Q_UNUSED( classAttributes );
if ( mLabelAttributes->selectedOnly() && !selected )
return;

0 comments on commit 847204e

Please sign in to comment.
You can’t perform that action at this time.