QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsdatadefinedbutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatadefinedbutton.cpp - Data defined selector button
3  --------------------------------------
4  Date : 27-April-2013
5  Copyright : (C) 2013 by Larry Shaffer
6  Email : larrys at dakcarto dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsdatadefinedbutton.h"
17 
18 #include <qgsapplication.h>
19 #include <qgsdatadefined.h>
21 #include <qgsexpression.h>
22 #include <qgsmessageviewer.h>
23 #include <qgsvectorlayer.h>
24 
25 #include <QClipboard>
26 #include <QMenu>
27 #include <QMouseEvent>
28 #include <QPointer>
29 
30 
31 QIcon QgsDataDefinedButton::mIconDataDefine;
32 QIcon QgsDataDefinedButton::mIconDataDefineOn;
33 QIcon QgsDataDefinedButton::mIconDataDefineError;
34 QIcon QgsDataDefinedButton::mIconDataDefineExpression;
35 QIcon QgsDataDefinedButton::mIconDataDefineExpressionOn;
36 QIcon QgsDataDefinedButton::mIconDataDefineExpressionError;
37 
39  const QgsVectorLayer* vl,
40  const QgsDataDefined* datadefined,
41  DataTypes datatypes,
42  QString description )
43  : QToolButton( parent )
44 {
45  // set up static icons
46  if ( mIconDataDefine.isNull() )
47  {
48  mIconDataDefine = QgsApplication::getThemeIcon( "/mIconDataDefine.svg" );
49  mIconDataDefineOn = QgsApplication::getThemeIcon( "/mIconDataDefineOn.svg" );
50  mIconDataDefineError = QgsApplication::getThemeIcon( "/mIconDataDefineError.svg" );
51  mIconDataDefineExpression = QgsApplication::getThemeIcon( "/mIconDataDefineExpression.svg" );
52  mIconDataDefineExpressionOn = QgsApplication::getThemeIcon( "/mIconDataDefineExpressionOn.svg" );
53  mIconDataDefineExpressionError = QgsApplication::getThemeIcon( "/mIconDataDefineExpressionError.svg" );
54  }
55 
56  setFocusPolicy( Qt::StrongFocus );
57 
58  // set default tool button icon properties
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 );
63 
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 );
68 
69  mFieldsMenu = new QMenu( this );
70 
71  mActionDataTypes = new QAction( this );
72  // list fields and types in submenu, since there may be many
73  mActionDataTypes->setMenu( mFieldsMenu );
74 
75  mActionActive = new QAction( this );
76  QFont f = mActionActive->font();
77  f.setBold( true );
78  mActionActive->setFont( f );
79 
80  mActionDescription = new QAction( tr( "Description..." ), this );
81 
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 );
87  mActionAssistant = new QAction( tr( "Assistant..." ), this );
88 
89  // set up sibling widget connections
90  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( disableEnabledWidgets( bool ) ) );
91  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( checkCheckedWidgets( bool ) ) );
92 
93  init( vl, datadefined, datatypes, description );
94 }
95 
97 {
98  mEnabledWidgets.clear();
99  mCheckedWidgets.clear();
100 }
101 
103  const QgsDataDefined* datadefined,
104  DataTypes datatypes,
105  QString description )
106 {
107  mVectorLayer = vl;
108  // construct default property if none or incorrect passed in
109  if ( !datadefined )
110  {
111  mProperty.insert( "active", "0" );
112  mProperty.insert( "useexpr", "0" );
113  mProperty.insert( "expression", "" );
114  mProperty.insert( "field", "" );
115  }
116  else
117  {
118  mProperty.insert( "active", datadefined->isActive() ? "1" : "0" );
119  mProperty.insert( "useexpr", datadefined->useExpression() ? "1" : "0" );
120  mProperty.insert( "expression", datadefined->expressionString() );
121  mProperty.insert( "field", datadefined->field() );
122  }
123 
124  mDataTypes = datatypes;
125  mFieldNameList.clear();
126  mFieldTypeList.clear();
127 
128  mInputDescription = description;
129  mFullDescription = QString( "" );
130  mUsageInfo = QString( "" );
131  mCurrentDefinition = QString( "" );
132 
133  // set up data types string
134  mDataTypesString = QString( "" );
135 
136  QStringList ts;
137  if ( mDataTypes.testFlag( String ) )
138  {
139  ts << tr( "string" );
140  }
141  if ( mDataTypes.testFlag( Int ) )
142  {
143  ts << tr( "int" );
144  }
145  if ( mDataTypes.testFlag( Double ) )
146  {
147  ts << tr( "double" );
148  }
149 
150  if ( !ts.isEmpty() )
151  {
152  mDataTypesString = ts.join( ", " );
153  mActionDataTypes->setText( tr( "Field type: " ) + mDataTypesString );
154  }
155 
156  if ( mVectorLayer )
157  {
158  // store just a list of fields of unknown type or those that match the expected type
159  const QgsFields& fields = mVectorLayer->pendingFields();
160  for ( int i = 0; i < fields.count(); ++i )
161  {
162  const QgsField& f = fields.at( i );
163  bool fieldMatch = false;
164  // NOTE: these are the only QVariant enums supported at this time (see QgsField)
165  QString fieldType;
166  switch ( f.type() )
167  {
168  case QVariant::String:
169  fieldMatch = mDataTypes.testFlag( String );
170  fieldType = tr( "string" );
171  break;
172  case QVariant::Int:
173  fieldMatch = mDataTypes.testFlag( Int ) || mDataTypes.testFlag( Double );
174  fieldType = tr( "integer" );
175  break;
176  case QVariant::Double:
177  fieldMatch = mDataTypes.testFlag( Double );
178  fieldType = tr( "double" );
179  break;
180  case QVariant::Invalid:
181  default:
182  fieldMatch = true; // field type is unknown
183  fieldType = tr( "unknown type" );
184  }
185  if ( fieldMatch || mDataTypes.testFlag( AnyType ) )
186  {
187  mFieldNameList << f.name();
188  mFieldTypeList << fieldType;
189  }
190  }
191  }
192 
193  updateGui();
194 }
195 
197 {
198  if ( !dd )
199  return;
200 
201  dd->setActive( isActive() );
204  dd->setField( getField() );
205 }
206 
208 {
209  QgsDataDefined dd;
210  updateDataDefined( &dd );
211  return dd;
212 }
213 
214 void QgsDataDefinedButton::mouseReleaseEvent( QMouseEvent *event )
215 {
216  // Ctrl-click to toggle activated state
217  if (( event->modifiers() & ( Qt::ControlModifier ) )
218  || event->button() == Qt::RightButton )
219  {
220  setActive( !isActive() );
221  updateGui();
222  event->ignore();
223  return;
224  }
225 
226  // pass to default behaviour
227  QToolButton::mousePressEvent( event );
228 }
229 
230 void QgsDataDefinedButton::aboutToShowMenu()
231 {
232  mDefineMenu->clear();
233 
234  bool hasExp = !getExpression().isEmpty();
235  bool hasField = !getField().isEmpty();
236  QString ddTitle = tr( "Data defined override" );
237 
238  QAction* ddTitleAct = mDefineMenu->addAction( ddTitle );
239  QFont titlefont = ddTitleAct->font();
240  titlefont.setItalic( true );
241  ddTitleAct->setFont( titlefont );
242  ddTitleAct->setEnabled( false );
243 
244  bool addActiveAction = false;
245  if ( useExpression() && hasExp )
246  {
247  QgsExpression exp( getExpression() );
248  // whether expression is parse-able
249  addActiveAction = !exp.hasParserError();
250  }
251  else if ( !useExpression() && hasField )
252  {
253  // whether field exists
254  addActiveAction = mFieldNameList.contains( getField() );
255  }
256 
257  if ( addActiveAction )
258  {
259  ddTitleAct->setText( ddTitle + " (" + ( useExpression() ? tr( "expression" ) : tr( "field" ) ) + ")" );
260  mDefineMenu->addAction( mActionActive );
261  mActionActive->setText( isActive() ? tr( "Deactivate" ) : tr( "Activate" ) );
262  mActionActive->setData( QVariant( isActive() ? false : true ) );
263  }
264 
265  if ( !mFullDescription.isEmpty() )
266  {
267  mDefineMenu->addAction( mActionDescription );
268  }
269 
270  mDefineMenu->addSeparator();
271 
272  bool fieldActive = false;
273  if ( !mDataTypesString.isEmpty() )
274  {
275  QAction* fieldTitleAct = mDefineMenu->addAction( tr( "Attribute field" ) );
276  fieldTitleAct->setFont( titlefont );
277  fieldTitleAct->setEnabled( false );
278 
279  mDefineMenu->addAction( mActionDataTypes );
280 
281  mFieldsMenu->clear();
282 
283  if ( mFieldNameList.size() > 0 )
284  {
285 
286  for ( int j = 0; j < mFieldNameList.count(); ++j )
287  {
288  QString fldname = mFieldNameList.at( j );
289  QAction* act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ")" );
290  act->setData( QVariant( fldname ) );
291  if ( getField() == fldname )
292  {
293  act->setCheckable( true );
294  act->setChecked( !useExpression() );
295  fieldActive = !useExpression();
296  }
297  }
298  }
299  else
300  {
301  QAction* act = mFieldsMenu->addAction( tr( "No matching field types found" ) );
302  act->setEnabled( false );
303  }
304 
305  mDefineMenu->addSeparator();
306  }
307 
308  mFieldsMenu->menuAction()->setCheckable( true );
309  mFieldsMenu->menuAction()->setChecked( fieldActive );
310 
311  QAction* exprTitleAct = mDefineMenu->addAction( tr( "Expression" ) );
312  exprTitleAct->setFont( titlefont );
313  exprTitleAct->setEnabled( false );
314 
315  if ( hasExp )
316  {
317  QString expString = getExpression();
318  if ( expString.length() > 35 )
319  {
320  expString.truncate( 35 );
321  expString.append( "..." );
322  }
323 
324  expString.prepend( tr( "Current: " ) );
325 
326  if ( !mActionExpression )
327  {
328  mActionExpression = new QAction( expString, this );
329  mActionExpression->setCheckable( true );
330  }
331  else
332  {
333  mActionExpression->setText( expString );
334  }
335  mDefineMenu->addAction( mActionExpression );
336  mActionExpression->setChecked( useExpression() );
337 
338  mDefineMenu->addAction( mActionExpDialog );
339  mDefineMenu->addAction( mActionCopyExpr );
340  mDefineMenu->addAction( mActionPasteExpr );
341  mDefineMenu->addAction( mActionClearExpr );
342  }
343  else
344  {
345  mDefineMenu->addAction( mActionExpDialog );
346  mDefineMenu->addAction( mActionPasteExpr );
347  }
348 
349  if ( mAssistant.data() )
350  {
351  mDefineMenu->addSeparator();
352  mDefineMenu->addAction( mActionAssistant );
353  }
354 }
355 
356 void QgsDataDefinedButton::menuActionTriggered( QAction* action )
357 {
358  if ( action == mActionActive )
359  {
360  setActive( mActionActive->data().toBool() );
361  updateGui();
362  }
363  else if ( action == mActionDescription )
364  {
365  showDescriptionDialog();
366  }
367  else if ( action == mActionExpDialog )
368  {
369  showExpressionDialog();
370  }
371  else if ( action == mActionExpression )
372  {
373  setUseExpression( true );
374  setActive( true );
375  updateGui();
376  }
377  else if ( action == mActionCopyExpr )
378  {
379  QApplication::clipboard()->setText( getExpression() );
380  }
381  else if ( action == mActionPasteExpr )
382  {
383  QString exprString = QApplication::clipboard()->text();
384  if ( !exprString.isEmpty() )
385  {
386  setExpression( exprString );
387  setUseExpression( true );
388  setActive( true );
389  updateGui();
390  }
391  }
392  else if ( action == mActionClearExpr )
393  {
394  // only deactivate if defined expression is being used
395  if ( isActive() && useExpression() )
396  {
397  setUseExpression( false );
398  setActive( false );
399  }
400  setExpression( QString( "" ) );
401  updateGui();
402  }
403  else if ( action == mActionAssistant )
404  {
405  showAssistant();
406  }
407  else if ( mFieldsMenu->actions().contains( action ) ) // a field name clicked
408  {
409  if ( action->isEnabled() )
410  {
411  if ( getField() != action->text() )
412  {
413  setField( action->data().toString() );
414  }
415  setUseExpression( false );
416  setActive( true );
417  updateGui();
418  }
419  }
420 }
421 
422 void QgsDataDefinedButton::showDescriptionDialog()
423 {
424  QgsMessageViewer* mv = new QgsMessageViewer( this );
425  mv->setWindowTitle( tr( "Data definition description" ) );
426  mv->setMessageAsHtml( mFullDescription );
427  mv->exec();
428 }
429 
430 void QgsDataDefinedButton::showAssistant()
431 {
432  if ( !mAssistant.data() )
433  return;
434 
435  if ( mAssistant->exec() == QDialog::Accepted )
436  {
437  QgsDataDefined dd = mAssistant->dataDefined();
439  setActive( dd.isActive() );
440  if ( dd.isActive() && dd.useExpression() )
442  else if ( dd.isActive() )
443  setField( dd.field() );
444  updateGui();
445  }
446  activateWindow(); // reset focus to parent window
447 }
448 
449 void QgsDataDefinedButton::showExpressionDialog()
450 {
451  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer*>( mVectorLayer ), getExpression() );
452  if ( d.exec() == QDialog::Accepted )
453  {
454  QString newExp = d.expressionText();
455  setExpression( d.expressionText().trimmed() );
456  bool hasExp = !newExp.isEmpty();
457 
458  setUseExpression( hasExp );
459  setActive( hasExp );
460  updateGui();
461  }
462  activateWindow(); // reset focus to parent window
463 }
464 
465 void QgsDataDefinedButton::updateGui()
466 {
467  QString oldDef = mCurrentDefinition;
468  QString newDef( "" );
469  bool hasExp = !getExpression().isEmpty();
470  bool hasField = !getField().isEmpty();
471 
472  if ( useExpression() && !hasExp )
473  {
474  setActive( false );
475  setUseExpression( false );
476  }
477  else if ( !useExpression() && !hasField )
478  {
479  setActive( false );
480  }
481 
482  QIcon icon = mIconDataDefine;
483  QString deftip = tr( "undefined" );
484  if ( useExpression() && hasExp )
485  {
486  icon = isActive() ? mIconDataDefineExpressionOn : mIconDataDefineExpression;
487  newDef = deftip = getExpression();
488 
489  QgsExpression exp( getExpression() );
490  if ( exp.hasParserError() )
491  {
492  setActive( false );
493  icon = mIconDataDefineExpressionError;
494  deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
495  newDef = "";
496  }
497  }
498  else if ( !useExpression() && hasField )
499  {
500  icon = isActive() ? mIconDataDefineOn : mIconDataDefine;
501  newDef = deftip = getField();
502 
503  if ( !mFieldNameList.contains( getField() ) )
504  {
505  setActive( false );
506  icon = mIconDataDefineError;
507  deftip = tr( "'%1' field missing" ).arg( getField() );
508  newDef = "";
509  }
510  }
511 
512  setIcon( icon );
513 
514  // update and emit current definition
515  if ( newDef != oldDef )
516  {
517  mCurrentDefinition = newDef;
518  emit dataDefinedChanged( mCurrentDefinition );
519  }
520 
521  // build full description for tool tip and popup dialog
522  mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );
523 
524  mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( isActive() ? tr( "yes" ) : tr( "no" ) );
525 
526  if ( !mUsageInfo.isEmpty() )
527  {
528  mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
529  }
530 
531  if ( !mInputDescription.isEmpty() )
532  {
533  mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
534  }
535 
536  if ( !mDataTypesString.isEmpty() )
537  {
538  mFullDescription += tr( "<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
539  }
540 
541  QString deftype( "" );
542  if ( deftip != tr( "undefined" ) )
543  {
544  deftype = QString( " (%1)" ).arg( useExpression() ? tr( "expression" ) : tr( "field" ) );
545  }
546 
547  // truncate long expressions, or tool tip may be too wide for screen
548  if ( deftip.length() > 75 )
549  {
550  deftip.truncate( 75 );
551  deftip.append( "..." );
552  }
553 
554  mFullDescription += tr( "<b>Current definition %1:</b><br>%2" ).arg( deftype ).arg( deftip );
555 
556  setToolTip( mFullDescription );
557 
558 }
559 
561 {
562  if ( isActive() != active )
563  {
564  mProperty.insert( "active", active ? "1" : "0" );
565  emit dataDefinedActivated( active );
566  }
567 }
568 
569 void QgsDataDefinedButton::registerEnabledWidgets( QList<QWidget*> wdgts )
570 {
571  for ( int i = 0; i < wdgts.size(); ++i )
572  {
573  registerEnabledWidget( wdgts.at( i ) );
574  }
575 }
576 
578 {
579  QPointer<QWidget> wdgtP( wdgt );
580  if ( !mEnabledWidgets.contains( wdgtP ) )
581  {
582  mEnabledWidgets.append( wdgtP );
583  }
584 }
585 
587 {
588  QList<QWidget*> wdgtList;
589  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
590  {
591  wdgtList << mEnabledWidgets.at( i );
592  }
593  return wdgtList;
594 }
595 
597 {
598  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
599  {
600  mEnabledWidgets.at( i )->setDisabled( disable );
601  }
602 }
603 
604 void QgsDataDefinedButton::registerCheckedWidgets( QList<QWidget*> wdgts )
605 {
606  for ( int i = 0; i < wdgts.size(); ++i )
607  {
608  registerCheckedWidget( wdgts.at( i ) );
609  }
610 }
611 
613 {
614  QPointer<QWidget> wdgtP( wdgt );
615  if ( !mCheckedWidgets.contains( wdgtP ) )
616  {
617  mCheckedWidgets.append( wdgtP );
618  }
619 }
620 
622 {
623  QList<QWidget*> wdgtList;
624  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
625  {
626  wdgtList << mCheckedWidgets.at( i );
627  }
628  return wdgtList;
629 }
630 
632 {
633  mAssistant.reset( assistant );
634  mAssistant.data()->setParent( this, Qt::Dialog );
635 }
636 
638 {
639  // don't uncheck, only set to checked
640  if ( !check )
641  {
642  return;
643  }
644  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
645  {
646  QAbstractButton *btn = qobject_cast< QAbstractButton * >( mCheckedWidgets.at( i ) );
647  if ( btn && btn->isCheckable() )
648  {
649  btn->setChecked( true );
650  continue;
651  }
652  QGroupBox *grpbx = qobject_cast< QGroupBox * >( mCheckedWidgets.at( i ) );
653  if ( grpbx && grpbx->isCheckable() )
654  {
655  grpbx->setChecked( true );
656  }
657  }
658 }
659 
661 {
662  // just something to reduce translation redundancy
663  return tr( "string " );
664 }
665 
667 {
668  return tr( "single character" );
669 }
670 
672 {
673  return tr( "bool [<b>1</b>=True|<b>0</b>=False]" );
674 }
675 
677 {
678  return tr( "string of variable length" );
679 }
680 
682 {
683  return tr( "int [&lt;= 0 =&gt;]" );
684 }
685 
687 {
688  return tr( "int [&gt;= 0]" );
689 }
690 
692 {
693  return tr( "int [&gt;= 1]" );
694 }
695 
697 {
698  return tr( "double [&lt;= 0.0 =&gt;]" );
699 }
700 
702 {
703  return tr( "double [&gt;= 0.0]" );
704 }
705 
707 {
708  return tr( "double [0.0-1.0]" );
709 }
710 
712 {
713  return tr( "double coord [<b>X,Y</b>] as &lt;= 0.0 =&gt;" );
714 }
715 
717 {
718  return tr( "double [-180.0 - 180.0]" );
719 }
720 
722 {
723  return tr( "int [0-100]" );
724 }
725 
727 {
728  return trString() + "[<b>MM</b>|<b>MapUnit</b>]";
729 }
730 
732 {
733  return trString() + "[<b>MM</b>|<b>MapUnit</b>|<b>Percent</b>]";
734 }
735 
737 {
738  return tr( "string [<b>r,g,b</b>] as int 0-255" );
739 }
740 
742 {
743  return tr( "string [<b>r,g,b,a</b>] as int 0-255" );
744 }
745 
747 {
748  return trString() + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]";
749 }
750 
752 {
753  return trString() + "[<b>Bottom</b>|<b>Middle</b>|<b>Top</b>]";
754 }
755 
757 {
758  return trString() + "[<b>bevel</b>|<b>miter</b>|<b>round</b>]";
759 }
760 
762 {
763  return trString() + QString( "[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
764  "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
765  "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>]" );
766 }
767 
769 {
770  return trString() + QString( "[<b>filepath</b>] as<br>"
771  "<b>''</b>=empty|absolute|search-paths-relative|<br>"
772  "project-relative|URL" );
773 }
774 
776 {
777  return tr( "string [<b>filepath</b>]" );
778 }
779 
781 {
782  return trString() + QString( "[<b>A5</b>|<b>A4</b>|<b>A3</b>|<b>A2</b>|<b>A1</b>|<b>A0</b>"
783  "<b>B5</b>|<b>B4</b>|<b>B3</b>|<b>B2</b>|<b>B1</b>|<b>B0</b>"
784  "<b>Legal</b>|<b>Ansi A</b>|<b>Ansi B</b>|<b>Ansi C</b>|<b>Ansi D</b>|<b>Ansi E</b>"
785  "<b>Arch A</b>|<b>Arch B</b>|<b>Arch C</b>|<b>Arch D</b>|<b>Arch E</b>|<b>Arch E1</b>]"
786  );
787 }
788 
790 {
791  return trString() + QString( "[<b>portrait</b>|<b>landscape</b>]" );
792 }
793 
795 {
796  return trString() + QString( "[<b>left</b>|<b>center</b>|<b>right</b>]" );
797 }
798 
800 {
801  return trString() + QString( "[<b>top</b>|<b>center</b>|<b>bottom</b>]" );
802 }
803 
805 {
806  return trString() + QString( "[<b>linear</b>|<b>radial</b>|<b>conical</b>]" );
807 }
808 
810 {
811  return trString() + QString( "[<b>feature</b>|<b>viewport</b>]" );
812 }
813 
815 {
816  return trString() + QString( "[<b>pad</b>|<b>repeat</b>|<b>reflect</b>]" );
817 }
818 
820 {
821  return trString() + QString( "[<b>no</b>|<b>solid</b>|<b>dash</b>|<b>dot</b>|<b>dash dot</b>|<b>dash dot dot</b>]" );
822 }
823 
825 {
826  return trString() + QString( "[<b>square</b>|<b>flat</b>|<b>round</b>]" );
827 }
828 
830 {
831  return trString() + QString( "[<b>solid</b>|<b>horizontal</b>|<b>vertical</b>|<b>cross</b>|<b>b_diagonal</b>|<b>f_diagonal"
832  "</b>|<b>diagonal_x</b>|<b>dense1</b>|<b>dense2</b>|<b>dense3</b>|<b>dense4</b>|<b>dense5"
833  "</b>|<b>dense6</b>|<b>dense7</b>|<b>no]" );
834 }
835 
837 {
838  return trString() + QString( "[<b>circle</b>|<b>rectangle</b>|<b>cross</b>|<b>triangle</b>]" );
839 }
840 
842 {
843  return tr( "[<b><dash>;<space></b>] e.g. '8;2;1;2'" );
844 }