mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
expression button and expression capability added to the field model
This commit is contained in:
parent
1f20630ec5
commit
760f835129
@ -29,6 +29,7 @@
|
||||
%Include qgsexpressionbuilderwidget.sip
|
||||
%Include qgsexpressionhighlighter.sip
|
||||
%Include qgsfieldcombobox.sip
|
||||
%Include qgsfieldexpressionwidget.sip
|
||||
%Include qgsfieldmodel.sip
|
||||
%Include qgsfieldvalidator.sip
|
||||
%Include qgsfiledropedit.sip
|
||||
|
@ -1,5 +1,9 @@
|
||||
/**
|
||||
* @brief The QgsFieldComboBox is a combo box which displays the list of fields of a given layer.
|
||||
* If allowed, expression may also be added at the bottom of the list of fields.
|
||||
* It can be combined with a QgsExpressioButton to set the expression using the dedicated expression builder dialog.
|
||||
* It might also be combined with a QgsMapLayerComboBox and the fields will be automatically updated according to the chosen layer.
|
||||
* @see QgsExpressioButton, QgsMapLayerComboBox
|
||||
* @note added in 2.3
|
||||
*/
|
||||
class QgsFieldComboBox : QComboBox
|
||||
@ -17,13 +21,25 @@ class QgsFieldComboBox : QComboBox
|
||||
explicit QgsFieldComboBox( QWidget *parent /TransferThis/ = 0 );
|
||||
|
||||
/**
|
||||
* @brief currentField returns the currently selected field
|
||||
* @brief currentField returns the currently selected field or expression if allowed
|
||||
* @param isExpression determines if the string returned is the name of a field or an expression
|
||||
*/
|
||||
QString currentField();
|
||||
QString currentField( bool *isExpression = 0 );
|
||||
|
||||
//!! setAllowExpression sets if expression can be added the combo box
|
||||
void setAllowExpression( bool allowExpression );
|
||||
//! returns if the widget allows expressions to be added or not
|
||||
bool allowExpression();
|
||||
|
||||
//! Returns the currently used layer
|
||||
QgsVectorLayer* layer();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief fieldChanged the signal is emitted when the currently selected field changes
|
||||
* @brief setField sets the currently selected field
|
||||
* if expressions are allowed in the widget,
|
||||
* then it will either set it as selected
|
||||
* if it already exists, or it will add it otherwise
|
||||
*/
|
||||
void fieldChanged( QString fieldName );
|
||||
|
||||
|
44
python/gui/qgsfieldexpressionwidget.sip
Normal file
44
python/gui/qgsfieldexpressionwidget.sip
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
class QgsFieldExpressionWidget : QWidget
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgsfieldexpressionwidget.h"
|
||||
%End
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief QgsFieldExpressionWidget creates a widget with a combo box to display the fields and expression and a button to open the expression dialog
|
||||
*/
|
||||
explicit QgsFieldExpressionWidget( QWidget *parent /TransferThis/ = 0 );
|
||||
|
||||
//! define the title used in the expression dialog
|
||||
void setExpressionDialogTitle( QString title );
|
||||
|
||||
//! set the geometry calculator used in the expression dialog
|
||||
void setGeomCalculator( const QgsDistanceArea &da );
|
||||
|
||||
//! return a pointer to the combo box in the widget
|
||||
QgsFieldComboBox* fieldComboBox();
|
||||
|
||||
//! return a pointer to the tool button used in the widget
|
||||
QToolButton* toolButton();
|
||||
|
||||
/**
|
||||
* @brief currentField returns the currently selected field or expression if allowed
|
||||
* @param isExpression determines if the string returned is the name of a field or an expression
|
||||
*/
|
||||
QString currentField( bool *isExpression = 0 );
|
||||
|
||||
//! Returns the currently used layer
|
||||
QgsVectorLayer* layer();
|
||||
|
||||
public slots:
|
||||
//! set the layer used to display the fields and expression
|
||||
void setLayer( QgsMapLayer* layer );
|
||||
|
||||
//! sets the current field or expression in the widget
|
||||
void setField( QString fieldName );
|
||||
|
||||
//! open the expression dialog to edit the current or add a new expression
|
||||
void editExpression();
|
||||
};
|
@ -1,10 +1,10 @@
|
||||
|
||||
/**
|
||||
* @brief The QgsFieldModel class is a model to display the list of fields of a layer in widgets.
|
||||
* If allowed, expressions might be added to the end of the model.
|
||||
* It can be associated with a QgsMapLayerModel to dynamically display a layer and its fields.
|
||||
* @note added in 2.3
|
||||
*/
|
||||
|
||||
class QgsFieldModel : QAbstractItemModel
|
||||
{
|
||||
%TypeHeaderCode
|
||||
@ -12,8 +12,11 @@ class QgsFieldModel : QAbstractItemModel
|
||||
%End
|
||||
|
||||
public:
|
||||
static const int FieldNameRole;
|
||||
static const int FieldIndexRole;
|
||||
enum FieldRoles {
|
||||
FieldNameRole = 33, /* Qt::UserRole + 1, SIP does not accept any arithmetic" */
|
||||
FieldIndexRole = 34,
|
||||
ExpressionRole = 35
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief QgsFieldModel creates a model to display the fields of a given layer
|
||||
@ -24,12 +27,30 @@ class QgsFieldModel : QAbstractItemModel
|
||||
* @brief indexFromName returns the index corresponding to a given fieldName
|
||||
*/
|
||||
QModelIndex indexFromName( QString fieldName );
|
||||
|
||||
/**
|
||||
* @brief setAllowExpression determines if expressions are allowed to be added to the model
|
||||
*/
|
||||
void setAllowExpression( bool allowExpression );
|
||||
bool allowExpression();
|
||||
|
||||
/**
|
||||
* @brief setExpression sets a single expression to be added after the fields at the end of the model
|
||||
* @return the model index of the newly added expression
|
||||
*/
|
||||
QModelIndex setExpression( QString expression );
|
||||
|
||||
/**
|
||||
* @brief layer returns the currently used layer
|
||||
*/
|
||||
QgsMapLayer* layer();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief setLayer sets the layer of whch fields are displayed
|
||||
*/
|
||||
void setLayer( QgsMapLayer *layer );
|
||||
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
|
@ -58,8 +58,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
|
||||
mPreviewSize = 24;
|
||||
|
||||
// main layer label-enabling connections
|
||||
connect( chkEnableLabeling, SIGNAL( toggled( bool ) ), cboFieldName, SLOT( setEnabled( bool ) ) );
|
||||
connect( chkEnableLabeling, SIGNAL( toggled( bool ) ), btnExpression, SLOT( setEnabled( bool ) ) );
|
||||
connect( chkEnableLabeling, SIGNAL( toggled( bool ) ), mFieldExpressionWidget, SLOT( setEnabled( bool ) ) );
|
||||
connect( chkEnableLabeling, SIGNAL( toggled( bool ) ), mLabelingFrame, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
// connections for groupboxes with separate activation checkboxes (that need to honor data defined setting)
|
||||
@ -96,7 +95,6 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
|
||||
connect( mLimitLabelChkBox, SIGNAL( toggled( bool ) ), mLimitLabelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
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() )
|
||||
@ -121,7 +119,14 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
|
||||
mDirectSymbolsFrame->setVisible( layer->geometryType() == QGis::Line );
|
||||
mMinSizeFrame->setVisible( layer->geometryType() != QGis::Point );
|
||||
|
||||
populateFieldNames(); // this is just for label text combo box
|
||||
// field combo and expression button
|
||||
mFieldExpressionWidget->setLayer( mLayer );
|
||||
QgsDistanceArea myDa;
|
||||
myDa.setSourceCrs( mLayer->crs().srsid() );
|
||||
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
|
||||
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
|
||||
mFieldExpressionWidget->setGeomCalculator( myDa );
|
||||
|
||||
populateFontCapitalsComboBox();
|
||||
|
||||
// set up quadrant offset button group
|
||||
@ -234,15 +239,11 @@ void QgsLabelingGui::init()
|
||||
|
||||
// enable/disable main options based upon whether layer is being labeled
|
||||
chkEnableLabeling->setChecked( lyr.enabled );
|
||||
cboFieldName->setEnabled( chkEnableLabeling->isChecked() );
|
||||
btnExpression->setEnabled( chkEnableLabeling->isChecked() );
|
||||
mFieldExpressionWidget->setEnabled( chkEnableLabeling->isChecked() );
|
||||
mLabelingFrame->setEnabled( chkEnableLabeling->isChecked() );
|
||||
|
||||
// add the current expression to the bottom of the list
|
||||
if ( lyr.isExpression && !lyr.fieldName.isEmpty() )
|
||||
cboFieldName->addItem( lyr.fieldName );
|
||||
|
||||
cboFieldName->setCurrentIndex( cboFieldName->findText( lyr.fieldName ) );
|
||||
// set the current field or add the current expression to the bottom of the list
|
||||
mFieldExpressionWidget->setField( lyr.fieldName );
|
||||
|
||||
// populate placement options
|
||||
int distUnitIndex = lyr.distInMapUnits ? 1 : 0;
|
||||
@ -509,10 +510,9 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
|
||||
lyr.enabled = chkEnableLabeling->isChecked();
|
||||
|
||||
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();
|
||||
bool isExpression;
|
||||
lyr.fieldName = mFieldExpressionWidget->currentField( &isExpression );
|
||||
lyr.isExpression = isExpression;
|
||||
|
||||
lyr.dist = 0;
|
||||
lyr.placementFlags = 0;
|
||||
@ -775,15 +775,6 @@ void QgsLabelingGui::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn,
|
||||
lyr.setDataDefinedProperty( p, map.value( "active" ).toInt(), map.value( "useexpr" ).toInt(), map.value( "expression" ), map.value( "field" ) );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::populateFieldNames()
|
||||
{
|
||||
const QgsFields& fields = mLayer->pendingFields();
|
||||
for ( int idx = 0; idx < fields.count(); ++idx )
|
||||
{
|
||||
cboFieldName->addItem( fields[idx].name() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
|
||||
{
|
||||
// don't register enable/disable siblings, since visual feedback from data defined buttons should be enough,
|
||||
@ -1175,30 +1166,6 @@ void QgsLabelingGui::showEngineConfigDialog()
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void QgsLabelingGui::showExpressionDialog()
|
||||
{
|
||||
QgsExpressionBuilderDialog dlg( mLayer, cboFieldName->currentText() , this );
|
||||
dlg.setWindowTitle( tr( "Expression based label" ) );
|
||||
|
||||
QgsDistanceArea myDa;
|
||||
myDa.setSourceCrs( mLayer->crs().srsid() );
|
||||
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
|
||||
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
|
||||
dlg.setGeomCalculator( myDa );
|
||||
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
{
|
||||
QString expression = dlg.expressionText();
|
||||
//Only add the expression if the user has entered some text.
|
||||
if ( !expression.isEmpty() )
|
||||
{
|
||||
cboFieldName->addItem( expression );
|
||||
cboFieldName->setCurrentIndex( cboFieldName->count() - 1 );
|
||||
}
|
||||
}
|
||||
activateWindow(); // set focus back parent
|
||||
}
|
||||
|
||||
void QgsLabelingGui::syncDefinedCheckboxFrame( QgsDataDefinedButton* ddBtn, QCheckBox* chkBx, QFrame* f )
|
||||
{
|
||||
if ( ddBtn->isActive() && !chkBx->isChecked() )
|
||||
|
@ -45,7 +45,6 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
void apply();
|
||||
void changeTextColor( const QColor &color );
|
||||
void showEngineConfigDialog();
|
||||
void showExpressionDialog();
|
||||
void changeBufferColor( const QColor &color );
|
||||
|
||||
void updateUi();
|
||||
|
@ -89,6 +89,7 @@ qgsexpressionselectiondialog.cpp
|
||||
qgsextentgroupbox.cpp
|
||||
qgsfeatureselectiondlg.cpp
|
||||
qgsfieldcombobox.cpp
|
||||
qgsfieldexpressionwidget.cpp
|
||||
qgsfieldmodel.cpp
|
||||
qgsfieldvalidator.cpp
|
||||
qgsfiledropedit.cpp
|
||||
@ -233,6 +234,7 @@ qgsexpressionselectiondialog.h
|
||||
qgsextentgroupbox.h
|
||||
qgsfeatureselectiondlg.h
|
||||
qgsfieldcombobox.h
|
||||
qgsfieldexpressionwidget.h
|
||||
qgsfieldmodel.h
|
||||
qgsfieldvalidator.h
|
||||
qgsfilterlineedit.h
|
||||
@ -303,6 +305,7 @@ qgsexpressionhighlighter.h
|
||||
qgsexpressionselectiondialog.h
|
||||
qgsfeatureselectiondlg.h
|
||||
qgsfieldcombobox.h
|
||||
qgsfieldexpressionwidget.h
|
||||
qgsfieldmodel.h
|
||||
qgsfieldvalidator.h
|
||||
qgsfiledropedit.h
|
||||
|
@ -31,21 +31,41 @@ void QgsFieldComboBox::setLayer( QgsMapLayer *layer )
|
||||
mFieldModel->setLayer( layer );
|
||||
}
|
||||
|
||||
QgsVectorLayer *QgsFieldComboBox::layer()
|
||||
{
|
||||
QgsMapLayer* layer = mFieldModel->layer();
|
||||
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
|
||||
if ( vl )
|
||||
return vl;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QgsFieldComboBox::setField( QString fieldName )
|
||||
{
|
||||
QModelIndex idx = mFieldModel->indexFromName( fieldName );
|
||||
if ( idx.isValid() )
|
||||
{
|
||||
setCurrentIndex( idx.row() );
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if ( mAllowExpression )
|
||||
{
|
||||
setCurrentIndex( -1 );
|
||||
mFieldModel->setExpression( fieldName );
|
||||
setCurrentIndex( findText( fieldName ) );
|
||||
return;
|
||||
}
|
||||
setCurrentIndex( -1 );
|
||||
}
|
||||
|
||||
QString QgsFieldComboBox::currentField()
|
||||
QString QgsFieldComboBox::currentField( bool *isExpression )
|
||||
{
|
||||
if ( isExpression )
|
||||
{
|
||||
*isExpression = false;
|
||||
}
|
||||
|
||||
int i = currentIndex();
|
||||
|
||||
const QModelIndex index = mFieldModel->index( i, 0 );
|
||||
@ -54,8 +74,31 @@ QString QgsFieldComboBox::currentField()
|
||||
return "";
|
||||
}
|
||||
|
||||
QString name = mFieldModel->data( index, QgsFieldModel::FieldNameRole ).toString();
|
||||
return name;
|
||||
QString fieldName = mFieldModel->data( index, QgsFieldModel::FieldNameRole ).toString();
|
||||
if ( !fieldName.isEmpty() )
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
if ( mAllowExpression )
|
||||
{
|
||||
QString expression = mFieldModel->data( index, QgsFieldModel::ExpressionRole ).toString();
|
||||
if ( !expression.isEmpty() )
|
||||
{
|
||||
if ( isExpression )
|
||||
{
|
||||
*isExpression = true;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void QgsFieldComboBox::setAllowExpression( bool allowExpression )
|
||||
{
|
||||
mFieldModel->setAllowExpression( allowExpression );
|
||||
}
|
||||
|
||||
void QgsFieldComboBox::indexChanged( int i )
|
||||
|
@ -20,9 +20,14 @@
|
||||
|
||||
class QgsFieldModel;
|
||||
class QgsMapLayer;
|
||||
class QgsVectorLayer;
|
||||
|
||||
/**
|
||||
* @brief The QgsFieldComboBox is a combo box which displays the list of fields of a given layer.
|
||||
* If allowed, expression may also be added at the bottom of the list of fields.
|
||||
* It can be combined with a QgsExpressioButton to set the expression using the dedicated expression builder dialog.
|
||||
* It might also be combined with a QgsMapLayerComboBox and the fields will be automatically updated according to the chosen layer.
|
||||
* @see QgsExpressioButton, QgsMapLayerComboBox
|
||||
* @note added in 2.3
|
||||
*/
|
||||
class GUI_EXPORT QgsFieldComboBox : public QComboBox
|
||||
@ -36,9 +41,18 @@ class GUI_EXPORT QgsFieldComboBox : public QComboBox
|
||||
explicit QgsFieldComboBox( QWidget *parent = 0 );
|
||||
|
||||
/**
|
||||
* @brief currentField returns the currently selected field
|
||||
* @brief currentField returns the currently selected field or expression if allowed
|
||||
* @param isExpression determines if the string returned is the name of a field or an expression
|
||||
*/
|
||||
QString currentField();
|
||||
QString currentField( bool *isExpression = 0 );
|
||||
|
||||
//!! setAllowExpression sets if expression can be added the combo box
|
||||
void setAllowExpression( bool allowExpression );
|
||||
//! returns if the widget allows expressions to be added or not
|
||||
bool allowExpression() { return mAllowExpression; }
|
||||
|
||||
//! Returns the currently used layer
|
||||
QgsVectorLayer* layer();
|
||||
|
||||
signals:
|
||||
/**
|
||||
@ -51,8 +65,12 @@ class GUI_EXPORT QgsFieldComboBox : public QComboBox
|
||||
* @brief setLayer sets the layer of which the fields are listed
|
||||
*/
|
||||
void setLayer( QgsMapLayer* layer );
|
||||
|
||||
/**
|
||||
* @brief setField sets the currently selected field
|
||||
* if expressions are allowed in the widget,
|
||||
* then it will either set it as selected
|
||||
* if it already exists, or it will add it otherwise
|
||||
*/
|
||||
void setField( QString fieldName );
|
||||
|
||||
@ -61,6 +79,7 @@ class GUI_EXPORT QgsFieldComboBox : public QComboBox
|
||||
|
||||
private:
|
||||
QgsFieldModel* mFieldModel;
|
||||
bool mAllowExpression;
|
||||
|
||||
};
|
||||
|
||||
|
104
src/gui/qgsfieldexpressionwidget.cpp
Normal file
104
src/gui/qgsfieldexpressionwidget.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/***************************************************************************
|
||||
qgsfieldexpressionwidget.cpp
|
||||
--------------------------------------
|
||||
Date : 01.04.2014
|
||||
Copyright : (C) 2014 Denis Rouzaud
|
||||
Email : denis.rouzaud@gmail.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 <QHBoxLayout>
|
||||
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsfieldexpressionwidget.h"
|
||||
#include "qgsexpressionbuilderdialog.h"
|
||||
#include "qgsfieldcombobox.h"
|
||||
#include "qgsdistancearea.h"
|
||||
|
||||
QgsFieldExpressionWidget::QgsFieldExpressionWidget( QWidget *parent )
|
||||
: QWidget( parent )
|
||||
, mExpressionDialogTitle( tr( "Expression dialog" ) )
|
||||
, mDa( 0 )
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout( this );
|
||||
layout->setContentsMargins( 0, 0, 0, 0 );
|
||||
mCombo = new QgsFieldComboBox( this );
|
||||
mCombo->setAllowExpression( true );
|
||||
mCombo->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Minimum );
|
||||
layout->addWidget( mCombo );
|
||||
mButton = new QToolButton( this );
|
||||
mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::MinimumExpanding );
|
||||
mButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionEditorOpen.svg" ) );
|
||||
layout->addWidget( mButton );
|
||||
|
||||
connect( mButton, SIGNAL( clicked() ), this, SLOT( editExpression() ) );
|
||||
}
|
||||
|
||||
void QgsFieldExpressionWidget::setExpressionDialogTitle( QString title )
|
||||
{
|
||||
mExpressionDialogTitle = title;
|
||||
}
|
||||
|
||||
void QgsFieldExpressionWidget::setGeomCalculator( const QgsDistanceArea &da )
|
||||
{
|
||||
mDa = QSharedPointer<const QgsDistanceArea>( new QgsDistanceArea( da ) );
|
||||
}
|
||||
|
||||
QgsFieldComboBox *QgsFieldExpressionWidget::fieldComboBox()
|
||||
{
|
||||
return mCombo;
|
||||
}
|
||||
|
||||
QToolButton *QgsFieldExpressionWidget::toolButton()
|
||||
{
|
||||
return mButton;
|
||||
}
|
||||
|
||||
QString QgsFieldExpressionWidget::currentField( bool *isExpression )
|
||||
{
|
||||
return mCombo->currentField( isExpression );
|
||||
}
|
||||
|
||||
QgsVectorLayer *QgsFieldExpressionWidget::layer()
|
||||
{
|
||||
return mCombo->layer();
|
||||
}
|
||||
|
||||
void QgsFieldExpressionWidget::setLayer( QgsMapLayer *layer )
|
||||
{
|
||||
mCombo->setLayer( layer );
|
||||
}
|
||||
|
||||
void QgsFieldExpressionWidget::setField( QString fieldName )
|
||||
{
|
||||
mCombo->setField( fieldName );
|
||||
}
|
||||
|
||||
void QgsFieldExpressionWidget::editExpression()
|
||||
{
|
||||
QString currentExpression = mCombo->currentField();
|
||||
QgsVectorLayer* layer = mCombo->layer();
|
||||
|
||||
if ( !layer )
|
||||
return;
|
||||
|
||||
QgsExpressionBuilderDialog dlg( layer, currentExpression );
|
||||
if ( !mDa.isNull() )
|
||||
{
|
||||
dlg.setGeomCalculator( *mDa );
|
||||
}
|
||||
dlg.setWindowTitle( mExpressionDialogTitle );
|
||||
|
||||
if ( dlg.exec() )
|
||||
{
|
||||
QString newExpression = dlg.expressionText();
|
||||
mCombo->setField( newExpression );
|
||||
}
|
||||
|
||||
}
|
78
src/gui/qgsfieldexpressionwidget.h
Normal file
78
src/gui/qgsfieldexpressionwidget.h
Normal file
@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
qgsfieldexpressionwidget.h
|
||||
--------------------------------------
|
||||
Date : 01.04.2014
|
||||
Copyright : (C) 2014 Denis Rouzaud
|
||||
Email : denis.rouzaud@gmail.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSFIELDEXPRESSIONWIDGET_H
|
||||
#define QGSFIELDEXPRESSIONWIDGET_H
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QWidget>
|
||||
#include <QToolButton>
|
||||
|
||||
#include "qgsdistancearea.h"
|
||||
|
||||
class QgsFieldComboBox;
|
||||
class QgsMapLayer;
|
||||
class QgsVectorLayer;
|
||||
|
||||
|
||||
class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief QgsFieldExpressionWidget creates a widget with a combo box to display the fields and expression and a button to open the expression dialog
|
||||
*/
|
||||
explicit QgsFieldExpressionWidget( QWidget *parent = 0 );
|
||||
|
||||
//! define the title used in the expression dialog
|
||||
void setExpressionDialogTitle( QString title );
|
||||
|
||||
//! set the geometry calculator used in the expression dialog
|
||||
void setGeomCalculator( const QgsDistanceArea &da );
|
||||
|
||||
//! return a pointer to the combo box in the widget
|
||||
QgsFieldComboBox* fieldComboBox();
|
||||
|
||||
//! return a pointer to the tool button used in the widget
|
||||
QToolButton* toolButton();
|
||||
|
||||
/**
|
||||
* @brief currentField returns the currently selected field or expression if allowed
|
||||
* @param isExpression determines if the string returned is the name of a field or an expression
|
||||
*/
|
||||
QString currentField( bool *isExpression = 0 );
|
||||
|
||||
//! Returns the currently used layer
|
||||
QgsVectorLayer* layer();
|
||||
|
||||
public slots:
|
||||
//! set the layer used to display the fields and expression
|
||||
void setLayer( QgsMapLayer* layer );
|
||||
|
||||
//! sets the current field or expression in the widget
|
||||
void setField( QString fieldName );
|
||||
|
||||
//! open the expression dialog to edit the current or add a new expression
|
||||
void editExpression();
|
||||
|
||||
private:
|
||||
QgsFieldComboBox* mCombo;
|
||||
QToolButton* mButton;
|
||||
QString mExpressionDialogTitle;
|
||||
QSharedPointer<const QgsDistanceArea> mDa;
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSFIELDEXPRESSIONWIDGET_H
|
@ -22,15 +22,34 @@
|
||||
QgsFieldModel::QgsFieldModel( QObject *parent )
|
||||
: QAbstractItemModel( parent )
|
||||
, mLayer( NULL )
|
||||
, mAllowExpression( false )
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex QgsFieldModel::indexFromName( QString fieldName )
|
||||
{
|
||||
int r = mFields.indexFromName( fieldName );
|
||||
return index( r, 0 );
|
||||
}
|
||||
QModelIndex idx = index( r, 0 );
|
||||
if ( idx.isValid() )
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
||||
if ( mAllowExpression )
|
||||
{
|
||||
int exprIdx = mExpression.indexOf( fieldName );
|
||||
if ( exprIdx != -1 )
|
||||
{
|
||||
return index( mFields.count() + exprIdx , 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return setExpression( fieldName );
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void QgsFieldModel::setLayer( QgsMapLayer *layer )
|
||||
{
|
||||
@ -39,29 +58,37 @@ void QgsFieldModel::setLayer( QgsMapLayer *layer )
|
||||
disconnect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateFields() ) );
|
||||
disconnect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
|
||||
}
|
||||
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
|
||||
if ( vl )
|
||||
{
|
||||
mLayer = vl;
|
||||
connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateFields() ) );
|
||||
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
|
||||
}
|
||||
else
|
||||
|
||||
if ( !layer )
|
||||
{
|
||||
mLayer = 0;
|
||||
updateModel();
|
||||
return;
|
||||
}
|
||||
updateFields();
|
||||
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
|
||||
if ( !vl )
|
||||
{
|
||||
mLayer = 0;
|
||||
updateModel();
|
||||
return;
|
||||
}
|
||||
|
||||
mLayer = vl;
|
||||
connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateFields() ) );
|
||||
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
|
||||
updateModel();
|
||||
}
|
||||
|
||||
void QgsFieldModel::layerDeleted()
|
||||
{
|
||||
mLayer = 0;
|
||||
updateFields();
|
||||
updateModel();
|
||||
}
|
||||
|
||||
void QgsFieldModel::updateFields()
|
||||
void QgsFieldModel::updateModel()
|
||||
{
|
||||
beginResetModel();
|
||||
mExpression = QList<QString>();
|
||||
if ( mLayer )
|
||||
mFields = mLayer->pendingFields();
|
||||
else
|
||||
@ -69,10 +96,39 @@ void QgsFieldModel::updateFields()
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void QgsFieldModel::setAllowExpression( bool allowExpression )
|
||||
{
|
||||
if ( allowExpression == mAllowExpression )
|
||||
return;
|
||||
|
||||
mAllowExpression = allowExpression;
|
||||
|
||||
if ( !mAllowExpression )
|
||||
{
|
||||
int start = mFields.count();
|
||||
int end = start + mExpression.count() - 1;
|
||||
beginRemoveRows( QModelIndex(), start, end );
|
||||
mExpression = QList<QString>();
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex QgsFieldModel::setExpression( QString expression )
|
||||
{
|
||||
if ( !mAllowExpression )
|
||||
return QModelIndex();
|
||||
|
||||
beginResetModel();
|
||||
mExpression = QList<QString>() << expression;
|
||||
endResetModel();
|
||||
|
||||
return index( mFields.count() , 0 );
|
||||
}
|
||||
|
||||
QModelIndex QgsFieldModel::index( int row, int column, const QModelIndex &parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
if ( row < 0 || row >= mFields.count() )
|
||||
if ( row < 0 || row >= rowCount() )
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex( row, column, row );
|
||||
@ -87,7 +143,7 @@ QModelIndex QgsFieldModel::parent( const QModelIndex &child ) const
|
||||
int QgsFieldModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
return mFields.count();
|
||||
return mAllowExpression ? mFields.count() + mExpression.count() : mFields.count();
|
||||
}
|
||||
|
||||
int QgsFieldModel::columnCount( const QModelIndex &parent ) const
|
||||
@ -106,27 +162,53 @@ QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
|
||||
|
||||
if ( role == FieldNameRole )
|
||||
{
|
||||
int exprIdx = index.internalId() - mFields.count();
|
||||
if ( exprIdx >= 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
QgsField field = mFields[index.internalId()];
|
||||
return field.name();
|
||||
}
|
||||
|
||||
if ( role == ExpressionRole )
|
||||
{
|
||||
int exprIdx = index.internalId() - mFields.count();
|
||||
if ( exprIdx >= 0 )
|
||||
{
|
||||
return mExpression[exprIdx];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
if ( role == FieldIndexRole )
|
||||
{
|
||||
return index.row();
|
||||
if ( index.internalId() >= mFields.count() )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
return index.internalId();
|
||||
}
|
||||
|
||||
if ( role == Qt::DisplayRole )
|
||||
{
|
||||
int exprIdx = index.internalId() - mFields.count();
|
||||
if ( exprIdx >= 0 )
|
||||
{
|
||||
return mExpression[exprIdx];
|
||||
}
|
||||
QgsField field = mFields[index.internalId()];
|
||||
const QMap< QString, QString > aliases = mLayer->attributeAliases();
|
||||
QString alias = aliases.value( field.name(), field.name() );
|
||||
return alias;
|
||||
}
|
||||
|
||||
if ( role == Qt::UserRole )
|
||||
if ( role == Qt::FontRole && index.internalId() >= mFields.count() )
|
||||
{
|
||||
QgsField field = mFields[index.internalId()];
|
||||
return field.name();
|
||||
// if the line is an expression, set it as italic
|
||||
QFont font;
|
||||
font.setItalic( true );
|
||||
return font;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
@ -24,15 +24,20 @@
|
||||
|
||||
/**
|
||||
* @brief The QgsFieldModel class is a model to display the list of fields of a layer in widgets.
|
||||
* If allowed, expressions might be added to the end of the model.
|
||||
* It can be associated with a QgsMapLayerModel to dynamically display a layer and its fields.
|
||||
* @note added in 2.3
|
||||
*/
|
||||
|
||||
class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum { FieldNameRole = Qt::UserRole + 1, FieldIndexRole = Qt::UserRole + 2 };
|
||||
enum FieldRoles
|
||||
{
|
||||
FieldNameRole = Qt::UserRole + 1,
|
||||
FieldIndexRole = Qt::UserRole + 2,
|
||||
ExpressionRole = Qt::UserRole + 3
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief QgsFieldModel creates a model to display the fields of a given layer
|
||||
@ -44,6 +49,23 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
|
||||
*/
|
||||
QModelIndex indexFromName( QString fieldName );
|
||||
|
||||
/**
|
||||
* @brief setAllowExpression determines if expressions are allowed to be added to the model
|
||||
*/
|
||||
void setAllowExpression( bool allowExpression );
|
||||
bool allowExpression() {return mAllowExpression;}
|
||||
|
||||
/**
|
||||
* @brief setExpression sets a single expression to be added after the fields at the end of the model
|
||||
* @return the model index of the newly added expression
|
||||
*/
|
||||
QModelIndex setExpression( QString expression );
|
||||
|
||||
/**
|
||||
* @brief layer returns the currently used layer
|
||||
*/
|
||||
QgsMapLayer* layer() {return mLayer;}
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief setLayer sets the layer of whch fields are displayed
|
||||
@ -51,22 +73,25 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
|
||||
void setLayer( QgsMapLayer *layer );
|
||||
|
||||
protected slots:
|
||||
void updateFields();
|
||||
virtual void updateModel();
|
||||
|
||||
private slots:
|
||||
void layerDeleted();
|
||||
|
||||
protected:
|
||||
QgsFields mFields;
|
||||
QList<QString> mExpression;
|
||||
|
||||
QgsVectorLayer* mLayer;
|
||||
bool mAllowExpression;
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
|
||||
QModelIndex parent( const QModelIndex &child ) const;
|
||||
int rowCount( const QModelIndex &parent ) const;
|
||||
int rowCount( const QModelIndex &parent = QModelIndex() ) const;
|
||||
int columnCount( const QModelIndex &parent ) const;
|
||||
QVariant data( const QModelIndex &index, int role ) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSFIELDMODEL_H
|
||||
|
@ -14,10 +14,10 @@
|
||||
<string>Layer labeling settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<property name="verticalSpacing">
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
@ -34,23 +34,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboFieldName">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>75</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QgsFieldExpressionWidget" name="mFieldExpressionWidget" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
@ -68,26 +52,6 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnExpression">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Edit expression</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</normaloff>:/images/themes/default/mIconExpressionEditorOpen.svg</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
@ -198,7 +162,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<width>602</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -629,7 +593,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>566</width>
|
||||
<height>406</height>
|
||||
<height>392</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -1350,8 +1314,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>640</width>
|
||||
<height>462</height>
|
||||
<width>383</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
@ -1534,12 +1498,12 @@ font-style: italic;</string>
|
||||
<item>
|
||||
<widget class="QFrame" name="mDirectSymbolsFrame">
|
||||
<layout class="QGridLayout" name="gridLayout_33">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_9">
|
||||
<property name="orientation">
|
||||
@ -1961,8 +1925,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>640</width>
|
||||
<height>462</height>
|
||||
<width>298</width>
|
||||
<height>261</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
@ -2339,8 +2303,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>625</width>
|
||||
<height>753</height>
|
||||
<width>362</width>
|
||||
<height>711</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||
@ -3170,8 +3134,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>640</width>
|
||||
<height>462</height>
|
||||
<width>325</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
@ -3664,8 +3628,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>625</width>
|
||||
<height>814</height>
|
||||
<width>377</width>
|
||||
<height>737</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
@ -4930,8 +4894,8 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>625</width>
|
||||
<height>639</height>
|
||||
<width>421</width>
|
||||
<height>622</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
@ -5241,12 +5205,12 @@ font-style: italic;</string>
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="6">
|
||||
<spacer name="horizontalSpacer_23">
|
||||
<property name="orientation">
|
||||
@ -5339,12 +5303,12 @@ font-style: italic;</string>
|
||||
<item>
|
||||
<widget class="QFrame" name="mUpsidedownFrame">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="3">
|
||||
<widget class="QRadioButton" name="mUpsidedownRadioAll">
|
||||
<property name="text">
|
||||
@ -5442,12 +5406,12 @@ font-style: italic;</string>
|
||||
<item>
|
||||
<widget class="QFrame" name="mLimitLabelFrame">
|
||||
<layout class="QGridLayout" name="gridLayout_20">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_8">
|
||||
<property name="orientation">
|
||||
@ -5496,12 +5460,12 @@ font-style: italic;</string>
|
||||
<item>
|
||||
<widget class="QFrame" name="mMinSizeFrame">
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_20">
|
||||
<property name="orientation">
|
||||
@ -5615,6 +5579,12 @@ font-style: italic;</string>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgsdatadefinedbutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsFieldExpressionWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">qgsfieldexpressionwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user