27 #include <QMouseEvent>
31 QIcon QgsDataDefinedButton::mIconDataDefine;
32 QIcon QgsDataDefinedButton::mIconDataDefineOn;
33 QIcon QgsDataDefinedButton::mIconDataDefineError;
34 QIcon QgsDataDefinedButton::mIconDataDefineExpression;
35 QIcon QgsDataDefinedButton::mIconDataDefineExpressionOn;
36 QIcon QgsDataDefinedButton::mIconDataDefineExpressionError;
43 : QToolButton( parent )
46 if ( mIconDataDefine.isNull() )
56 setFocusPolicy( Qt::StrongFocus );
59 setFixedSize( 30, 26 );
60 setStyleSheet( QString(
"QToolButton{ background: none; border: 1px solid rgba(0, 0, 0, 0%);} QToolButton:focus { border: 1px solid palette(highlight); }" ) );
61 setIconSize( QSize( 24, 24 ) );
62 setPopupMode( QToolButton::InstantPopup );
64 mDefineMenu =
new QMenu(
this );
65 connect( mDefineMenu, SIGNAL( aboutToShow() ),
this, SLOT( aboutToShowMenu() ) );
66 connect( mDefineMenu, SIGNAL( triggered( QAction* ) ),
this, SLOT( menuActionTriggered( QAction* ) ) );
67 setMenu( mDefineMenu );
69 mFieldsMenu =
new QMenu(
this );
71 mActionDataTypes =
new QAction(
this );
73 mActionDataTypes->setMenu( mFieldsMenu );
75 mActionActive =
new QAction(
this );
76 QFont f = mActionActive->font();
78 mActionActive->setFont( f );
80 mActionDescription =
new QAction(
tr(
"Description..." ),
this );
82 mActionExpDialog =
new QAction(
tr(
"Edit..." ),
this );
83 mActionExpression = 0;
84 mActionPasteExpr =
new QAction(
tr(
"Paste" ),
this );
85 mActionCopyExpr =
new QAction(
tr(
"Copy" ),
this );
86 mActionClearExpr =
new QAction(
tr(
"Clear" ),
this );
92 init( vl, datadefined, datatypes, description );
97 mEnabledWidgets.clear();
98 mCheckedWidgets.clear();
104 QString description )
110 mProperty.insert(
"active",
"0" );
111 mProperty.insert(
"useexpr",
"0" );
112 mProperty.insert(
"expression",
"" );
113 mProperty.insert(
"field",
"" );
117 mProperty.insert(
"active", datadefined->
isActive() ?
"1" :
"0" );
118 mProperty.insert(
"useexpr", datadefined->
useExpression() ?
"1" :
"0" );
120 mProperty.insert(
"field", datadefined->
field() );
123 mDataTypes = datatypes;
124 mFieldNameList.clear();
125 mFieldTypeList.clear();
127 mInputDescription = description;
128 mFullDescription = QString(
"" );
129 mUsageInfo = QString(
"" );
130 mCurrentDefinition = QString(
"" );
133 mDataTypesString = QString(
"" );
136 if ( mDataTypes.testFlag(
String ) )
138 ts <<
tr(
"string" );
140 if ( mDataTypes.testFlag(
Int ) )
144 if ( mDataTypes.testFlag(
Double ) )
146 ts <<
tr(
"double" );
151 mDataTypesString = ts.join(
", " );
152 mActionDataTypes->setText(
tr(
"Field type: " ) + mDataTypesString );
159 for (
int i = 0; i < fields.
count(); ++i )
162 bool fieldMatch =
false;
167 case QVariant::String:
168 fieldMatch = mDataTypes.testFlag(
String );
169 fieldType =
tr(
"string" );
172 fieldMatch = mDataTypes.testFlag(
Int ) || mDataTypes.testFlag(
Double );
173 fieldType =
tr(
"integer" );
175 case QVariant::Double:
176 fieldMatch = mDataTypes.testFlag(
Double );
177 fieldType =
tr(
"double" );
179 case QVariant::Invalid:
182 fieldType =
tr(
"unknown type" );
184 if ( fieldMatch || mDataTypes.testFlag(
AnyType ) )
186 mFieldNameList << f.
name();
187 mFieldTypeList << fieldType;
198 if (( event->modifiers() & ( Qt::ControlModifier ) )
199 ||
event->button() == Qt::RightButton )
208 QToolButton::mousePressEvent( event );
211 void QgsDataDefinedButton::aboutToShowMenu()
213 mDefineMenu->clear();
216 bool hasField = !
getField().isEmpty();
217 QString ddTitle =
tr(
"Data defined override" );
219 QAction* ddTitleAct = mDefineMenu->addAction( ddTitle );
220 QFont titlefont = ddTitleAct->font();
221 titlefont.setItalic(
true );
222 ddTitleAct->setFont( titlefont );
223 ddTitleAct->setEnabled(
false );
225 bool addActiveAction =
false;
230 addActiveAction = !exp.hasParserError();
235 addActiveAction = mFieldNameList.contains(
getField() );
238 if ( addActiveAction )
240 ddTitleAct->setText( ddTitle +
" (" + (
useExpression() ?
tr(
"expression" ) :
tr(
"field" ) ) +
")" );
241 mDefineMenu->addAction( mActionActive );
242 mActionActive->setText(
isActive() ?
tr(
"Deactivate" ) :
tr(
"Activate" ) );
243 mActionActive->setData( QVariant(
isActive() ?
false :
true ) );
246 if ( !mFullDescription.isEmpty() )
248 mDefineMenu->addAction( mActionDescription );
251 mDefineMenu->addSeparator();
253 if ( !mDataTypesString.isEmpty() )
255 QAction* fieldTitleAct = mDefineMenu->addAction(
tr(
"Attribute field" ) );
256 fieldTitleAct->setFont( titlefont );
257 fieldTitleAct->setEnabled(
false );
259 mDefineMenu->addAction( mActionDataTypes );
261 mFieldsMenu->clear();
263 if ( mFieldNameList.size() > 0 )
266 for (
int j = 0; j < mFieldNameList.count(); ++j )
268 QString fldname = mFieldNameList.at( j );
269 QAction* act = mFieldsMenu->addAction( fldname +
" (" + mFieldTypeList.at( j ) +
")" );
270 act->setData( QVariant( fldname ) );
273 act->setCheckable(
true );
280 QAction* act = mFieldsMenu->addAction(
tr(
"No matching field types found" ) );
281 act->setEnabled(
false );
284 mDefineMenu->addSeparator();
287 QAction* exprTitleAct = mDefineMenu->addAction(
tr(
"Expression" ) );
288 exprTitleAct->setFont( titlefont );
289 exprTitleAct->setEnabled(
false );
294 if ( expString.length() > 35 )
296 expString.truncate( 35 );
297 expString.append(
"..." );
300 expString.prepend(
tr(
"Current: " ) );
302 if ( !mActionExpression )
304 mActionExpression =
new QAction( expString,
this );
305 mActionExpression->setCheckable(
true );
309 mActionExpression->setText( expString );
311 mDefineMenu->addAction( mActionExpression );
314 mDefineMenu->addAction( mActionExpDialog );
315 mDefineMenu->addAction( mActionCopyExpr );
316 mDefineMenu->addAction( mActionPasteExpr );
317 mDefineMenu->addAction( mActionClearExpr );
321 mDefineMenu->addAction( mActionExpDialog );
322 mDefineMenu->addAction( mActionPasteExpr );
327 void QgsDataDefinedButton::menuActionTriggered( QAction* action )
329 if ( action == mActionActive )
331 setActive( mActionActive->data().toBool() );
334 else if ( action == mActionDescription )
336 showDescriptionDialog();
338 else if ( action == mActionExpDialog )
340 showExpressionDialog();
342 else if ( action == mActionExpression )
348 else if ( action == mActionCopyExpr )
352 else if ( action == mActionPasteExpr )
354 QString exprString = QApplication::clipboard()->text();
355 if ( !exprString.isEmpty() )
363 else if ( action == mActionClearExpr )
374 else if ( mFieldsMenu->actions().contains( action ) )
376 if ( action->isEnabled() )
380 setField( action->data().toString() );
389 void QgsDataDefinedButton::showDescriptionDialog()
392 mv->setWindowTitle(
tr(
"Data definition description" ) );
397 void QgsDataDefinedButton::showExpressionDialog()
400 if ( d.exec() == QDialog::Accepted )
402 QString newExp = d.expressionText();
404 bool hasExp = !newExp.isEmpty();
413 void QgsDataDefinedButton::updateGui()
415 QString oldDef = mCurrentDefinition;
416 QString newDef(
"" );
418 bool hasField = !
getField().isEmpty();
430 QIcon icon = mIconDataDefine;
431 QString deftip =
tr(
"undefined" );
434 icon =
isActive() ? mIconDataDefineExpressionOn : mIconDataDefineExpression;
438 if ( exp.hasParserError() )
441 icon = mIconDataDefineExpressionError;
442 deftip =
tr(
"Parse error: %1" ).arg( exp.parserErrorString() );
448 icon =
isActive() ? mIconDataDefineOn : mIconDataDefine;
451 if ( !mFieldNameList.contains(
getField() ) )
454 icon = mIconDataDefineError;
455 deftip =
tr(
"'%1' field missing" ).arg(
getField() );
463 if ( newDef != oldDef )
465 mCurrentDefinition = newDef;
470 mFullDescription =
tr(
"<b><u>Data defined override</u></b><br>" );
472 mFullDescription +=
tr(
"<b>Active: </b>%1 <i>(ctrl|right-click toggles)</i><br>" ).arg(
isActive() ?
tr(
"yes" ) :
tr(
"no" ) );
474 if ( !mUsageInfo.isEmpty() )
476 mFullDescription +=
tr(
"<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
479 if ( !mInputDescription.isEmpty() )
481 mFullDescription +=
tr(
"<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
484 if ( !mDataTypesString.isEmpty() )
486 mFullDescription +=
tr(
"<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
489 QString deftype(
"" );
490 if ( deftip !=
tr(
"undefined" ) )
492 deftype = QString(
" (%1)" ).arg(
useExpression() ?
tr(
"expression" ) :
tr(
"field" ) );
496 if ( deftip.length() > 75 )
498 deftip.truncate( 75 );
499 deftip.append(
"..." );
502 mFullDescription +=
tr(
"<b>Current definition %1:</b><br>%2" ).arg( deftype ).arg( deftip );
504 setToolTip( mFullDescription );
512 mProperty.insert(
"active", active ?
"1" :
"0" );
519 for (
int i = 0; i < wdgts.size(); ++i )
527 QPointer<QWidget> wdgtP( wdgt );
528 if ( !mEnabledWidgets.contains( wdgtP ) )
530 mEnabledWidgets.append( wdgtP );
536 QList<QWidget*> wdgtList;
537 for (
int i = 0; i < mEnabledWidgets.size(); ++i )
539 wdgtList << mEnabledWidgets.at( i );
546 for (
int i = 0; i < mEnabledWidgets.size(); ++i )
548 mEnabledWidgets.at( i )->setDisabled( disable );
554 for (
int i = 0; i < wdgts.size(); ++i )
562 QPointer<QWidget> wdgtP( wdgt );
563 if ( !mCheckedWidgets.contains( wdgtP ) )
565 mCheckedWidgets.append( wdgtP );
571 QList<QWidget*> wdgtList;
572 for (
int i = 0; i < mCheckedWidgets.size(); ++i )
574 wdgtList << mCheckedWidgets.at( i );
586 for (
int i = 0; i < mCheckedWidgets.size(); ++i )
588 QAbstractButton *btn = qobject_cast< QAbstractButton * >( mCheckedWidgets.at( i ) );
589 if ( btn && btn->isCheckable() )
591 btn->setChecked(
true );
594 QGroupBox *grpbx = qobject_cast< QGroupBox * >( mCheckedWidgets.at( i ) );
595 if ( grpbx && grpbx->isCheckable() )
597 grpbx->setChecked(
true );
605 return tr(
"string " );
610 return tr(
"bool [<b>1</b>=True|<b>0</b>=False]" );
615 return tr(
"string of variable length" );
620 return tr(
"int [<= 0 =>]" );
625 return tr(
"int [>= 0]" );
630 return tr(
"int [>= 1]" );
635 return tr(
"double [<= 0.0 =>]" );
640 return tr(
"double [>= 0.0]" );
645 return tr(
"double [0.0-1.0]" );
650 return tr(
"double coord [<b>X,Y</b>] as <= 0.0 =>" );
655 return tr(
"double [-180.0 - 180.0]" );
660 return tr(
"int [0-100]" );
665 return trString() +
"[<b>MM</b>|<b>MapUnit</b>]";
670 return trString() +
"[<b>MM</b>|<b>MapUnit</b>|<b>Percent</b>]";
675 return tr(
"string [<b>r,g,b</b>] as int 0-255" );
680 return tr(
"string [<b>r,g,b,a</b>] as int 0-255" );
685 return trString() +
"[<b>Left</b>|<b>Center</b>|<b>Right</b>]";
690 return trString() +
"[<b>Bottom</b>|<b>Middle</b>|<b>Top</b>]";
695 return trString() +
"[<b>bevel</b>|<b>miter</b>|<b>round</b>]";
700 return trString() + QString(
"[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
701 "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
702 "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>]" );
707 return trString() + QString(
"[<b>filepath</b>] as<br>"
708 "<b>''</b>=empty|absolute|search-paths-relative|<br>"
709 "project-relative|URL" );
714 return tr(
"string [<b>filepath</b>]" );
719 return trString() + QString(
"[<b>A5</b>|<b>A4</b>|<b>A3</b>|<b>A2</b>|<b>A1</b>|<b>A0</b>"
720 "<b>B5</b>|<b>B4</b>|<b>B3</b>|<b>B2</b>|<b>B1</b>|<b>B0</b>"
721 "<b>Legal</b>|<b>Ansi A</b>|<b>Ansi B</b>|<b>Ansi C</b>|<b>Ansi D</b>|<b>Ansi E</b>"
722 "<b>Arch A</b>|<b>Arch B</b>|<b>Arch C</b>|<b>Arch D</b>|<b>Arch E</b>|<b>Arch E1</b>]"
728 return trString() + QString(
"[<b>portrait</b>|<b>landscape</b>]" );
733 return trString() + QString(
"[<b>left</b>|<b>center</b>|<b>right</b>]" );
738 return trString() + QString(
"[<b>top</b>|<b>center</b>|<b>bottom</b>]" );
743 return trString() + QString(
"[<b>linear</b>|<b>radial</b>|<b>conical</b>]" );
748 return trString() + QString(
"[<b>feature</b>|<b>viewport</b>]" );
753 return trString() + QString(
"[<b>pad</b>|<b>repeat</b>|<b>reflect</b>]" );
758 return trString() + QString(
"[<b>no</b>|<b>solid</b>|<b>dash</b>|<b>dot</b>|<b>dash dot</b>|<b>dash dot dot</b>]" );
763 return trString() + QString(
"[<b>square</b>|<b>flat</b>|<b>round</b>]" );
768 return trString() + QString(
"[<b>solid</b>|<b>horizontal</b>|<b>vertical</b>|<b>cross</b>|<b>b_diagonal</b>|<b>f_diagonal"
769 "</b>|<b>diagonal_x</b>|<b>dense1</b>|<b>dense2</b>|<b>dense3</b>|<b>dense4</b>|<b>dense5"
770 "</b>|<b>dense6</b>|<b>dense7</b>|<b>no]" );
775 return trString() + QString(
"[<b>circle</b>|<b>rectangle</b>|<b>cross</b>|<b>triangle</b>]" );
780 return tr(
"[<b><dash>;<space></b>] e.g. '8;2;1;2'" );