Skip to content

Commit 089652e

Browse files
m-kuhn3nids
authored andcommitted
Add icon support to actions
1 parent ba7f0a3 commit 089652e

File tree

6 files changed

+116
-22
lines changed

6 files changed

+116
-22
lines changed

src/app/qgsattributeactiondialog.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ back to QgsVectorLayer.
3131
#include <QHeaderView>
3232
#include <QMessageBox>
3333
#include <QSettings>
34+
#include <QImageWriter>
3435

3536
QgsAttributeActionDialog::QgsAttributeActionDialog( QgsAttributeAction* actions,
3637
const QgsFields& fields,
@@ -61,6 +62,8 @@ QgsAttributeActionDialog::QgsAttributeActionDialog( QgsAttributeAction* actions,
6162
connect( insertFieldButton, SIGNAL( clicked() ), this, SLOT( insertField() ) );
6263
connect( insertExpressionButton, SIGNAL( clicked() ), this, SLOT( insertExpression() ) );
6364

65+
connect( chooseIconButton, SIGNAL(clicked()), this, SLOT( chooseIcon() ) );
66+
6467
init();
6568
// Populate the combo box with the field names. Will the field names
6669
// change? If so, they need to be passed into the init() call, or
@@ -78,13 +81,13 @@ void QgsAttributeActionDialog::init()
7881
for ( int i = 0; i < mActions->size(); i++ )
7982
{
8083
const QgsAction action = ( *mActions )[i];
81-
insertRow( i, action.type(), action.name(), action.action(), action.capture() );
84+
insertRow( i, action.type(), action.name(), action.action(), action.iconPath(), action.capture() );
8285
}
8386

8487
updateButtons();
8588
}
8689

87-
void QgsAttributeActionDialog::insertRow( int row, QgsAction::ActionType type, const QString &name, const QString &action, bool capture )
90+
void QgsAttributeActionDialog::insertRow( int row, QgsAction::ActionType type, const QString &name, const QString &action, const QString& iconPath, bool capture )
8891
{
8992
QTableWidgetItem* item;
9093
attributeActionTable->insertRow( row );
@@ -97,6 +100,10 @@ void QgsAttributeActionDialog::insertRow( int row, QgsAction::ActionType type, c
97100
item->setFlags( item->flags() & ~( Qt::ItemIsEditable | Qt::ItemIsUserCheckable ) );
98101
item->setCheckState( capture ? Qt::Checked : Qt::Unchecked );
99102
attributeActionTable->setItem( row, 3, item );
103+
QIcon icon = QIcon( iconPath );
104+
QTableWidgetItem* headerItem = new QTableWidgetItem( icon, "" );
105+
headerItem->setData( Qt::UserRole, iconPath );
106+
attributeActionTable->setVerticalHeaderItem( row, headerItem );
100107

101108
updateButtons();
102109
}
@@ -250,7 +257,7 @@ void QgsAttributeActionDialog::insert( int pos )
250257
if ( pos >= numRows )
251258
{
252259
// Expand the table to have a row with index pos
253-
insertRow( pos, ( QgsAction::ActionType ) actionType->currentIndex(), name, actionAction->toPlainText(), captureCB->isChecked() );
260+
insertRow( pos, ( QgsAction::ActionType ) actionType->currentIndex(), name, actionAction->toPlainText(), actionIcon->text(), captureCB->isChecked() );
254261
}
255262
else
256263
{
@@ -259,6 +266,8 @@ void QgsAttributeActionDialog::insert( int pos )
259266
attributeActionTable->item( pos, 1 )->setText( name );
260267
attributeActionTable->item( pos, 2 )->setText( actionAction->toPlainText() );
261268
attributeActionTable->item( pos, 3 )->setCheckState( captureCB->isChecked() ? Qt::Checked : Qt::Unchecked );
269+
attributeActionTable->verticalHeaderItem( pos )->setIcon( QIcon( actionIcon->text() ) );
270+
attributeActionTable->verticalHeaderItem( pos )->setData( Qt::UserRole, actionIcon->text() );
262271
}
263272
}
264273
}
@@ -299,6 +308,23 @@ void QgsAttributeActionDialog::updateButtons()
299308
updateButton->setEnabled( hasSelection && validNewAction );
300309
}
301310

