Skip to content

Commit 2967d94

Browse files
author
wonder
committed
New feature: configure shortcuts for actions within main window of qgis!
See menu Setting->Configure shortcuts git-svn-id: http://svn.osgeo.org/qgis/trunk@10730 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 8eda772 commit 2967d94

7 files changed

+569
-51
lines changed

src/app/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ SET(QGIS_APP_SRCS
1010
qgsbookmarks.cpp
1111
qgsclipboard.cpp
1212
qgscontinuouscolordialog.cpp
13+
qgsconfigureshortcutsdialog.cpp
1314
qgscustomprojectiondialog.cpp
1415
qgsdbfilterproxymodel.cpp
1516
qgsdbtablemodel.cpp
@@ -54,6 +55,7 @@ SET(QGIS_APP_SRCS
5455
qgsrasterlayerproperties.cpp
5556
qgssearchquerybuilder.cpp
5657
qgsserversourceselect.cpp
58+
qgsshortcutsmanager.cpp
5759
qgssinglesymboldialog.cpp
5860
qgssnappingdialog.cpp
5961
qgsuniquevaluedialog.cpp
@@ -105,6 +107,7 @@ SET (QGIS_APP_MOC_HDRS
105107
qgsattributedialog.h
106108
qgsbookmarks.h
107109
qgscontinuouscolordialog.h
110+
qgsconfigureshortcutsdialog.h
108111
qgscustomprojectiondialog.h
109112
qgsdelattrdialog.h
110113
qgsgeomtypedialog.h

src/app/qgisapp.cpp

+98-51
Large diffs are not rendered by default.

src/app/qgisapp.h

+4
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ class QgisApp : public QMainWindow
280280
QAction *actionSettingsSeparator1() { return mActionSettingsSeparator1; }
281281
QAction *actionOptions() { return mActionOptions; }
282282
QAction *actionCustomProjection() { return mActionCustomProjection; }
283+
QAction *actionConfigureShortcuts() { return mActionConfigureShortcuts; }
283284

284285
#ifdef Q_WS_MAC
285286
QAction *actionWindowMinimize() { return mActionWindowMinimize; }
@@ -461,6 +462,8 @@ class QgisApp : public QMainWindow
461462
void checkQgisVersion();
462463
//!Invoke the custom projection dialog
463464
void customProjection();
465+
//! configure shortcuts
466+
void configureShortcuts();
464467
//! options dialog slot
465468
void options();
466469
//! Whats-this help slot
@@ -769,6 +772,7 @@ class QgisApp : public QMainWindow
769772
QAction *mActionSettingsSeparator1;
770773
QAction *mActionOptions;
771774
QAction *mActionCustomProjection;
775+
QAction *mActionConfigureShortcuts;
772776

773777
#ifdef Q_WS_MAC
774778
QAction *mActionWindowMinimize;
+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
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+
QgsConfigureShortcutsDialog::QgsConfigureShortcutsDialog(QWidget* parent)
27+
: QDialog(parent), mGettingShortcut(false)
28+
{
29+
setupUi(this);
30+
31+
connect(btnChangeShortcut, SIGNAL(clicked()), this, SLOT(changeShortcut()));
32+
connect(btnResetShortcut, SIGNAL(clicked()), this, SLOT(resetShortcut()));
33+
connect(btnSetNoShortcut, SIGNAL(clicked()), this, SLOT(setNoShortcut()));
34+
35+
connect(treeActions, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
36+
this, SLOT(actionChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
37+
38+
populateActions();
39+
}
40+
41+
void QgsConfigureShortcutsDialog::populateActions()
42+
{
43+
QList<QAction*> actions = QgsShortcutsManager::instance()->listActions();
44+
45+
QList<QTreeWidgetItem *> items;
46+
for (int i = 0; i < actions.count(); ++i)
47+
{
48+
QString actionText = actions[i]->text();
49+
actionText.remove('&'); // remove the accelerator
50+
51+
QStringList lst; lst << actionText << actions[i]->shortcut().toString();
52+
QTreeWidgetItem* item = new QTreeWidgetItem(lst);
53+
item->setIcon(0, actions[i]->icon());
54+
item->setData(0, Qt::UserRole, qVariantFromValue((QObject*)actions[i]) );
55+
items.append(item);
56+
}
57+
58+
treeActions->addTopLevelItems(items);
59+
60+
// make sure everything's visible and sorted
61+
treeActions->resizeColumnToContents(0);
62+
treeActions->sortItems(0, Qt::AscendingOrder);
63+
64+
actionChanged(treeActions->currentItem(), NULL);
65+
}
66+
67+
68+
void QgsConfigureShortcutsDialog::changeShortcut()
69+
{
70+
setFocus(); // make sure we have focus
71+
setGettingShortcut(true);
72+
}
73+
74+
void QgsConfigureShortcutsDialog::resetShortcut()
75+
{
76+
QAction* action = currentAction();
77+
if ( !action ) return;
78+
79+
// set default shortcut
80+
QString shortcut = QgsShortcutsManager::instance()->actionDefaultShortcut( action );
81+
setCurrentActionShortcut( shortcut );
82+
}
83+
84+
void QgsConfigureShortcutsDialog::setNoShortcut()
85+
{
86+
setCurrentActionShortcut( QKeySequence() );
87+
}
88+
89+
QAction* QgsConfigureShortcutsDialog::currentAction()
90+
{
91+
if (treeActions->currentItem() == NULL)
92+
return NULL;
93+
94+
QObject* action = treeActions->currentItem()->data(0, Qt::UserRole).value<QObject*>();
95+
return qobject_cast<QAction*>(action);
96+
}
97+
98+
void QgsConfigureShortcutsDialog::actionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
99+
{
100+
// cancel previous shortcut setting (if any)
101+
setGettingShortcut(false);
102+
103+
QAction* action = currentAction();
104+
if ( !action )
105+
return;
106+
107+
// show which one is the default action
108+
QString shortcut = QgsShortcutsManager::instance()->actionDefaultShortcut( action );
109+
if (shortcut.isEmpty())
110+
shortcut = tr("None");
111+
btnResetShortcut->setText( tr("Set default (%1)").arg(shortcut) );
112+
113+
// if there's no shortcut, disable set none
114+
btnSetNoShortcut->setEnabled( !action->shortcut().isEmpty() );
115+
// if the shortcut is default, disable set default
116+
btnResetShortcut->setEnabled( action->shortcut() != QKeySequence(shortcut) );
117+
}
118+
119+
void QgsConfigureShortcutsDialog::keyPressEvent ( QKeyEvent * event )
120+
{
121+
if (!mGettingShortcut)
122+
{
123+
QDialog::keyPressEvent(event);
124+
return;
125+
}
126+
127+
int key = event->key();
128+
switch (key)
129+
{
130+
// modifiers
131+
case Qt::Key_Meta:
132+
mModifiers |= Qt::META;
133+
updateShortcutText();
134+
break;
135+
case Qt::Key_Alt:
136+
mModifiers |= Qt::ALT;
137+
updateShortcutText();
138+
break;
139+
case Qt::Key_Control:
140+
mModifiers |= Qt::CTRL;
141+
updateShortcutText();
142+
break;
143+
case Qt::Key_Shift:
144+
mModifiers |= Qt::SHIFT;
145+
updateShortcutText();
146+
break;
147+
148+
// escape aborts the acquisition of shortcut
149+
case Qt::Key_Escape:
150+
setGettingShortcut(false);
151+
break;
152+
153+
default:
154+
mKey = key;
155+
updateShortcutText();
156+
}
157+
}
158+
159+
void QgsConfigureShortcutsDialog::keyReleaseEvent ( QKeyEvent * event )
160+
{
161+
if (!mGettingShortcut)
162+
{
163+
QDialog::keyPressEvent(event);
164+
return;
165+
}
166+
167+
int key = event->key();
168+
switch (key)
169+
{
170+
// modifiers
171+
case Qt::Key_Meta:
172+
mModifiers &= ~Qt::META;
173+
updateShortcutText();
174+
break;
175+
case Qt::Key_Alt:
176+
mModifiers &= ~Qt::ALT;
177+
updateShortcutText();
178+
break;
179+
case Qt::Key_Control:
180+
mModifiers &= ~Qt::CTRL;
181+
updateShortcutText();
182+
break;
183+
case Qt::Key_Shift:
184+
mModifiers &= ~Qt::SHIFT;
185+
updateShortcutText();
186+
break;
187+
188+
case Qt::Key_Escape:
189+
break;
190+
191+
default:
192+
{
193+
// an ordinary key - set it with modifiers as a shortcut
194+
setCurrentActionShortcut( QKeySequence(mModifiers + mKey) );
195+
setGettingShortcut(false);
196+
}
197+
}
198+
}
199+
200+
201+
void QgsConfigureShortcutsDialog::updateShortcutText()
202+
{
203+
// update text of the button so that user can see what has typed already
204+
QKeySequence s(mModifiers + mKey);
205+
btnChangeShortcut->setText( tr("Input: ") + s.toString() );
206+
}
207+
208+
void QgsConfigureShortcutsDialog::setGettingShortcut(bool getting)
209+
{
210+
mModifiers = 0;
211+
mKey = 0;
212+
mGettingShortcut = getting;
213+
if (!getting)
214+
{
215+
btnChangeShortcut->setChecked(false);
216+
btnChangeShortcut->setText(tr("Change"));
217+
}
218+
else
219+
{
220+
updateShortcutText();
221+
}
222+
}
223+
224+
void QgsConfigureShortcutsDialog::setCurrentActionShortcut(QKeySequence s)
225+
{
226+
QAction* action = currentAction();
227+
if ( !action ) return;
228+
229+
// first check whether this action is not taken already
230+
QAction* otherAction = QgsShortcutsManager::instance()->actionForShortcut(s);
231+
if (otherAction != NULL)
232+
{
233+
QString otherActionText = otherAction->text();
234+
otherActionText.remove('&'); // remove the accelerator
235+
236+
int res = QMessageBox::question( this, tr("Shortcut conflict"),
237+
tr("This shortcut is already assigned to action %1. Reassign?").arg(otherActionText),
238+
QMessageBox::Yes | QMessageBox::No);
239+
240+
if (res != QMessageBox::Yes)
241+
return;
242+
243+
// reset action of the conflicting other action!
244+
QgsShortcutsManager::instance()->setActionShortcut( otherAction, QString() );
245+
QList<QTreeWidgetItem*> items = treeActions->findItems(otherActionText, Qt::MatchExactly);
246+
if (items.count() > 0) // there should be exactly one
247+
items[0]->setText(1, QString() );
248+
}
249+
250+
// update manager
251+
QgsShortcutsManager::instance()->setActionShortcut( action, s.toString() );
252+
253+
// update gui
254+
treeActions->currentItem()->setText(1, s.toString() );
255+
256+
actionChanged( treeActions->currentItem(), NULL );
257+
}

src/app/qgsconfigureshortcutsdialog.h

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
qgsconfigureshortcutsdialog.h
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+
#ifndef QGSCONFIGURESHORTCUTSDIALOG_H
17+
#define QGSCONFIGURESHORTCUTSDIALOG_H
18+
19+
#include <QDialog>
20+
21+
#include "ui_qgsconfigureshortcutsdialog.h"
22+
23+
class QgsConfigureShortcutsDialog : public QDialog, private Ui::QgsConfigureShortcutsDialog
24+
{
25+
Q_OBJECT
26+
27+
public:
28+
QgsConfigureShortcutsDialog(QWidget* parent = NULL);
29+
30+
void populateActions();
31+
32+
protected:
33+
void keyPressEvent( QKeyEvent * event );
34+
void keyReleaseEvent( QKeyEvent * event );
35+
36+
QAction* currentAction();
37+
38+
void setGettingShortcut(bool getting);
39+
void setCurrentActionShortcut(QKeySequence s);
40+
void updateShortcutText();
41+
42+
public slots:
43+
void changeShortcut();
44+
void resetShortcut();
45+
void setNoShortcut();
46+
47+
void actionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
48+
49+
protected:
50+
bool mGettingShortcut;
51+
int mModifiers, mKey;
52+
};
53+
54+
#endif

0 commit comments

Comments
 (0)