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