1
/***************************************************************************
2
qgsconfigureshortcutsdialog.cpp
5
copyright : (C) 2009 by Martin Dobias
6
email : wonder dot sk at gmail dot com
7
***************************************************************************
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. *
14
***************************************************************************/
16
#include "qgsconfigureshortcutsdialog.h"
18
#include "qgsshortcutsmanager.h"
20
#include "qgslogger.h"
23
#include <QKeySequence>
24
#include <QMessageBox>
26
#include <QDomDocument>
27
#include <QFileDialog>
28
#include <QTextStream>
31
QgsConfigureShortcutsDialog::QgsConfigureShortcutsDialog( QWidget* parent )
32
: QDialog( parent ), mGettingShortcut( false )
36
connect( btnChangeShortcut, SIGNAL( clicked() ), this, SLOT( changeShortcut() ) );
37
connect( btnResetShortcut, SIGNAL( clicked() ), this, SLOT( resetShortcut() ) );
38
connect( btnSetNoShortcut, SIGNAL( clicked() ), this, SLOT( setNoShortcut() ) );
39
connect( btnSaveShortcuts, SIGNAL( clicked() ), this, SLOT( saveShortcuts() ) );
40
connect( btnLoadShortcuts, SIGNAL( clicked() ), this, SLOT( loadShortcuts() ) );
42
connect( treeActions, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
43
this, SLOT( actionChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
48
void QgsConfigureShortcutsDialog::populateActions()
50
QList<QAction*> actions = QgsShortcutsManager::instance()->listActions();
52
QList<QTreeWidgetItem *> items;
53
for ( int i = 0; i < actions.count(); ++i )
55
QString actionText = actions[i]->text();
56
actionText.remove( '&' ); // remove the accelerator
58
QStringList lst; lst << actionText << actions[i]->shortcut().toString();
59
QTreeWidgetItem* item = new QTreeWidgetItem( lst );
60
item->setIcon( 0, actions[i]->icon() );
61
item->setData( 0, Qt::UserRole, qVariantFromValue(( QObject* )actions[i] ) );
65
treeActions->addTopLevelItems( items );
67
// make sure everything's visible and sorted
68
treeActions->resizeColumnToContents( 0 );
69
treeActions->sortItems( 0, Qt::AscendingOrder );
71
actionChanged( treeActions->currentItem(), NULL );
74
void QgsConfigureShortcutsDialog::saveShortcuts()
76
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save shortcuts" ), ".", tr( "XML file (*.xml);; All files (*.*)" ) );
78
if ( fileName.isEmpty() )
81
// ensure the user never omitted the extension from the file name
82
if ( !fileName.toLower().endsWith( ".xml" ) )
87
QFile file( fileName );
88
if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
90
QMessageBox::warning( this, tr( "Saving shortcuts" ),
91
tr( "Cannot write file %1:\n%2." )
93
.arg( file.errorString() ) );
99
QDomDocument doc( "shortcuts" );
100
QDomElement root = doc.createElement( "qgsshortcuts" );
101
root.setAttribute( "version", "1.0" );
102
root.setAttribute( "locale", settings.value( "locale/userLocale", "en_US" ).toString() );
103
doc.appendChild( root );
105
settings.beginGroup( "/shortcuts/" );
106
QStringList keys = settings.childKeys();
109
QString actionShortcut;
111
for ( int i = 0; i < keys.count(); ++i )
113
actionText = keys[ i ];
114
actionShortcut = settings.value( actionText, "" ).toString();
116
QDomElement el = doc.createElement( "act" );
117
el.setAttribute( "name", actionText );
118
el.setAttribute( "shortcut", actionShortcut );
119
root.appendChild( el );
122
QTextStream out( &file );
126
void QgsConfigureShortcutsDialog::loadShortcuts()
128
QString fileName = QFileDialog::getOpenFileName( this, tr( "Load shortcuts" ), ".", tr( "XML file (*.xml);; All files (*.*)" ) );
130
if ( fileName.isEmpty() )
135
QFile file( fileName );
136
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
138
QMessageBox::warning( this, tr( "Loading shortcuts" ),
139
tr( "Cannot read file %1:\n%2." )
141
.arg( file.errorString() ) );
150
if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
152
QMessageBox::information( this, tr( "Loading shortcuts" ),
153
tr( "Parse error at line %1, column %2:\n%3" )
160
QDomElement root = doc.documentElement();
161
if ( root.tagName() != "qgsshortcuts" )
163
QMessageBox::information( this, tr( "Loading shortcuts" ),
164
tr( "The file is not an shortcuts exchange file." ) );
169
QString currentLocale;
171
bool localeOverrideFlag = settings.value( "locale/overrideFlag", false ).toBool();
172
if ( localeOverrideFlag )
174
currentLocale = settings.value( "locale/userLocale", "en_US" ).toString();
176
else // use QGIS locale
178
currentLocale = QLocale::system().name();
181
if ( root.attribute( "locale" ) != currentLocale )
183
QMessageBox::information( this, tr( "Loading shortcuts" ),
184
tr( "The file contains shortcuts created with different locale, so you can't use it." ) );
190
QString actionShortcut;
192
QDomElement child = root.firstChildElement();
193
while ( !child.isNull() )
195
actionName = child.attribute( "name" );
196
actionShortcut = child.attribute( "shortcut" );
197
action = QgsShortcutsManager::instance()->actionByName( actionName );
198
QgsShortcutsManager::instance()->setActionShortcut( action, actionShortcut );
199
child = child.nextSiblingElement();
202
treeActions->clear();
206
void QgsConfigureShortcutsDialog::changeShortcut()
208
setFocus(); // make sure we have focus
209
setGettingShortcut( true );
212
void QgsConfigureShortcutsDialog::resetShortcut()
214
QAction* action = currentAction();
215
if ( !action ) return;
217
// set default shortcut
218
QString shortcut = QgsShortcutsManager::instance()->actionDefaultShortcut( action );
219
setCurrentActionShortcut( shortcut );
222
void QgsConfigureShortcutsDialog::setNoShortcut()
224
setCurrentActionShortcut( QKeySequence() );
227
QAction* QgsConfigureShortcutsDialog::currentAction()
229
if ( treeActions->currentItem() == NULL )
232
QObject* action = treeActions->currentItem()->data( 0, Qt::UserRole ).value<QObject*>();
233
return qobject_cast<QAction*>( action );
236
void QgsConfigureShortcutsDialog::actionChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
238
// cancel previous shortcut setting (if any)
239
setGettingShortcut( false );
241
QAction* action = currentAction();
245
// show which one is the default action
246
QString shortcut = QgsShortcutsManager::instance()->actionDefaultShortcut( action );
247
if ( shortcut.isEmpty() )
248
shortcut = tr( "None" );
249
btnResetShortcut->setText( tr( "Set default (%1)" ).arg( shortcut ) );
251
// if there's no shortcut, disable set none
252
btnSetNoShortcut->setEnabled( !action->shortcut().isEmpty() );
253
// if the shortcut is default, disable set default
254
btnResetShortcut->setEnabled( action->shortcut() != QKeySequence( shortcut ) );
257
void QgsConfigureShortcutsDialog::keyPressEvent( QKeyEvent * event )
259
if ( !mGettingShortcut )
261
QDialog::keyPressEvent( event );
265
int key = event->key();
270
mModifiers |= Qt::META;
271
updateShortcutText();
274
mModifiers |= Qt::ALT;
275
updateShortcutText();
277
case Qt::Key_Control:
278
mModifiers |= Qt::CTRL;
279
updateShortcutText();
282
mModifiers |= Qt::SHIFT;
283
updateShortcutText();
286
// escape aborts the acquisition of shortcut
288
setGettingShortcut( false );
293
updateShortcutText();
297
void QgsConfigureShortcutsDialog::keyReleaseEvent( QKeyEvent * event )
299
if ( !mGettingShortcut )
301
QDialog::keyPressEvent( event );
305
int key = event->key();
310
mModifiers &= ~Qt::META;
311
updateShortcutText();
314
mModifiers &= ~Qt::ALT;
315
updateShortcutText();
317
case Qt::Key_Control:
318
mModifiers &= ~Qt::CTRL;
319
updateShortcutText();
322
mModifiers &= ~Qt::SHIFT;
323
updateShortcutText();
331
// an ordinary key - set it with modifiers as a shortcut
332
setCurrentActionShortcut( QKeySequence( mModifiers + mKey ) );
333
setGettingShortcut( false );
338
void QgsConfigureShortcutsDialog::updateShortcutText()
340
// update text of the button so that user can see what has typed already
341
QKeySequence s( mModifiers + mKey );
342
btnChangeShortcut->setText( tr( "Input: " ) + s.toString() );
345
void QgsConfigureShortcutsDialog::setGettingShortcut( bool getting )
349
mGettingShortcut = getting;
352
btnChangeShortcut->setChecked( false );
353
btnChangeShortcut->setText( tr( "Change" ) );
357
updateShortcutText();
361
void QgsConfigureShortcutsDialog::setCurrentActionShortcut( QKeySequence s )
363
QAction* action = currentAction();
364
if ( !action ) return;
366
// first check whether this action is not taken already
367
QAction* otherAction = QgsShortcutsManager::instance()->actionForShortcut( s );
368
if ( otherAction != NULL )
370
QString otherActionText = otherAction->text();
371
otherActionText.remove( '&' ); // remove the accelerator
373
int res = QMessageBox::question( this, tr( "Shortcut conflict" ),
374
tr( "This shortcut is already assigned to action %1. Reassign?" ).arg( otherActionText ),
375
QMessageBox::Yes | QMessageBox::No );
377
if ( res != QMessageBox::Yes )
380
// reset action of the conflicting other action!
381
QgsShortcutsManager::instance()->setActionShortcut( otherAction, QString() );
382
QList<QTreeWidgetItem*> items = treeActions->findItems( otherActionText, Qt::MatchExactly );
383
if ( items.count() > 0 ) // there should be exactly one
384
items[0]->setText( 1, QString() );
388
QgsShortcutsManager::instance()->setActionShortcut( action, s.toString() );
391
treeActions->currentItem()->setText( 1, s.toString() );
393
actionChanged( treeActions->currentItem(), NULL );