~ubuntu-branches/ubuntu/trusty/qgis/trusty

« back to all changes in this revision

Viewing changes to src/app/qgsconfigureshortcutsdialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    qgsconfigureshortcutsdialog.cpp
 
3
    ---------------------
 
4
    begin                : May 2009
 
5
    copyright            : (C) 2009 by Martin Dobias
 
6
    email                : wonder dot sk at gmail 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 "qgsconfigureshortcutsdialog.h"
 
17
 
 
18
#include "qgsshortcutsmanager.h"
 
19
 
 
20
#include "qgslogger.h"
 
21
 
 
22
#include <QKeyEvent>
 
23
#include <QKeySequence>
 
24
#include <QMessageBox>
 
25
 
 
26
#include <QDomDocument>
 
27
#include <QFileDialog>
 
28
#include <QTextStream>
 
29
#include <QSettings>
 
30
 
 
31
QgsConfigureShortcutsDialog::QgsConfigureShortcutsDialog( QWidget* parent )
 
32
    : QDialog( parent ), mGettingShortcut( false )
 
33
{
 
34
  setupUi( this );
 
35
 
 
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() ) );
 
41
 
 
42
  connect( treeActions, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ),
 
43
           this, SLOT( actionChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
 
44
 
 
45
  populateActions();
 
46
}
 
47
 
 
48
void QgsConfigureShortcutsDialog::populateActions()
 
49
{
 
50
  QList<QAction*> actions = QgsShortcutsManager::instance()->listActions();
 
51
 
 
52
  QList<QTreeWidgetItem *> items;
 
53
  for ( int i = 0; i < actions.count(); ++i )
 
54
  {
 
55
    QString actionText = actions[i]->text();
 
56
    actionText.remove( '&' ); // remove the accelerator
 
57
 
 
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] ) );
 
62
    items.append( item );
 
63
  }
 
64
 
 
65
  treeActions->addTopLevelItems( items );
 
66
 
 
67
  // make sure everything's visible and sorted
 
68
  treeActions->resizeColumnToContents( 0 );
 
69
  treeActions->sortItems( 0, Qt::AscendingOrder );
 
70
 
 
71
  actionChanged( treeActions->currentItem(), NULL );
 
72
}
 
73
 
 
74
void QgsConfigureShortcutsDialog::saveShortcuts()
 
75
{
 
76
  QString fileName = QFileDialog::getSaveFileName( this, tr( "Save shortcuts" ), ".", tr( "XML file (*.xml);; All files (*.*)" ) );
 
77
 
 
78
  if ( fileName.isEmpty() )
 
79
    return;
 
80
 
 
81
  // ensure the user never omitted the extension from the file name
 
82
  if ( !fileName.toLower().endsWith( ".xml" ) )
 
83
  {
 
84
    fileName += ".xml";
 
85
  }
 
86
 
 
87
  QFile file( fileName );
 
88
  if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
 
89
  {
 
90
    QMessageBox::warning( this, tr( "Saving shortcuts" ),
 
91
                          tr( "Cannot write file %1:\n%2." )
 
92
                          .arg( fileName )
 
93
                          .arg( file.errorString() ) );
 
94
    return;
 
95
  }
 
96
 
 
97
  QSettings settings;
 
98
 
 
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 );
 
104
 
 
105
  settings.beginGroup( "/shortcuts/" );
 
106
  QStringList keys = settings.childKeys();
 
107
 
 
108
  QString actionText;
 
109
  QString actionShortcut;
 
110
 
 
111
  for ( int i = 0; i < keys.count(); ++i )
 
112
  {
 
113
    actionText = keys[ i ];
 
114
    actionShortcut = settings.value( actionText, "" ).toString();
 
115
 
 
116
    QDomElement el = doc.createElement( "act" );
 
117
    el.setAttribute( "name", actionText );
 
118
    el.setAttribute( "shortcut", actionShortcut );
 
119
    root.appendChild( el );
 
120
  }
 
121
 
 
122
  QTextStream out( &file );
 
123
  doc.save( out, 4 );
 
124
}
 
125
 
 
126
void QgsConfigureShortcutsDialog::loadShortcuts()
 