311+
void QgsAttributeActionDialog::chooseIcon()
312+
{
313+
QList<QByteArray> list = QImageWriter::supportedImageFormats();
314+
QStringList formatList;
315+
Q_FOREACH( const QByteArray& format, list )
316+
formatList << QString( "*.%1" ).arg( QString( format ) );
317+
318+
QString filter = QString( "Images( %1 ); All( *.* )" ).arg( formatList.join( " " ) );
319+
QString icon = QFileDialog::getOpenFileName( this, tr( "Choose Icon..." ), actionIcon->text(), filter );
320+
321+
if ( !icon.isNull() )
322+
{
323+
actionIcon->setText( icon );
324+
iconPreview->setPixmap( QPixmap( icon ) );
325+
}
326+
}
327+
302328
void QgsAttributeActionDialog::insertField()
303329
{
304330
// Convert the selected field to an expression and
@@ -323,24 +349,25 @@ void QgsAttributeActionDialog::apply()
323349
const QgsAction::ActionType type = ( QgsAction::ActionType ) actionType->findText( attributeActionTable->item( i, 0 )->text() );
324350
const QString &name = attributeActionTable->item( i, 1 )->text();
325351
const QString &action = attributeActionTable->item( i, 2 )->text();
352+
const QString icon = attributeActionTable->verticalHeaderItem( i )->data( Qt::UserRole ).toString();
326353
if ( !name.isEmpty() && !action.isEmpty() )
327354
{
328355
QTableWidgetItem *item = attributeActionTable->item( i, 3 );
329-
mActions->addAction( type, name, action, item->checkState() == Qt::Checked );
356+
mActions->addAction( type, name, action, icon, item->checkState() == Qt::Checked );
330357
}
331358
}
332359
}
333360

334361
void QgsAttributeActionDialog::addDefaultActions()
335362
{
336363
int pos = 0;
337-
insertRow( pos++, QgsAction::Generic, tr( "Echo attribute's value" ), "echo \"[% \"MY_FIELD\" %]\"", true );
338-
insertRow( pos++, QgsAction::Generic, tr( "Run an application" ), "ogr2ogr -f \"ESRI Shapefile\" \"[% \"OUTPUT_PATH\" %]\" \"[% \"INPUT_FILE\" %]\"", true );
339-
insertRow( pos++, QgsAction::GenericPython, tr( "Get feature id" ), "QtGui.QMessageBox.information(None, \"Feature id\", \"feature id is [% $id %]\")", false );
340-
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% $currentfield %]\")", false );
341-
insertRow( pos++, QgsAction::GenericPython, tr( "Clicked coordinates (Run feature actions tool)" ), "QtGui.QMessageBox.information(None, \"Clicked coords\", \"layer: [% $layerid %]\\ncoords: ([% $clickx %],[% $clicky %])\")", false );
342-
insertRow( pos++, QgsAction::OpenUrl, tr( "Open file" ), "[% \"PATH\" %]", false );
343-
insertRow( pos++, QgsAction::OpenUrl, tr( "Search on web based on attribute's value" ), "http://www.google.com/search?q=[% \"ATTRIBUTE\" %]", false );
364+
insertRow( pos++, QgsAction::Generic, tr( "Echo attribute's value" ), "echo \"[% \"MY_FIELD\" %]\"", "", true );
365+
insertRow( pos++, QgsAction::Generic, tr( "Run an application" ), "ogr2ogr -f \"ESRI Shapefile\" \"[% \"OUTPUT_PATH\" %]\" \"[% \"INPUT_FILE\" %]\"", "", true );
366+
insertRow( pos++, QgsAction::GenericPython, tr( "Get feature id" ), "QtGui.QMessageBox.information(None, \"Feature id\", \"feature id is [% $id %]\")", "", false );
367+
insertRow( pos++, QgsAction::GenericPython, tr( "Selected field's value (Identify features tool)" ), "QtGui.QMessageBox.information(None, \"Current field's value\", \"[% $currentfield %]\")", "", false );
368+
insertRow( pos++, QgsAction::GenericPython, tr( "Clicked coordinates (Run feature actions tool)" ), "QtGui.QMessageBox.information(None, \"Clicked coords\", \"layer: [% $layerid %]\\ncoords: ([% $clickx %],[% $clicky %])\")", "", false );
369+
insertRow( pos++, QgsAction::OpenUrl, tr( "Open file" ), "[% \"PATH\" %]", "", false );
370+
insertRow( pos++, QgsAction::OpenUrl, tr( "Search on web based on attribute's value" ), "http://www.google.com/search?q=[% \"ATTRIBUTE\" %]", "", false );
344371
}
345372

