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,.