127
{
 
128
  QString fileName = QFileDialog::getOpenFileName( this, tr( "Load shortcuts" ), ".", tr( "XML file (*.xml);; All files (*.*)" ) );
 
129
 
 
130
  if ( fileName.isEmpty() )
 
131
  {
 
132
    return;
 
133
  }
 
134
 
 
135
  QFile file( fileName );
 
136
  if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
 
137
  {
 
138
    QMessageBox::warning( this, tr( "Loading shortcuts" ),
 
139
                          tr( "Cannot read file %1:\n%2." )
 
140
                          .arg( fileName )
 
141
                          .arg( file.errorString() ) );
 
142
    return;
 
143
  }
 
144
 
 
145
  QDomDocument  doc;
 
146
  QString errorStr;
 
147
  int errorLine;
 
148
  int errorColumn;
 
149
 
 
150
  if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
 
151
  {
 
152
    QMessageBox::information( this, tr( "Loading shortcuts" ),
 
153
                              tr( "Parse error at line %1, column %2:\n%3" )
 
154
                              .arg( errorLine )
 
155
                              .arg( errorColumn )
 
156
                              .arg( errorStr ) );
 
157
    return;
 
158
  }
 
159
 
 
160
  QDomElement root = doc.documentElement();
 
161
  if ( root.tagName() != "qgsshortcuts" )
 
162
  {
 
163
    QMessageBox::information( this, tr( "Loading shortcuts" ),
 
164
                              tr( "The file is not an shortcuts exchange file." ) );
 
165
    return;
 
166
  }
 
167
 
 
168
  QSettings settings;
 
169
  QString currentLocale;
 
170
 
 
171
  bool localeOverrideFlag = settings.value( "locale/overrideFlag", false ).toBool();
 
172
  if ( localeOverrideFlag )
 
173
  {
 
174
    currentLocale = settings.value( "locale/userLocale", "en_US" ).toString();
 
175
  }
 
176
  else // use QGIS locale
 
177
  {
 
178
    currentLocale = QLocale::system().name();
 
179
  }
 
180
 
 
181
  if ( root.attribute( "locale" ) != currentLocale )
 
182
  {
 
183
    QMessageBox::information( this, tr( "Loading shortcuts" ),
 
184
                              tr( "The file contains shortcuts created with different locale, so you can't use it." ) );
 
185
    return;
 
186
  }
 
187
 
 
188
  QAction* action;
 
189
  QString actionName;
 
190
  QString actionShortcut;
 
191
 
 
192
  QDomElement child = root.firstChildElement();
 
193
  while ( !child.isNull() )
 
194
  {
 
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();
 
200
  }
 
201
 
 
202
  treeActions->clear();
 
203
  populateActions();
 
204
}
 
205
 
 
206
void QgsConfigureShortcutsDialog::changeShortcut()
 
207
{
 
208
  setFocus(); // make sure we have focus
 
209
  setGettingShortcut( true );
 
210
}
 
211
 
 
212
void QgsConfigureShortcutsDialog::resetShortcut()
 
213
{
 
214
  QAction* action = currentAction();
 
215
  if ( !action ) return;
 
216
 
 
217
  // set default shortcut
 
218
  QString shortcut = QgsShortcutsManager::instance()->actionDefaultShortcut( action );
 
219
  setCurrentActionShortcut( shortcut );
 
220
}
 
221
 
 
222
void QgsConfigureShortcutsDialog::setNoShortcut()
 
223
{
 
224
  setCurrentActionShortcut( QKeySequence() );
 
225
}
 
226
 
 
227
QAction* QgsConfigureShortcutsDialog::currentAction()
 
228
{
 
229
  if ( treeActions->currentItem() == NULL )
 
230
    return NULL;
 
231
 
 
232
  QObject* action = treeActions->currentItem()->data( 0, Qt::UserRole ).value<QObject*>();
 
233
  return qobject_cast<QAction*>( action );
 
234
}
 
235
 
 
236
void QgsConfigureShortcutsDialog::actionChanged( QTreeWidgetItem* current, QTreeWidgetItem* previous )
 
237
{
 
238
  // cancel previous shortcut setting (if any)
 
239
  setGettingShortcut( false );
 
240
 
 
241
  QAction* action = currentAction();
 
242
  if ( !action )
 
243
    return;
 
244
 
 
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 ) );
 
250
 
 
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 ) );
 
255
}
 
256
 
 
257
void QgsConfigureShortcutsDialog::keyPressEvent( QKeyEvent * event )
 
