QGIS API Documentation 3.43.0-Master (a93bf8b6462)
qgsconfigureshortcutsdialog.cpp
Go to the documentation of this file.
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
17#include "moc_qgsconfigureshortcutsdialog.cpp"
18
19#include "qgsshortcutsmanager.h"
20#include "qgsapplication.h"
21#include "qgslogger.h"
22#include "qgssettings.h"
23#include "qgsgui.h"
24#include "qgsprojectversion.h"
25
26#include <QKeyEvent>
27#include <QKeySequence>
28#include <QMessageBox>
29#include <QShortcut>
30#include <QDomDocument>
31#include <QFileDialog>
32#include <QTextStream>
33#include <QMenu>
34#include <QAction>
35#include <QPdfWriter>
36#include <QTextDocument>
37#include <QTextCursor>
38#include <QTextTable>
39#include <QTextTableFormat>
40#include <QTextTableCellFormat>
41#include <QTextCharFormat>
42
44 : QDialog( parent )
45 , mManager( manager )
46{
47 setupUi( this );
49
50 mSaveMenu = new QMenu( this );
51 mSaveUserShortcuts = new QAction( tr( "Save User Shortcuts…" ), this );
52 mSaveMenu->addAction( mSaveUserShortcuts );
53 connect( mSaveUserShortcuts, &QAction::triggered, this, [this] { saveShortcuts( false ); } );
54
55 mSaveAllShortcuts = new QAction( tr( "Save All Shortcuts…" ), this );
56 mSaveMenu->addAction( mSaveAllShortcuts );
57 connect( mSaveAllShortcuts, &QAction::triggered, this, [this] { saveShortcuts(); } );
58
59 mSaveAsPdf = new QAction( tr( "Save as PDF…" ), this );
60 mSaveMenu->addAction( mSaveAsPdf );
61 connect( mSaveAsPdf, &QAction::triggered, this, &QgsConfigureShortcutsDialog::saveShortcutsPdf );
62
63 btnSaveShortcuts->setMenu( mSaveMenu );
64
65 connect( mLeFilter, &QgsFilterLineEdit::textChanged, this, &QgsConfigureShortcutsDialog::mLeFilter_textChanged );
66
67 if ( !mManager )
68 mManager = QgsGui::shortcutsManager();
69
70 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsConfigureShortcutsDialog::showHelp ); // Vérifier nommage des boutons
71 connect( btnChangeShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::changeShortcut );
72 connect( btnResetShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::resetShortcut );
73 connect( btnSetNoShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::setNoShortcut );
74 connect( btnLoadShortcuts, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::loadShortcuts );
75
76 connect( treeActions, &QTreeWidget::currentItemChanged, this, &QgsConfigureShortcutsDialog::actionChanged );
77
78 populateActions();
79}
80
81void QgsConfigureShortcutsDialog::populateActions()
82{
83 const QList<QObject *> objects = mManager->listAll();
84
85 QList<QTreeWidgetItem *> items;
86 items.reserve( objects.count() );
87 const auto constObjects = objects;
88 for ( QObject *obj : constObjects )
89 {
90 QString actionText;
91 QString sequence;
92 QIcon icon;
93 const QString settingKey = mManager->objectSettingKey( obj );
94
95 if ( QAction *action = qobject_cast<QAction *>( obj ) )
96 {
97 actionText = action->text();
98 actionText.remove( '&' ); // remove the accelerator
99 sequence = action->shortcut().toString( QKeySequence::NativeText );
100 icon = action->icon();
101 }
102 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
103 {
104 actionText = shortcut->whatsThis();
105 sequence = shortcut->key().toString( QKeySequence::NativeText );
106 icon = shortcut->property( "Icon" ).value<QIcon>();
107 }
108 else
109 {
110 continue;
111 }
112
113 if ( actionText.isEmpty() )
114 {
115 continue;
116 }
117
118 QStringList lst;
119 lst << actionText << sequence;
120 QTreeWidgetItem *item = new QTreeWidgetItem( lst );
121 item->setIcon( 0, icon );
122 item->setData( 0, Qt::UserRole, QVariant::fromValue( obj ) );
123 item->setToolTip( 0, settingKey );
124 items.append( item );
125 }
126
127 treeActions->addTopLevelItems( items );
128
129 // make sure everything's visible and sorted
130 treeActions->resizeColumnToContents( 0 );
131 treeActions->sortItems( 0, Qt::AscendingOrder );
132
133 actionChanged( treeActions->currentItem(), nullptr );
134}
135
136void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
137{
138 QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Shortcuts" ), QDir::homePath(), tr( "XML file" ) + " (*.xml);;" + tr( "All files" ) + " (*)" );
139 // return dialog focus on Mac
140 activateWindow();
141 raise();
142
143 if ( fileName.isEmpty() )
144 return;
145
146 // ensure the user never omitted the extension from the file name
147 if ( !fileName.endsWith( QLatin1String( ".xml" ), Qt::CaseInsensitive ) )
148 {
149 fileName += QLatin1String( ".xml" );
150 }
151
152 QFile file( fileName );
153 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate ) )
154 {
155 QMessageBox::warning( this, tr( "Saving Shortcuts" ), tr( "Cannot write file %1:\n%2." ).arg( fileName, file.errorString() ) );
156 return;
157 }
158
159 QgsSettings settings;
160
161 QDomDocument doc( QStringLiteral( "shortcuts" ) );
162 QDomElement root = doc.createElement( QStringLiteral( "qgsshortcuts" ) );
163 root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1" ) );
164 root.setAttribute( QStringLiteral( "locale" ), settings.value( QgsApplication::settingsLocaleUserLocale->key(), "en_US" ).toString() );
165 doc.appendChild( root );
166
167 const QList<QObject *> objects = mManager->listAll();
168 for ( QObject *obj : objects )
169 {
170 QString actionText;
171 QString actionShortcut;
172 QString actionSettingKey;
173 QKeySequence sequence;
174
175 if ( QAction *action = qobject_cast<QAction *>( obj ) )
176 {
177 actionText = action->text().remove( '&' );
178 actionShortcut = action->shortcut().toString( QKeySequence::NativeText );
179 sequence = mManager->defaultKeySequence( action );
180 }
181 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
182 {
183 actionText = shortcut->whatsThis();
184 actionShortcut = shortcut->key().toString( QKeySequence::NativeText );
185 sequence = mManager->defaultKeySequence( shortcut );
186 }
187 else
188 {
189 continue;
190 }
191
192 actionSettingKey = mManager->objectSettingKey( obj );
193
194 if ( actionSettingKey.isEmpty() )
195 {
196 continue;
197 }
198
199 // skip unchanged shortcuts if only user-definied were requested
200 if ( !saveAll && sequence == QKeySequence( actionShortcut ) )
201 {
202 continue;
203 }
204
205 QDomElement el = doc.createElement( QStringLiteral( "action" ) );
206 el.setAttribute( QStringLiteral( "name" ), actionText );
207 el.setAttribute( QStringLiteral( "shortcut" ), actionShortcut );
208 el.setAttribute( QStringLiteral( "setting" ), actionSettingKey );
209 root.appendChild( el );
210 }
211
212 QTextStream out( &file );
213 doc.save( out, 4 );
214}
215
216void QgsConfigureShortcutsDialog::loadShortcuts()
217{
218 const QString fileName = QFileDialog::getOpenFileName( this, tr( "Load Shortcuts" ), QDir::homePath(), tr( "XML file" ) + " (*.xml);;" + tr( "All files" ) + " (*)" );
219
220 if ( fileName.isEmpty() )
221 {
222 return;
223 }
224
225 QFile file( fileName );
226 if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
227 {
228 QMessageBox::warning( this, tr( "Loading Shortcuts" ), tr( "Cannot read file %1:\n%2." ).arg( fileName, file.errorString() ) );
229 return;
230 }
231
232 QDomDocument doc;
233 QString errorStr;
234 int errorLine;
235 int errorColumn;
236
237 if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
238 {
239 QMessageBox::information( this, tr( "Loading Shortcuts" ), tr( "Parse error at line %1, column %2:\n%3" ).arg( errorLine ).arg( errorColumn ).arg( errorStr ) );
240 return;
241 }
242
243 const QDomElement root = doc.documentElement();
244 if ( root.tagName() != QLatin1String( "qgsshortcuts" ) )
245 {
246 QMessageBox::information( this, tr( "Loading Shortcuts" ), tr( "The file is not an shortcuts exchange file." ) );
247 return;
248 }
249
250 QString currentLocale;
251
252 const bool localeOverrideFlag = QgsApplication::settingsLocaleOverrideFlag->value();
253 if ( localeOverrideFlag )
254 {
256 }
257 else // use QGIS locale
258 {
259 currentLocale = QLocale().name();
260 }
261
262 const QString versionStr = root.attribute( QStringLiteral( "version" ) );
263 const QgsProjectVersion version( versionStr );
264
265 if ( root.attribute( QStringLiteral( "locale" ) ) != currentLocale )
266 {
267 if ( version < QgsProjectVersion( QStringLiteral( "1.1" ) ) )
268 {
269 QMessageBox::information( this, tr( "Loading Shortcuts" ), tr( "The file contains shortcuts created with different locale, so you can't use it." ) );
270 return;
271 }
272 else // From version 1.1, if objectName is not empty, it is used as key.
273 {
274 QMessageBox::information( this, tr( "Loading Shortcuts" ), tr( "The file contains shortcuts created with different locale, so some shortcuts may not work." ) );
275 }
276 }
277
278 QString actionName;
279 QString actionShortcut;
280 QString actionSettingKey;
281
282 QDomElement child = root.firstChildElement();
283 ActionOnExisting actionOnExisting = ActionOnExisting::Ask;
284 while ( !child.isNull() )
285 {
286 actionShortcut = child.attribute( QStringLiteral( "shortcut" ) );
287 QKeySequence actionShortcutSequence( actionShortcut );
288 QString previousText;
289
290 if ( version < QgsProjectVersion( QStringLiteral( "1.1" ) ) )
291 {
292 actionName = child.attribute( QStringLiteral( "name" ) );
293 QShortcut *previousShortcut = mManager->shortcutForSequence( actionShortcutSequence );
294 QAction *previousAction = mManager->actionForSequence( actionShortcutSequence );
295 if ( previousShortcut && previousShortcut->objectName() != actionName )
296 {
297 previousText = previousShortcut->whatsThis();
298 }
299 else if ( previousAction && previousAction->objectName() != actionName )
300 {
301 previousText = previousAction->text().remove( '&' );
302 }
303 if ( !previousText.isEmpty() )
304 {
305 QString text;
306 if ( QAction *action = mManager->actionByName( actionName ) )
307 {
308 text = action->text().remove( '&' );
309 }
310 else if ( QShortcut *shortcut = mManager->shortcutByName( actionName ) )
311 {
312 text = shortcut->whatsThis();
313 }
314
315 if ( actionOnExisting == ActionOnExisting::Ask )
316 {
317 const int res = QMessageBox::question( this, tr( "Load Shortcut" ), tr( "Shortcut %1 is already assigned to action %2. Reassign to %3?" ).arg( actionShortcut, previousText, text ), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::NoToAll );
318 if ( res == QMessageBox::No || res == QMessageBox::NoToAll )
319 {
320 if ( res == QMessageBox::NoToAll )
321 {
322 actionOnExisting = ActionOnExisting::SkipAll;
323 }
324 child = child.nextSiblingElement();
325 continue;
326 }
327 if ( res == QMessageBox::YesToAll )
328 {
329 actionOnExisting = ActionOnExisting::ReassignAll;
330 }
331 }
332 else if ( actionOnExisting == ActionOnExisting::SkipAll )
333 {
334 child = child.nextSiblingElement();
335 continue;
336 }
337 mManager->setObjectKeySequence( previousAction ? qobject_cast<QObject *>( previousAction ) : qobject_cast<QObject *>( previousShortcut ), QString() );
338 }
339 mManager->setKeySequence( actionName, actionShortcut );
340 }
341 else
342 {
343 actionSettingKey = child.attribute( QStringLiteral( "setting" ) );
344 QObject *obj = mManager->objectForSettingKey( actionSettingKey );
345 if ( obj )
346 {
347 QObject *previousObj = mManager->objectForSequence( actionShortcutSequence );
348 if ( previousObj && previousObj != obj )
349 {
350 if ( QAction *previousAction = qobject_cast<QAction *>( previousObj ) )
351 {
352 previousText = previousAction->text().remove( '&' );
353 }
354 else if ( QShortcut *previousShortcut = qobject_cast<QShortcut *>( previousObj ) )
355 {
356 previousText = previousShortcut->whatsThis();
357 }
358 }
359
360 if ( !previousText.isEmpty() )
361 {
362 QString text;
363 if ( QAction *action = qobject_cast<QAction *>( obj ) )
364 {
365 text = action->text().remove( '&' );
366 }
367 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
368 {
369 text = shortcut->whatsThis();
370 }
371
372 if ( actionOnExisting == ActionOnExisting::Ask )
373 {
374 const int res = QMessageBox::question( this, tr( "Load Shortcut" ), tr( "Shortcut %1 is already assigned to action %2. Reassign to %3?" ).arg( actionShortcut, previousText, text ), QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::No | QMessageBox::NoToAll );
375 if ( res == QMessageBox::No || res == QMessageBox::NoToAll )
376 {
377 if ( res == QMessageBox::NoToAll )
378 {
379 actionOnExisting = ActionOnExisting::SkipAll;
380 }
381 child = child.nextSiblingElement();
382 continue;
383 }
384 if ( res == QMessageBox::YesToAll )
385 {
386 actionOnExisting = ActionOnExisting::ReassignAll;
387 }
388 }
389 else if ( actionOnExisting == ActionOnExisting::SkipAll )
390 {
391 child = child.nextSiblingElement();
392 continue;
393 }
394 mManager->setObjectKeySequence( previousObj, QString() );
395 }
396 mManager->setObjectKeySequence( obj, actionShortcut );
397 }
398 }
399
400 child = child.nextSiblingElement();
401 }
402
403 treeActions->clear();
404 populateActions();
405}
406
407void QgsConfigureShortcutsDialog::changeShortcut()
408{
409 setFocus(); // make sure we have focus
410 setGettingShortcut( true );
411}
412
413void QgsConfigureShortcutsDialog::resetShortcut()
414{
415 QObject *object = currentObject();
416 const QString sequence = mManager->objectDefaultKeySequence( object );
417 setCurrentActionShortcut( sequence );
418}
419
420void QgsConfigureShortcutsDialog::setNoShortcut()
421{
422 setCurrentActionShortcut( QKeySequence() );
423}
424
425QAction *QgsConfigureShortcutsDialog::currentAction()
426{
427 return qobject_cast<QAction *>( currentObject() );
428}
429
430QShortcut *QgsConfigureShortcutsDialog::currentShortcut()
431{
432 return qobject_cast<QShortcut *>( currentObject() );
433}
434
435void QgsConfigureShortcutsDialog::actionChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
436{
437 Q_UNUSED( current )
438 Q_UNUSED( previous )
439 // cancel previous shortcut setting (if any)
440 setGettingShortcut( false );
441
442 QString shortcut;
443 QKeySequence sequence;
444 if ( QAction *action = currentAction() )
445 {
446 // show which one is the default action
447 shortcut = mManager->defaultKeySequence( action );
448 sequence = action->shortcut();
449 }
450 else if ( QShortcut *object = currentShortcut() )
451 {
452 // show which one is the default action
453 shortcut = mManager->defaultKeySequence( object );
454 sequence = object->key();
455 }
456 else
457 {
458 return;
459 }
460
461 if ( shortcut.isEmpty() )
462 shortcut = tr( "None" );
463 btnResetShortcut->setText( tr( "Set default (%1)" ).arg( shortcut ) );
464
465 // if there's no shortcut, disable set none
466 btnSetNoShortcut->setEnabled( !sequence.isEmpty() );
467 // if the shortcut is default, disable set default
468 btnResetShortcut->setEnabled( sequence != QKeySequence( shortcut ) );
469}
470
472{
473 if ( !mGettingShortcut )
474 {
475 QDialog::keyPressEvent( event );
476 return;
477 }
478
479 const int key = event->key();
480 switch ( key )
481 {
482 // modifiers
483 case Qt::Key_Meta:
484 mModifiers |= Qt::META;
485 updateShortcutText();
486 break;
487 case Qt::Key_Alt:
488 mModifiers |= Qt::ALT;
489 updateShortcutText();
490 break;
491 case Qt::Key_Control:
492 mModifiers |= Qt::CTRL;
493 updateShortcutText();
494 break;
495 case Qt::Key_Shift:
496 mModifiers |= Qt::SHIFT;
497 updateShortcutText();
498 break;
499
500 // escape aborts the acquisition of shortcut
501 case Qt::Key_Escape:
502 setGettingShortcut( false );
503 break;
504
505 default:
506 mKey = key;
507 updateShortcutText();
508 }
509}
510
512{
513 if ( !mGettingShortcut )
514 {
515 QDialog::keyReleaseEvent( event );
516 return;
517 }
518
519 const int key = event->key();
520 switch ( key )
521 {
522 // modifiers
523 case Qt::Key_Meta:
524 mModifiers &= ~Qt::META;
525 updateShortcutText();
526 break;
527 case Qt::Key_Alt:
528 mModifiers &= ~Qt::ALT;
529 updateShortcutText();
530 break;
531 case Qt::Key_Control:
532 mModifiers &= ~Qt::CTRL;
533 updateShortcutText();
534 break;
535 case Qt::Key_Shift:
536 mModifiers &= ~Qt::SHIFT;
537 updateShortcutText();
538 break;
539
540 case Qt::Key_Escape:
541 break;
542
543 default:
544 {
545 // an ordinary key - set it with modifiers as a shortcut
546 setCurrentActionShortcut( QKeySequence( mModifiers + mKey ) );
547 setGettingShortcut( false );
548 }
549 }
550}
551
552QObject *QgsConfigureShortcutsDialog::currentObject()
553{
554 if ( !treeActions->currentItem() )
555 return nullptr;
556
557 QObject *object = treeActions->currentItem()->data( 0, Qt::UserRole ).value<QObject *>();
558 return object;
559}
560
561void QgsConfigureShortcutsDialog::updateShortcutText()
562{
563 // update text of the button so that user can see what has typed already
564 const QKeySequence s( mModifiers + mKey );
565 btnChangeShortcut->setText( tr( "Input: " ) + s.toString( QKeySequence::NativeText ) );
566}
567
568void QgsConfigureShortcutsDialog::setGettingShortcut( bool getting )
569{
570 mModifiers = 0;
571 mKey = 0;
572 mGettingShortcut = getting;
573 if ( !getting )
574 {
575 btnChangeShortcut->setChecked( false );
576 btnChangeShortcut->setText( tr( "Change" ) );
577 }
578 else
579 {
580 updateShortcutText();
581 }
582}
583
584void QgsConfigureShortcutsDialog::setCurrentActionShortcut( const QKeySequence &s )
585{
586 QObject *object = currentObject();
587 if ( !object )
588 return;
589
590 // first check whether this action is not taken already
591 QObject *otherObject = mManager->objectForSequence( s );
592 if ( otherObject == object )
593 return;
594
595 if ( otherObject )
596 {
597 QString otherText;
598 if ( QAction *otherAction = qobject_cast<QAction *>( otherObject ) )
599 {
600 otherText = otherAction->text();
601 otherText.remove( '&' ); // remove the accelerator
602 }
603 else if ( QShortcut *otherShortcut = qobject_cast<QShortcut *>( otherObject ) )
604 {
605 otherText = otherShortcut->whatsThis();
606 }
607
608 const int res = QMessageBox::question( this, tr( "Change Shortcut" ), tr( "This shortcut is already assigned to action %1. Reassign?" ).arg( otherText ), QMessageBox::Yes | QMessageBox::No );
609
610 if ( res != QMessageBox::Yes )
611 return;
612
613 // reset action of the conflicting other action!
614 mManager->setObjectKeySequence( otherObject, QString() );
615 QList<QTreeWidgetItem *> items = treeActions->findItems( otherText, Qt::MatchExactly );
616 if ( !items.isEmpty() ) // there should be exactly one
617 items[0]->setText( 1, QString() );
618 }
619
620 // update manager
621 mManager->setObjectKeySequence( object, s.toString( QKeySequence::NativeText ) );
622
623 // update gui
624 treeActions->currentItem()->setText( 1, s.toString( QKeySequence::NativeText ) );
625
626 actionChanged( treeActions->currentItem(), nullptr );
627}
628
629void QgsConfigureShortcutsDialog::mLeFilter_textChanged( const QString &text )
630{
631 for ( int i = 0; i < treeActions->topLevelItemCount(); i++ )
632 {
633 QTreeWidgetItem *item = treeActions->topLevelItem( i );
634 if ( !item->text( 0 ).contains( text, Qt::CaseInsensitive ) && !item->text( 1 ).contains( text, Qt::CaseInsensitive ) )
635 {
636 item->setHidden( true );
637 }
638 else
639 {
640 item->setHidden( false );
641 }
642 }
643}
644
645void QgsConfigureShortcutsDialog::showHelp()
646{
647 QgsHelp::openHelp( QStringLiteral( "introduction/qgis_configuration.html#shortcuts" ) );
648}
649
650void QgsConfigureShortcutsDialog::saveShortcutsPdf()
651{
652 QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Shortcuts" ), QDir::homePath(), tr( "PDF file" ) + " (*.pdf);;" + tr( "All files" ) + " (*)" );
653 // return dialog focus on Mac
654 activateWindow();
655 raise();
656
657 if ( fileName.isEmpty() )
658 return;
659
660 if ( !fileName.endsWith( QLatin1String( ".pdf" ), Qt::CaseInsensitive ) )
661 {
662 fileName += QLatin1String( ".pdf" );
663 }
664
665 QTextDocument *document = new QTextDocument;
666 QTextCursor cursor( document );
667
668 QTextTableFormat tableFormat;
669 tableFormat.setBorder( 0 );
670 tableFormat.setCellSpacing( 0 );
671 tableFormat.setCellPadding( 4 );
672 tableFormat.setHeaderRowCount( 1 );
673
674 QVector<QTextLength> constraints;
675 constraints << QTextLength( QTextLength::PercentageLength, 5 );
676 constraints << QTextLength( QTextLength::PercentageLength, 80 );
677 constraints << QTextLength( QTextLength::PercentageLength, 15 );
678 tableFormat.setColumnWidthConstraints( constraints );
679
680 QTextTableCellFormat headerFormat;
681 headerFormat.setFontWeight( QFont::Bold );
682 headerFormat.setBottomPadding( 4 );
683
684 QTextCharFormat rowFormat;
685 rowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );
686
687 QTextCharFormat altRowFormat;
688 altRowFormat.setBackground( QBrush( QColor( 238, 238, 236 ) ) );
689 altRowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );
690
691 int row = 0;
692 QTextTable *table = cursor.insertTable( 1, 3, tableFormat );
693 table->mergeCells( 0, 0, 1, 2 );
694 QTextCursor c = table->cellAt( row, 0 ).firstCursorPosition();
695 c.setCharFormat( headerFormat );
696 c.insertText( tr( "Action" ) );
697 c = table->cellAt( row, 2 ).firstCursorPosition();
698 c.setCharFormat( headerFormat );
699 c.insertText( tr( "Shortcut" ) );
700
701 const QList<QObject *> objects = mManager->listAll();
702 for ( QObject *obj : objects )
703 {
704 QString actionText;
705 QString sequence;
706 QIcon icon;
707
708 if ( QAction *action = qobject_cast<QAction *>( obj ) )
709 {
710 actionText = action->text().remove( '&' );
711 sequence = action->shortcut().toString( QKeySequence::NativeText );
712 icon = action->icon();
713 }
714 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
715 {
716 actionText = shortcut->whatsThis();
717 sequence = shortcut->key().toString( QKeySequence::NativeText );
718 icon = shortcut->property( "Icon" ).value<QIcon>();
719 }
720 else
721 {
722 continue;
723 }
724
725 // skip actions without shortcut and name
726 if ( actionText.isEmpty() || sequence.isEmpty() )
727 {
728 continue;
729 }
730
731 row += 1;
732 table->appendRows( 1 );
733
734 if ( row % 2 )
735 {
736 table->cellAt( row, 0 ).setFormat( altRowFormat );
737 table->cellAt( row, 1 ).setFormat( altRowFormat );
738 table->cellAt( row, 2 ).setFormat( altRowFormat );
739 }
740 else
741 {
742 table->cellAt( row, 0 ).setFormat( rowFormat );
743 table->cellAt( row, 1 ).setFormat( rowFormat );
744 table->cellAt( row, 2 ).setFormat( rowFormat );
745 }
746
747 if ( !icon.isNull() )
748 {
749 c = table->cellAt( row, 0 ).firstCursorPosition();
750 c.insertImage( icon.pixmap( QSize( 24, 24 ) ).toImage() );
751 }
752 table->cellAt( row, 1 ).firstCursorPosition().insertText( actionText );
753 table->cellAt( row, 2 ).firstCursorPosition().insertText( sequence );
754 }
755
756 QPdfWriter pdfWriter( fileName );
757 pdfWriter.setPageLayout( QPageLayout( QPageSize( QPageSize::A4 ), QPageLayout::Portrait, QMarginsF( 20, 10, 10, 10 ) ) );
758 document->setPageSize( QSizeF( pdfWriter.pageLayout().fullRect( QPageLayout::Point ).size() ) );
759 document->print( &pdfWriter );
760}
static const QgsSettingsEntryBool * settingsLocaleOverrideFlag
Settings entry locale override flag.
static const QgsSettingsEntryString * settingsLocaleUserLocale
Settings entry locale user locale.
QgsConfigureShortcutsDialog(QWidget *parent=nullptr, QgsShortcutsManager *manager=nullptr)
Constructor for QgsConfigureShortcutsDialog.
void keyReleaseEvent(QKeyEvent *event) override
void keyPressEvent(QKeyEvent *event) override
static QgsShortcutsManager * shortcutsManager()
Returns the global shortcuts manager, used for managing a QAction and QShortcut sequences.
Definition qgsgui.cpp:125
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...
Definition qgsgui.cpp:210
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:39
Describes the version of a project.
T valueWithDefaultOverride(const T &defaultValueOverride, const QString &dynamicKeyPart=QString()) const
Returns the settings value with a defaultValueOverride and with an optional dynamicKeyPart.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
QString key(const QString &dynamicKeyPart=QString()) const
Returns settings entry key.
Stores settings for use within QGIS.
Definition qgssettings.h:65
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Shortcuts manager is a class that contains a list of QActions and QShortcuts that have been registere...
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.
QObject * objectForSettingKey(const QString &name) const
Returns the QShortcut or QAction matching the the full setting key Return nullptr if the key was not ...
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.
QShortcut * shortcutByName(const QString &name) const
Returns a shortcut by its name, or nullptr if nothing found.
QAction * actionByName(const QString &name) const
Returns an action by its name, or nullptr if nothing found.
QShortcut * shortcutForSequence(const QKeySequence &sequence) const
Returns the shortcut which is associated for a key sequence, or nullptr if no shortcut is associated.
QString objectSettingKey(QObject *object) const
Returns the full settings key matching the QShortcut or QAction Return an empty QString if the QObjec...
QAction * actionForSequence(const QKeySequence &sequence) const
Returns the action which is associated for a shortcut sequence, or nullptr if no action is associated...
QObject * objectForSequence(const QKeySequence &sequence) const
Returns the object (QAction or QShortcut) matching the specified key sequence,.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c