21 #include "qgssettings.h"
25 #include <QKeySequence>
26 #include <QMessageBox>
28 #include <QDomDocument>
29 #include <QFileDialog>
30 #include <QTextStream>
39 connect( mLeFilter, &QgsFilterLineEdit::textChanged,
this, &QgsConfigureShortcutsDialog::mLeFilter_textChanged );
44 connect( buttonBox, &QDialogButtonBox::helpRequested,
this, &QgsConfigureShortcutsDialog::showHelp );
45 connect( btnChangeShortcut, &QAbstractButton::clicked,
this, &QgsConfigureShortcutsDialog::changeShortcut );
46 connect( btnResetShortcut, &QAbstractButton::clicked,
this, &QgsConfigureShortcutsDialog::resetShortcut );
47 connect( btnSetNoShortcut, &QAbstractButton::clicked,
this, &QgsConfigureShortcutsDialog::setNoShortcut );
48 connect( btnSaveShortcuts, &QAbstractButton::clicked,
this, &QgsConfigureShortcutsDialog::saveShortcuts );
49 connect( btnLoadShortcuts, &QAbstractButton::clicked,
this, &QgsConfigureShortcutsDialog::loadShortcuts );
51 connect( treeActions, &QTreeWidget::currentItemChanged,
52 this, &QgsConfigureShortcutsDialog::actionChanged );
57 void QgsConfigureShortcutsDialog::populateActions()
59 QList<QObject *> objects = mManager->
listAll();
61 QList<QTreeWidgetItem *> items;
62 items.reserve( objects.count() );
63 const auto constObjects = objects;
64 for ( QObject *obj : constObjects )
70 if ( QAction *action = qobject_cast< QAction * >( obj ) )
72 actionText = action->text();
73 actionText.remove(
'&' );
74 sequence = action->shortcut().toString( QKeySequence::NativeText );
75 icon = action->icon();
77 else if ( QShortcut *shortcut = qobject_cast< QShortcut * >( obj ) )
79 actionText = shortcut->whatsThis();
80 sequence = shortcut->key().toString( QKeySequence::NativeText );
81 icon = shortcut->property(
"Icon" ).value<QIcon>();
88 if ( actionText.isEmpty() )
94 lst << actionText << sequence;
95 QTreeWidgetItem *item =
new QTreeWidgetItem( lst );
96 item->setIcon( 0, icon );
97 item->setData( 0, Qt::UserRole, QVariant::fromValue( obj ) );
101 treeActions->addTopLevelItems( items );
104 treeActions->resizeColumnToContents( 0 );
105 treeActions->sortItems( 0, Qt::AscendingOrder );
107 actionChanged( treeActions->currentItem(),
nullptr );
110 void QgsConfigureShortcutsDialog::saveShortcuts()
112 QString fileName = QFileDialog::getSaveFileName(
this, tr(
"Save Shortcuts" ), QDir::homePath(),
113 tr(
"XML file" ) +
" (*.xml);;" + tr(
"All files" ) +
" (*)" );
115 if ( fileName.isEmpty() )
119 if ( !fileName.endsWith( QLatin1String(
".xml" ), Qt::CaseInsensitive ) )
121 fileName += QLatin1String(
".xml" );
124 QFile file( fileName );
125 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
127 QMessageBox::warning(
this, tr(
"Saving Shortcuts" ),
128 tr(
"Cannot write file %1:\n%2." )
130 file.errorString() ) );
134 QgsSettings settings;
136 QDomDocument doc( QStringLiteral(
"shortcuts" ) );
137 QDomElement root = doc.createElement( QStringLiteral(
"qgsshortcuts" ) );
138 root.setAttribute( QStringLiteral(
"version" ), QStringLiteral(
"1.0" ) );
140 doc.appendChild( root );
143 QStringList keys = settings.childKeys();
146 QString actionShortcut;
148 for (
int i = 0; i < keys.count(); ++i )
150 actionText = keys[ i ];
151 actionShortcut = settings.value( actionText,
"" ).toString();
153 QDomElement el = doc.createElement( QStringLiteral(
"act" ) );
154 el.setAttribute( QStringLiteral(
"name" ), actionText );
155 el.setAttribute( QStringLiteral(
"shortcut" ), actionShortcut );
156 root.appendChild( el );
159 QTextStream out( &file );
163 void QgsConfigureShortcutsDialog::loadShortcuts()
165 QString fileName = QFileDialog::getOpenFileName(
this, tr(
"Load Shortcuts" ), QDir::homePath(),
166 tr(
"XML file" ) +
" (*.xml);;" + tr(
"All files" ) +
" (*)" );
168 if ( fileName.isEmpty() )
173 QFile file( fileName );
174 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
176 QMessageBox::warning(
this, tr(
"Loading Shortcuts" ),
177 tr(
"Cannot read file %1:\n%2." )
179 file.errorString() ) );
188 if ( !doc.setContent( &file,
true, &errorStr, &errorLine, &errorColumn ) )
190 QMessageBox::information(
this, tr(
"Loading Shortcuts" ),
191 tr(
"Parse error at line %1, column %2:\n%3" )
198 QDomElement root = doc.documentElement();
199 if ( root.tagName() != QLatin1String(
"qgsshortcuts" ) )
201 QMessageBox::information(
this, tr(
"Loading Shortcuts" ),
202 tr(
"The file is not an shortcuts exchange file." ) );
206 QString currentLocale;
209 if ( localeOverrideFlag )
215 currentLocale = QLocale().name();
218 if ( root.attribute( QStringLiteral(
"locale" ) ) != currentLocale )
220 QMessageBox::information(
this, tr(
"Loading Shortcuts" ),
221 tr(
"The file contains shortcuts created with different locale, so you can't use it." ) );
226 QString actionShortcut;
228 QDomElement child = root.firstChildElement();
229 while ( !child.isNull() )
231 actionName = child.attribute( QStringLiteral(
"name" ) );
232 actionShortcut = child.attribute( QStringLiteral(
"shortcut" ) );
235 child = child.nextSiblingElement();
238 treeActions->clear();
242 void QgsConfigureShortcutsDialog::changeShortcut()
245 setGettingShortcut(
true );
248 void QgsConfigureShortcutsDialog::resetShortcut()
250 QObject *
object = currentObject();
252 setCurrentActionShortcut( sequence );
255 void QgsConfigureShortcutsDialog::setNoShortcut()
257 setCurrentActionShortcut( QKeySequence() );
260 QAction *QgsConfigureShortcutsDialog::currentAction()
262 return qobject_cast<QAction *>( currentObject() );
265 QShortcut *QgsConfigureShortcutsDialog::currentShortcut()
267 return qobject_cast<QShortcut *>( currentObject() );
270 void QgsConfigureShortcutsDialog::actionChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
275 setGettingShortcut(
false );
278 QKeySequence sequence;
279 if ( QAction *action = currentAction() )
283 sequence = action->shortcut();
285 else if ( QShortcut *
object = currentShortcut() )
289 sequence =
object->key();
296 if ( shortcut.isEmpty() )
297 shortcut = tr(
"None" );
298 btnResetShortcut->setText( tr(
"Set default (%1)" ).arg( shortcut ) );
301 btnSetNoShortcut->setEnabled( !sequence.isEmpty() );
303 btnResetShortcut->setEnabled( sequence != QKeySequence( shortcut ) );
308 if ( !mGettingShortcut )
310 QDialog::keyPressEvent( event );
314 int key =
event->key();
319 mModifiers |= Qt::META;
320 updateShortcutText();
323 mModifiers |= Qt::ALT;
324 updateShortcutText();
326 case Qt::Key_Control:
327 mModifiers |= Qt::CTRL;
328 updateShortcutText();
331 mModifiers |= Qt::SHIFT;
332 updateShortcutText();
337 setGettingShortcut(
false );
342 updateShortcutText();
348 if ( !mGettingShortcut )
350 QDialog::keyReleaseEvent( event );
354 int key =
event->key();
359 mModifiers &= ~Qt::META;
360 updateShortcutText();
363 mModifiers &= ~Qt::ALT;
364 updateShortcutText();
366 case Qt::Key_Control:
367 mModifiers &= ~Qt::CTRL;
368 updateShortcutText();
371 mModifiers &= ~Qt::SHIFT;
372 updateShortcutText();
381 setCurrentActionShortcut( QKeySequence( mModifiers + mKey ) );
382 setGettingShortcut(
false );
387 QObject *QgsConfigureShortcutsDialog::currentObject()
389 if ( !treeActions->currentItem() )
392 QObject *
object = treeActions->currentItem()->data( 0, Qt::UserRole ).value<QObject *>();
396 void QgsConfigureShortcutsDialog::updateShortcutText()
399 QKeySequence s( mModifiers + mKey );
400 btnChangeShortcut->setText( tr(
"Input: " ) + s.toString( QKeySequence::NativeText ) );
403 void QgsConfigureShortcutsDialog::setGettingShortcut(
bool getting )
407 mGettingShortcut = getting;
410 btnChangeShortcut->setChecked(
false );
411 btnChangeShortcut->setText( tr(
"Change" ) );
415 updateShortcutText();
419 void QgsConfigureShortcutsDialog::setCurrentActionShortcut(
const QKeySequence &s )
421 QObject *
object = currentObject();
427 if ( otherObject ==
object )
433 if ( QAction *otherAction = qobject_cast< QAction * >( otherObject ) )
435 otherText = otherAction->text();
436 otherText.remove(
'&' );
438 else if ( QShortcut *otherShortcut = qobject_cast< QShortcut * >( otherObject ) )
440 otherText = otherShortcut->whatsThis();
443 int res = QMessageBox::question(
this, tr(
"Change Shortcut" ),
444 tr(
"This shortcut is already assigned to action %1. Reassign?" ).arg( otherText ),
445 QMessageBox::Yes | QMessageBox::No );
447 if ( res != QMessageBox::Yes )
452 QList<QTreeWidgetItem *> items = treeActions->findItems( otherText, Qt::MatchExactly );
453 if ( !items.isEmpty() )
454 items[0]->setText( 1, QString() );
461 treeActions->currentItem()->setText( 1, s.toString( QKeySequence::NativeText ) );
463 actionChanged( treeActions->currentItem(),
nullptr );
466 void QgsConfigureShortcutsDialog::mLeFilter_textChanged(
const QString &text )
468 for (
int i = 0; i < treeActions->topLevelItemCount(); i++ )
470 QTreeWidgetItem *item = treeActions->topLevelItem( i );
471 if ( !item->text( 0 ).contains( text, Qt::CaseInsensitive ) && !item->text( 1 ).contains( text, Qt::CaseInsensitive ) )
473 item->setHidden(
true );
477 item->setHidden(
false );
482 void QgsConfigureShortcutsDialog::showHelp()
484 QgsHelp::openHelp( QStringLiteral(
"introduction/qgis_configuration.html#keyboard-shortcuts" ) );
static const QgsSettingsEntryBool settingsLocaleOverrideFlag
Settings entry locale override flag.
static const QgsSettingsEntryString settingsLocaleUserLocale
Settings entry locale user locale.
static QgsShortcutsManager * shortcutsManager()
Returns the global shortcuts manager, used for managing a QAction and QShortcut sequences.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Shortcuts manager is a class that contains a list of QActions and QShortcuts that have been registere...
QString settingsPath() const
Returns the root settings path used to store shortcut customization.
bool setKeySequence(const QString &name, const QString &sequence)
Modifies an action or shortcut's key sequence.
QList< QObject * > listAll() const
Returns a list of both actions and shortcuts in the manager.
QString objectDefaultKeySequence(QObject *object) const
Returns the default sequence for an object (either a QAction or QShortcut).
QString defaultKeySequence(QAction *action) const
Returns the default sequence for an action.
bool setObjectKeySequence(QObject *object, const QString &sequence)
Modifies an object's (either a QAction or a QShortcut) key sequence.
QObject * objectForSequence(const QKeySequence &sequence) const
Returns the object (QAction or QShortcut) matching the specified key sequence,.