Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update QgsDataDefinedButton
- Add 'Usage info' functions; displays in description and tool tip
- Reorganize menu, adding conceptual section titles
- Add ability to paste in expression
- Add ability to clear defined expression
- Add check for non-matching data field types
- Add better truncation of expressions in tool tip and menu
  • Loading branch information
dakcarto committed May 28, 2013
1 parent 047976b commit dd60a34
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 55 deletions.
8 changes: 8 additions & 0 deletions src/app/qgslabelinggui.cpp
Expand Up @@ -937,19 +937,27 @@ void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
QgsDataDefinedButton::AnyType, tr( "double coord [<b>in,out</b> as 20.0-60.0,20.0-95.0]" ) );

// data defined-only
QString ddPlaceInfo = tr( "In edit mode, layer's relevant labeling map tool is:<br>"
"&nbsp;&nbsp;Defined attribute field -&gt; <i>enabled</i><br>"
"&nbsp;&nbsp;Defined expression -&gt; <i>disabled</i>" );
mCoordXDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::PositionX ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mCoordXDDBtn->setUsageInfo( ddPlaceInfo );
mCoordYDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::PositionY ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mCoordYDDBtn->setUsageInfo( ddPlaceInfo );
mCoordAlignmentHDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Hali ),
QgsDataDefinedButton::String,
trString + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]" );
mCoordAlignmentHDDBtn->setUsageInfo( ddPlaceInfo );
mCoordAlignmentVDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Vali ),
QgsDataDefinedButton::String,
trString + QString( "[<b>Bottom</b>|<b>Base</b>|<br>"
"<b>Half</b>|<b>Cap</b>|<b>Top</b>]" ) );
mCoordAlignmentVDDBtn->setUsageInfo( ddPlaceInfo );
mCoordRotationDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::Rotation ),
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mCoordRotationDDBtn->setUsageInfo( ddPlaceInfo );