346373
void QgsAttributeActionDialog::itemSelectionChanged()

src/app/qgsattributeactiondialog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ class APP_EXPORT QgsAttributeActionDialog: public QWidget, private Ui::QgsAttrib
5858

5959
private slots:
6060
void updateButtons();
61+
void chooseIcon();
6162

6263
private:
6364

64-
void insertRow( int row, QgsAction::ActionType type, const QString &name, const QString &action, bool capture );
65+
void insertRow(int row, QgsAction::ActionType type, const QString &name, const QString &action, const QString& iconPath, bool capture );
6566
void swapRows( int row1, int row2 );
6667

6768
void insert( int pos );

src/core/qgsattributeaction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ void QgsAttributeAction::addAction( QgsAction::ActionType type, QString name, QS
4545
mActions << QgsAction( type, name, action, capture );
4646
}
4747

48+
void QgsAttributeAction::addAction(QgsAction::ActionType type, QString name, QString action, const QString& icon, bool capture)
49+
{
50+
mActions << QgsAction( type, name, action, icon, capture );
51+
}
52+
4853
void QgsAttributeAction::removeAction( int index )
4954
{
5055
if ( index >= 0 && index < mActions.size() )
@@ -236,6 +241,7 @@ bool QgsAttributeAction::writeXML( QDomNode& layer_node, QDomDocument& doc ) con
236241
QDomElement actionSetting = doc.createElement( "actionsetting" );
237242
actionSetting.setAttribute( "type", mActions[i].type() );
238243
actionSetting.setAttribute( "name", mActions[i].name() );
244+
actionSetting.setAttribute( "icon", mActions[i].iconPath() );
239245
actionSetting.setAttribute( "action", mActions[i].action() );
240246
actionSetting.setAttribute( "capture", mActions[i].capture() );
241247
aActions.appendChild( actionSetting );
@@ -260,6 +266,7 @@ bool QgsAttributeAction::readXML( const QDomNode& layer_node )
260266
addAction(( QgsAction::ActionType ) setting.attributeNode( "type" ).value().toInt(),
261267
setting.attributeNode( "name" ).value(),
262268
setting.attributeNode( "action" ).value(),
269+
setting.attributeNode( "icon" ).value(),
263270
setting.attributeNode( "capture" ).value().toInt() != 0 );
264271
}
265272
}

src/core/qgsattributeaction.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#define QGSATTRIBUTEACTION_H
2626

2727
#include <QString>
28-
#include <QObject>
28+
#include <QIcon>
2929

3030
#include <qgsfeature.h>
3131

@@ -53,9 +53,18 @@ class CORE_EXPORT QgsAction
5353
QgsAction( ActionType type, QString name, QString action, bool capture ) :
5454
mType( type ), mName( name ), mAction( action ), mCaptureOutput( capture ) {}
5555

56+
QgsAction( ActionType type, QString name, QString action, const QString& icon, bool capture ) :
57+
mType( type ), mName( name ), mIcon( icon ), mAction( action ), mCaptureOutput( capture ) {}
58+
5659
//! The name of the action
5760
QString name() const { return mName; }
5861

62+
//! The path to the icon
63+
const QString iconPath() const { return mIcon; }
64+
65+
//! The icon
66+
const QIcon icon() const { return QIcon( mIcon ); }
67+
5968
//! The action
6069
QString action() const { return mAction; }
6170

@@ -84,6 +93,7 @@ class CORE_EXPORT QgsAction
8493
private:
8594
ActionType mType;
8695
QString mName;
96+
QString mIcon;
8797
QString mAction;
8898
bool mCaptureOutput;
8999
};
@@ -102,13 +112,22 @@ class CORE_EXPORT QgsAttributeAction
102112
//! Destructor
103113
virtual ~QgsAttributeAction() {}
104114

