1
/***************************************************************************
2
qgsattributeactiondialog.cpp - attribute action dialog
5
This class creates and manages the Action tab of the Vector Layer
6
Properties dialog box. Changes made in the dialog box are propagated
7
back to QgsVectorLayer.
10
copyright : (C) 2004 by Gavin Macaulay
11
email : gavin at macaulay dot co dot nz
12
***************************************************************************/
14
/***************************************************************************
16
* This program is free software; you can redistribute it and/or modify *
17
* it under the terms of the GNU General Public License as published by *
18
* the Free Software Foundation; either version 2 of the License, or *
19
* (at your option) any later version. *
21
***************************************************************************/
24
#include "qgsattributeactiondialog.h"
25
#include "qgsattributeaction.h"
27
#include <QFileDialog>
28
#include <QHeaderView>
29
#include <QMessageBox>
32
QgsAttributeActionDialog::QgsAttributeActionDialog( QgsAttributeAction* actions,
33
const QgsFieldMap& fields,
35
QWidget( parent ), mActions( actions )
38
QHeaderView *header = attributeActionTable->horizontalHeader();
39
header->setHighlightSections( false );
40
header->setStretchLastSection( true );
41
attributeActionTable->setColumnWidth( 0, 100 );
42
attributeActionTable->setColumnWidth( 1, 230 );
43
#if QT_VERSION >= 0x040300
44
attributeActionTable->setCornerButtonEnabled( false );
47
connect( attributeActionTable, SIGNAL( itemSelectionChanged() ),
48
this, SLOT( itemSelectionChanged() ) );
49
connect( moveUpButton, SIGNAL( clicked() ), this, SLOT( moveUp() ) );
50
connect( moveDownButton, SIGNAL( clicked() ), this, SLOT( moveDown() ) );
51
connect( removeButton, SIGNAL( clicked() ), this, SLOT( remove() ) );
52
connect( browseButton, SIGNAL( clicked() ), this, SLOT( browse() ) );
53
connect( insertButton, SIGNAL( clicked() ), this, SLOT( insert() ) );
54
connect( updateButton, SIGNAL( clicked() ), this, SLOT( update() ) );
55
connect( insertFieldButton, SIGNAL( clicked() ), this, SLOT( insertField() ) );
58
// Populate the combo box with the field names. Will the field names
59
// change? If so, they need to be passed into the init() call, or
60
// some access to them retained in this class.
61
for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); it++ )
62
fieldComboBox->addItem( it->name() );
65
void QgsAttributeActionDialog::init()
67
// Start from a fresh slate.
68
attributeActionTable->setRowCount( 0 );
70
// Populate with our actions.
71
for ( int i = 0; i < mActions->size(); i++ )
73
const QgsAction action = ( *mActions )[i];
74
insertRow( i, action.type(), action.name(), action.action(), action.capture() );
78
void QgsAttributeActionDialog::insertRow( int row, QgsAction::ActionType type, const QString &name, const QString &action, bool capture )
80
QTableWidgetItem* item;
81
attributeActionTable->insertRow( row );
82
item = new QTableWidgetItem( actionType->itemText( type ) );
83
item->setFlags( item->flags() & ~Qt::ItemIsEditable );
84
attributeActionTable->setItem( row, 0, item );
85
attributeActionTable->setItem( row, 1, new QTableWidgetItem( name ) );
86
attributeActionTable->setItem( row, 2, new QTableWidgetItem( action ) );
87
item = new QTableWidgetItem();
88
item->setFlags( item->flags() & ~( Qt::ItemIsEditable | Qt::ItemIsUserCheckable ) );
89
item->setCheckState( capture ? Qt::Checked : Qt::Unchecked );
90
attributeActionTable->setItem( row, 3, item );
93
void QgsAttributeActionDialog::moveUp()
95
// Swap the selected row with the one above
97
int row1 = -1, row2 = -1;
98
QList<QTableWidgetItem *> selection = attributeActionTable->selectedItems();
99
if ( !selection.isEmpty() )
101
row1 = attributeActionTable->row( selection.first() );
107
if ( row1 != -1 && row2 != -1 )
109
swapRows( row1, row2 );
110
// Move the selection to follow
111
attributeActionTable->selectRow( row2 );
115
void QgsAttributeActionDialog::moveDown()
117
// Swap the selected row with the one below
118
int row1 = -1, row2 = -1;
119
QList<QTableWidgetItem *> selection = attributeActionTable->selectedItems();
120
if ( !selection.isEmpty() )
122
row1 = attributeActionTable->row( selection.first() );
125
if ( row1 < attributeActionTable->rowCount() - 1 )
128
if ( row1 != -1 && row2 != -1 )
130
swapRows( row1, row2 );
131
// Move the selection to follow
132
attributeActionTable->selectRow( row2 );
136
void QgsAttributeActionDialog::swapRows( int row1, int row2 )
138
int colCount = attributeActionTable->columnCount();
139
for ( int col = 0; col < colCount; col++ )
141
QTableWidgetItem *item = attributeActionTable->takeItem( row1, col );
142
attributeActionTable->setItem( row1, col, attributeActionTable->takeItem( row2, col ) );
143
attributeActionTable->setItem( row2, col, item );
147
void QgsAttributeActionDialog::browse()
149
// Popup a file browser and place the results into the actionName
152
QString action = QFileDialog::getOpenFileName(
153
this, tr( "Select an action", "File dialog window title" ) );
155
if ( !action.isNull() )
156
actionAction->insert( action );
159
void QgsAttributeActionDialog::remove()
161
QList<QTableWidgetItem *> selection = attributeActionTable->selectedItems();
162
if ( !selection.isEmpty() )
164
// Remove the selected row.
165
int row = attributeActionTable->row( selection.first() );
166
attributeActionTable->removeRow( row );
168
// And select the row below the one that was selected or the last one.
169
if ( row >= attributeActionTable->rowCount() ) row = attributeActionTable->rowCount() - 1;
170
attributeActionTable->selectRow( row );
174
void QgsAttributeActionDialog::insert()
176
// Add the action details as a new row in the table.
178
int pos = attributeActionTable->rowCount();
182
void QgsAttributeActionDialog::insert( int pos )
184
// Check to see if the action name and the action have been specified
187
if ( actionName->text().isEmpty() || actionAction->text().isEmpty() )
189
QMessageBox::warning( this, tr( "Missing Information" ),
190
tr( "To create an attribute action, you must provide both a name and the action to perform." ) );
196
// Get the action details and insert into the table at the given
197
// position. Name needs to be unique, so make it so if required.
199
// If the new action name is the same as the action name in the
200
// given pos, don't make the new name unique (because we're
203
int numRows = attributeActionTable->rowCount();
205
if ( pos < numRows && actionName->text() == attributeActionTable->item( pos, 0 )->text() )
206
name = actionName->text();
208
name = uniqueName( actionName->text() );
210
if ( pos >= numRows )
212
// Expand the table to have a row with index pos
213
insertRow( pos, ( QgsAction::ActionType ) actionType->currentIndex(), name, actionAction->text(), captureCB->isChecked() );
217
// Update existing row
218
attributeActionTable->item( pos, 0 )->setText( actionType->currentText() );
219
attributeActionTable->item( pos, 1 )->setText( name );
220
attributeActionTable->item( pos, 2 )->setText( actionAction->text() );
221
attributeActionTable->item( pos, 3 )->setCheckState( captureCB->isChecked() ? Qt::Checked : Qt::Unchecked );
226
void QgsAttributeActionDialog::update()
228
// Updates the action that is selected with the
230
QList<QTableWidgetItem *> selection = attributeActionTable->selectedItems();
231
if ( !selection.isEmpty() )
233
int i = attributeActionTable->row( selection.first() );
238
void QgsAttributeActionDialog::insertField()
240
// Take the selected field, preprend a % and insert into the action
241
// field at the cursor position
243
if ( !fieldComboBox->currentText().isNull() )
245
QString field( "%" );
246
field += fieldComboBox->currentText();
247
actionAction->insert( field );
251
void QgsAttributeActionDialog::apply()
253
// Update the contents of mActions from the UI.
255
mActions->clearActions();
256
for ( int i = 0; i < attributeActionTable->rowCount(); ++i )
258
const QgsAction::ActionType type = ( QgsAction::ActionType ) actionType->findText( attributeActionTable->item( i, 0 )->text() );
259
const QString &name = attributeActionTable->item( i, 1 )->text();
260
const QString &action = attributeActionTable->item( i, 2 )->text();
261
if ( !name.isEmpty() && !action.isEmpty() )
263
QTableWidgetItem *item = attributeActionTable->item( i, 3 );
264
mActions->addAction( type, name, action, item->checkState() == Qt::Checked );
269
void QgsAttributeActionDialog::itemSelectionChanged()
271
QList<QTableWidgetItem *> selection = attributeActionTable->selectedItems();
272
if ( !selection.isEmpty() )
274
#if QT_VERSION < 0x040400
275
// Supress multiple selection and select row where mouse release occurs.
276
// Workaround for Qt 4.3 bug which allows multiple rows to be selected if
277
// the user presses the mouse in one row header and releases in another.
278
if ( attributeActionTable->row( selection.first() ) != attributeActionTable->row( selection.last() ) )
280
attributeActionTable->selectRow( attributeActionTable->currentRow() );
281
selection = attributeActionTable->selectedItems();
284
rowSelected( attributeActionTable->row( selection.first() ) );
288
void QgsAttributeActionDialog::rowSelected( int row )
290
// The user has selected a row. We take the contents of that row and
291
// populate the edit section of the dialog so that they can change
292
// the row if desired.
294
QTableWidgetItem *item = attributeActionTable->item( row, 2 );
297
// Only if a populated row was selected
298
actionType->setCurrentIndex( actionType->findText( attributeActionTable->item( row, 0 )->text() ) );
299
actionName->setText( attributeActionTable->item( row, 1 )->text() );
300
actionAction->setText( attributeActionTable->item( row, 2 )->text() );
301
captureCB->setChecked( item->checkState() == Qt::Checked );
305
QString QgsAttributeActionDialog::uniqueName( QString name )
307
// Make sure that the given name is unique, adding a numerical
308
// suffix if necessary.
310
int pos = attributeActionTable->rowCount();
313
for ( int i = 0; i < pos; ++i )
315
if ( attributeActionTable->item( i, 0 )->text() == name )
325
QString suffix = QString::number( suffix_num );
326
new_name = name + "_" + suffix;
328
for ( int i = 0; i < pos; ++i )
329
if ( attributeActionTable->item( i, 0 )->text() == new_name )