// rendering
mScaleBasedVisibilityDDBtn->init( mLayer, s.dataDefinedProperty( QgsPalLayerSettings::ScaleVisibility ),
Expand Down
154 changes: 109 additions & 45 deletions src/gui/qgsdatadefinedbutton.cpp
Expand Up @@ -76,6 +76,7 @@ void QgsDataDefinedButton::init( const QgsVectorLayer* vl,
mDataTypes = datatypes;
mInputDescription = description;
mFullDescription = QString( "" );
mUsageInfo = QString( "" );
mCurrentDefinition = QString( "" );

mActionExpression = 0;
Expand Down Expand Up @@ -109,9 +110,10 @@ void QgsDataDefinedButton::init( const QgsVectorLayer* vl,

mActionDescription = new QAction( tr( "Description..." ), this );

mActionExpDialog = new QAction( tr( "Edit expression..." ), this );

mActionCopyExpr = new QAction( tr( "Copy expression" ), this );
mActionExpDialog = new QAction( tr( "Edit..." ), this );
mActionPasteExpr = new QAction( tr( "Paste" ), this );
mActionCopyExpr = new QAction( tr( "Copy" ), this );
mActionClearExpr = new QAction( tr( "Clear" ), this );

// set up data types string
mActionDataTypes = 0;
Expand All @@ -120,21 +122,21 @@ void QgsDataDefinedButton::init( const QgsVectorLayer* vl,
QStringList ts;
if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( String ) )
{
ts << tr( "String" );
ts << tr( "string" );
}
if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( Int ) )
{
ts << tr( "Int" );
ts << tr( "int" );
}
if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( Double ) )
{
ts << tr( "Double" );
ts << tr( "double" );
}

if ( !ts.isEmpty() )
{
mDataTypesString = ts.join( ", " );
mActionDataTypes = new QAction( tr( "Field types: " ) + mDataTypesString, this );
mActionDataTypes = new QAction( tr( "Field type: " ) + mDataTypesString, this );

// list fields and types in submenu, since there may be many
mActionDataTypes->setMenu( mFieldsMenu );
Expand Down Expand Up @@ -208,6 +210,13 @@ void QgsDataDefinedButton::aboutToShowMenu()

bool hasExp = !getExpression().isEmpty();
bool hasField = !getField().isEmpty();
QString ddTitle = tr( "Data defined override" );

QAction* ddTitleAct = mDefineMenu->addAction( ddTitle );
QFont titlefont = ddTitleAct->font();
titlefont.setItalic( true );
ddTitleAct->setFont( titlefont );
ddTitleAct->setEnabled( false );

bool addActiveAction = false;
if ( useExpression() && hasExp )
Expand All @@ -222,36 +231,70 @@ void QgsDataDefinedButton::aboutToShowMenu()
addActiveAction = mFieldNameList.contains( getField() );
}

bool addTopSep = false;
if ( addActiveAction )
{
ddTitleAct->setText( ddTitle + " (" + ( useExpression() ? tr( "expression" ) : tr( "field" ) ) + ")" );
mDefineMenu->addAction( mActionActive );
mActionActive->setText( isActive() ? tr( "Deactivate" ) : tr( "Activate" ) );
mActionActive->setData( QVariant( isActive() ? false : true ) );
addTopSep = true;
}

if ( !mFullDescription.isEmpty() )
{
mDefineMenu->addAction( mActionDescription );
addTopSep = true;
}

if ( addTopSep )
mDefineMenu->addSeparator();

if ( mActionDataTypes )
{
QAction* fieldTitleAct = mDefineMenu->addAction( tr( "Attribute field" ) );
fieldTitleAct->setFont( titlefont );
fieldTitleAct->setEnabled( false );

mDefineMenu->addAction( mActionDataTypes );

mFieldsMenu->clear();

if ( mFieldNameList.size() > 0 )
{

for ( int j = 0; j < mFieldNameList.count(); ++j )
{
QString fldname = mFieldNameList.at( j );
QAction* act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ")" );
act->setData( QVariant( fldname ) );
if ( getField() == fldname )
{
act->setCheckable( true );
act->setChecked( !useExpression() );
}
}
}
else
{
QAction* act = mFieldsMenu->addAction( tr( "No matching field types found" ) );
act->setEnabled( false );
}

mDefineMenu->addSeparator();
}

mDefineMenu->addAction( mActionExpDialog );
QAction* exprTitleAct = mDefineMenu->addAction( tr( "Expression" ) );
exprTitleAct->setFont( titlefont );
exprTitleAct->setEnabled( false );

if ( hasExp )
{
QString expString = getExpression();
if ( expString.length() > 100 )
if ( expString.length() > 35 )
{
expString.truncate( 100 );
expString.truncate( 35 );
expString.append( "..." );
}

expString.prepend( tr( "Current: " ) );

if ( !mActionExpression )
{
mActionExpression = new QAction( expString, this );
Expand All @@ -261,34 +304,18 @@ void QgsDataDefinedButton::aboutToShowMenu()
{
mActionExpression->setText( expString );
}

mDefineMenu->addAction( mActionCopyExpr );
mDefineMenu->addAction( mActionExpression );
mActionExpression->setChecked( useExpression() );
}

if ( mFieldNameList.size() > 0 )
mDefineMenu->addAction( mActionExpDialog );
mDefineMenu->addAction( mActionCopyExpr );
mDefineMenu->addAction( mActionPasteExpr );
mDefineMenu->addAction( mActionClearExpr );
}
else
{
mDefineMenu->addSeparator();

if ( mActionDataTypes )
{
mDefineMenu->addAction( mActionDataTypes );
}

mFieldsMenu->clear();

for ( int j = 0; j < mFieldNameList.count(); ++j )
{
QString fldname = mFieldNameList.at( j );
QAction* act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ")" );
act->setData( QVariant( fldname ) );
if ( getField() == fldname )
{
act->setCheckable( true );
act->setChecked( !useExpression() );
}
}
mDefineMenu->addAction( mActionExpDialog );
mDefineMenu->addAction( mActionPasteExpr );
}

}
Expand Down Expand Up @@ -318,16 +345,41 @@ void QgsDataDefinedButton::menuActionTriggered( QAction* action )
{
QApplication::clipboard()->setText( getExpression() );
}
else // a field name clicked
else if ( action == mActionPasteExpr )
{
if ( getField() != action->text() )
QString exprString = QApplication::clipboard()->text();
if ( !exprString.isEmpty() )
{
setField( action->data().toString() );
setExpression( exprString );
setUseExpression( true );
setActive( true );
updateGui();
}
setUseExpression( false );
setActive( true );
}
else if ( action == mActionClearExpr )
{
// only deactivate if defined expression is being used
if ( isActive() && useExpression() )
{
setUseExpression( false );
setActive( false );
}
setExpression( QString( "" ) );
updateGui();
}
else if ( mFieldsMenu->actions().contains( action ) ) // a field name clicked
{
if ( action->isEnabled() )
{
if ( getField() != action->text() )
{
setField( action->data().toString() );
}
setUseExpression( false );
setActive( true );
updateGui();
}
}
}