105-
//! Add an action with the given name and action details.
106-
// Will happily have duplicate names and actions. If
107-
// capture is true, when running the action using doAction(),
108-
// any stdout from the process will be captured and displayed in a
109-
// dialog box.
115+
/** Add an action with the given name and action details.
116+
* Will happily have duplicate names and actions. If
117+
* capture is true, when running the action using doAction(),
118+
* any stdout from the process will be captured and displayed in a
119+
* dialog box.
120+
*/
110121
void addAction( QgsAction::ActionType type, QString name, QString action, bool capture = false );
111122

123+
/** Add an action with the given name and action details.
124+
* Will happily have duplicate names and actions. If
125+
* capture is true, when running the action using doAction(),
126+
* any stdout from the process will be captured and displayed in a
127+
* dialog box.
128+
*/
129+
void addAction(QgsAction::ActionType type, QString name, QString action, const QString& icon, bool capture = false );
130+
112131
//! Remove an action at given index
113132
void removeAction( int index );
114133

src/gui/qgsactionmenu.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void QgsActionMenu::reloadActions()
126126
{
127127
const QgsAction& qaction( mActions->at( idx ) );
128128

129-
QAction* action = new QAction( qaction.name(), this );
129+
QAction* action = new QAction( qaction.icon(), qaction.name(), this );
130130

131131
// Only enable items on supported platforms
132132
if ( !qaction.runable() )

src/ui/qgsattributeactiondialogbase.ui

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,13 @@
291291
</widget>
292292
</item>
293293
<item row="2" column="0">
294+
<widget class="QLabel" name="label_2">
295+
<property name="text">
296+
<string>Icon</string>
297+
</property>
298+
</widget>
299+
</item>
300+
<item row="3" column="0">
294301
<widget class="QLabel" name="textLabel2">
295302
<property name="whatsThis">
296303
<string>Enter the action here. This can be any program, script or command that is available on your system. When the action is invoked any set of characters that start with a % and then have the name of a field will be replaced by the value of that field. The special characters %% will be replaced by the value of the field that was selected. Double quote marks group text into single arguments to the program, script or command. Double quotes will be ignored if prefixed with a backslash</string>
@@ -303,7 +310,7 @@
303310
</property>
304311
</widget>
305312
</item>
306-
<item row="2" column="1">
313+
<item row="3" column="1">
307314
<layout class="QGridLayout" name="gridLayout_4">
308315
<item row="0" column="1">
309316
<widget class="QToolButton" name="browseButton">
@@ -356,7 +363,7 @@
356363
</item>
357364
</layout>
358365
</item>
359-
<item row="3" column="1">
366+
<item row="4" column="1">
360367
<layout class="QHBoxLayout" name="horizontalLayout_2">
361368
<item>
362369
<widget class="QPushButton" name="insertExpressionButton">
@@ -415,7 +422,7 @@
415422
</item>
416423
</layout>
417424
</item>
418-
<item row="4" column="0" colspan="2">
425+
<item row="5" column="0" colspan="2">
419426
<layout class="QHBoxLayout" name="horizontalLayout_3">
420427
<item>
421428
<spacer name="horizontalSpacer">
@@ -455,6 +462,39 @@
455462
</item>
456463
</layout>
457464
</item>
465+
<item row="2" column="1">
466+
<layout class="QHBoxLayout" name="horizontalLayout_5">
467+
<item>
468+
<widget class="QLabel" name="iconPreview">
469+
<property name="sizePolicy">
470+
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
471+
<horstretch>24</horstretch>
472+
<verstretch>24</verstretch>
473+
</sizepolicy>
474+
</property>
475+
<property name="minimumSize">
476+
<size>
477+
<width>24</width>
478+
<height>24</height>
479+
</size>
480+
</property>
481+
<property name="text">
482+
<string/>
483+
</property>
484+
</widget>
485+
</item>
486+
<item>
487+
<widget class="QLineEdit" name="actionIcon"/>
488+
</item>
489+
<item>
490+
<widget class="QToolButton" name="chooseIconButton">
491+
<property name="text">
492+
<string>...</string>
493+
</property>
494+
</widget>
495+
</item>
496+
</layout>
497+
</item>
458498
</layout>
459499
<widget class="QLabel" name="label">
460500
<property name="geometry">

0 commit comments

Comments
 (0)