258
{
 
259
  if ( !mGettingShortcut )
 
260
  {
 
261
    QDialog::keyPressEvent( event );
 
262
    return;
 
263
  }
 
264
 
 
265
  int key = event->key();
 
266
  switch ( key )
 
267
  {
 
268
      // modifiers
 
269
    case Qt::Key_Meta:
 
270
      mModifiers |= Qt::META;
 
271
      updateShortcutText();
 
272
      break;
 
273
    case Qt::Key_Alt:
 
274
      mModifiers |= Qt::ALT;
 
275
      updateShortcutText();
 
276
      break;
 
277
    case Qt::Key_Control:
 
278
      mModifiers |= Qt::CTRL;
 
279
      updateShortcutText();
 
280
      break;
 
281
    case Qt::Key_Shift:
 
282
      mModifiers |= Qt::SHIFT;
 
283
      updateShortcutText();
 
284
      break;
 
285
 
 
286
      // escape aborts the acquisition of shortcut
 
287
    case Qt::Key_Escape:
 
288
      setGettingShortcut( false );
 
289
      break;
 
290
 
 
291
    default:
 
292
      mKey = key;
 
293
      updateShortcutText();
 
294
  }
 
295
}
 
296
 
 
297
void QgsConfigureShortcutsDialog::keyReleaseEvent( QKeyEvent * event )
 
298
{
 
299
  if ( !mGettingShortcut )
 
300
  {
 
301
    QDialog::keyPressEvent( event );
 
302
    return;
 
303
  }
 
304
 
 
305
  int key = event->key();
 
306
  switch ( key )
 
307
  {
 
308
      // modifiers
 
309
    case Qt::Key_Meta:
 
310
      mModifiers &= ~Qt::META;
 
311
      updateShortcutText();
 
312
      break;
 
313
    case Qt::Key_Alt:
 
314
      mModifiers &= ~Qt::ALT;
 
315
      updateShortcutText();
 
316
      break;
 
317
    case Qt::Key_Control:
 
318
      mModifiers &= ~Qt::CTRL;
 
319
      updateShortcutText();
 
320
      break;
 
321
    case Qt::Key_Shift:
 
322
      mModifiers &= ~Qt::SHIFT;
 
323
      updateShortcutText();
 
324
      break;
 
325
 
 
326
    case Qt::Key_Escape:
 
327
      break;
 
328
 
 
329
    default:
 
330
    {
 
331
      // an ordinary key - set it with modifiers as a shortcut
 
332
      setCurrentActionShortcut( QKeySequence( mModifiers + mKey ) );
 
333
      setGettingShortcut( false );
 
334
    }
 
335
  }
 
336
}
 
337
 
 
338
void QgsConfigureShortcutsDialog::updateShortcutText()
 
339
{
 
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() );
 
343
}
 
344
 
 
345
void QgsConfigureShortcutsDialog::setGettingShortcut( bool getting )
 
346
{
 
347
  mModifiers = 0;
 
348
  mKey = 0;
 
349
  mGettingShortcut = getting;
 
350
  if ( !getting )
 
351
  {
 
352
    btnChangeShortcut->setChecked( false );
 
353
    btnChangeShortcut->setText( tr( "Change" ) );
 
354
  }
 
355
  else
 
356
  {
 
357
    updateShortcutText();
 
358
  }
 
359
}
 
360
 
 
361
void QgsConfigureShortcutsDialog::setCurrentActionShortcut( QKeySequence s )
 
362
{
 
363
  QAction* action = currentAction();
 
364
  if ( !action ) return;
 
365
 
 
366
  // first check whether this action is not taken already
 
367
  QAction* otherAction = QgsShortcutsManager::instance()->actionForShortcut( s );
 
368
  if ( otherAction != NULL )
 
369
  {
 
370
    QString otherActionText = otherAction->text();
 
371
    otherActionText.remove( '&' ); // remove the accelerator
 
372
 
 
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 );
 
376
 
 
377
    if ( res != QMessageBox::Yes )
 
378
      return;
 
379
 
 
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() );
 
385
  }
 
386
 
 
387
  // update manager
 
388
  QgsShortcutsManager::instance()->setActionShortcut( action, s.toString() );
 
389
 
 
390
  // update gui
 
391
  treeActions->currentItem()->setText( 1, s.toString() );
 
392
 
 
393
  actionChanged( treeActions->currentItem(), NULL );
 
394
}