void QgsDataDefinedButton::showDescriptionDialog()
Expand Down Expand Up @@ -383,7 +435,7 @@ void QgsDataDefinedButton::updateGui()
{
setActive( false );
icon = mIconDataDefineExpressionError;
deftip = tr( "Expression parse error: %1" ).arg( exp.parserErrorString() );
deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
newDef = "";
}
}
Expand Down Expand Up @@ -411,10 +463,15 @@ void QgsDataDefinedButton::updateGui()
}

// build full description for tool tip and popup dialog
mFullDescription = QString( "" );
mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );

mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( isActive() ? tr( "yes" ) : tr( "no" ) );

if ( !mUsageInfo.isEmpty() )
{
mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
}

if ( !mInputDescription.isEmpty() )
{
mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
Expand All @@ -431,6 +488,13 @@ void QgsDataDefinedButton::updateGui()
deftype = QString( " (%1)" ).arg( useExpression() ? tr( "expression" ) : tr( "field" ) );
}

// truncate long expressions, or tool tip may be too wide for screen
if ( deftip.length() > 75 )
{
deftip.truncate( 75 );
deftip.append( "..." );
}

mFullDescription += tr( "<b>Current definition%1:</b><br>%2" ).arg( deftype ).arg( deftip );

setToolTip( mFullDescription );
Expand Down
13 changes: 13 additions & 0 deletions src/gui/qgsdatadefinedbutton.h
Expand Up @@ -113,6 +113,16 @@ class GUI_EXPORT QgsDataDefinedButton: public QToolButton
*/
QString fullDescription() const { return mFullDescription; }

/**
* The usage information about this data definition
*/
QString usageInfo() const { return mUsageInfo; }

/**
* Set the usage information about this data definition
*/
void setUsageInfo( const QString& info ) { mUsageInfo = info; updateGui(); }

/**
* Register list of sibling widgets that get disabled/enabled when data definition or expression is set/unset
*/
Expand Down Expand Up @@ -247,13 +257,16 @@ class GUI_EXPORT QgsDataDefinedButton: public QToolButton
QAction* mActionDescription;
QAction* mActionExpDialog;
QAction* mActionExpression;
QAction* mActionPasteExpr;
QAction* mActionCopyExpr;
QAction* mActionClearExpr;
QAction* mActionDataTypes;

DataTypes mDataTypes;
QString mDataTypesString;
QString mInputDescription;
QString mFullDescription;
QString mUsageInfo;
QString mCurrentDefinition;

static QIcon mIconDataDefine;
Expand Down
10 changes: 0 additions & 10 deletions src/ui/qgslabelingguibase.ui
Expand Up @@ -4835,16 +4835,6 @@
</layout>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="mDefineFieldsNoteLabel">
<property name="styleSheet">
<string notr="true">font-style: italic;</string>
</property>
<property name="text">
<string>( Define attribute fields to enable labeling map tools )</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down

0 comments on commit dd60a34

Please sign in to comment.