QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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::
322 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 );
323 if ( res == QMessageBox::No || res == QMessageBox::NoToAll )
324 {
325 if ( res == QMessageBox::NoToAll )
326 {
327 actionOnExisting = ActionOnExisting::SkipAll;
328 }
329 child = child.nextSiblingElement();
330 continue;
331 }
332 if ( res == QMessageBox::YesToAll )
333 {
334 actionOnExisting = ActionOnExisting::ReassignAll;
335 }
336 }
337 else if ( actionOnExisting == ActionOnExisting::SkipAll )
338 {
339 child = child.nextSiblingElement();
340 continue;
341 }
342 mManager->setObjectKeySequence( previousAction ? qobject_cast<QObject *>( previousAction ) : qobject_cast<QObject *>( previousShortcut ), QString() );
343 }
344 mManager->setKeySequence( actionName, actionShortcut );
345 }
346 else
347 {
348 actionSettingKey = child.attribute( u"setting"_s );
349 QObject *obj = mManager->objectForSettingKey( actionSettingKey );
350 if ( obj )
351 {
352 QObject *previousObj = mManager->objectForSequence( actionShortcutSequence );
353 if ( previousObj && previousObj != obj )
354 {
355 if ( QAction *previousAction = qobject_cast<QAction *>( previousObj ) )
356 {
357 previousText = previousAction->text().remove( '&' );
358 }
359 else if ( QShortcut *previousShortcut = qobject_cast<QShortcut *>( previousObj ) )
360 {
361 previousText = previousShortcut->whatsThis();
362 }
363 }
364
365 if ( !previousText.isEmpty() )
366 {
367 QString text;
368 if ( QAction *action = qobject_cast<QAction *>( obj ) )
369 {
370 text = action->text().remove( '&' );
371 }
372 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
373 {
374 text = shortcut->whatsThis();
375 }
376
377 if ( actionOnExisting == ActionOnExisting::Ask )
378 {
379 const int res = QMessageBox::
380 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 );
381 if ( res == QMessageBox::No || res == QMessageBox::NoToAll )
382 {
383 if ( res == QMessageBox::NoToAll )
384 {
385 actionOnExisting = ActionOnExisting::SkipAll;
386 }
387 child = child.nextSiblingElement();
388 continue;
389 }
390 if ( res == QMessageBox::YesToAll )
391 {
392 actionOnExisting = ActionOnExisting::ReassignAll;
393 }
394 }
395 else if ( actionOnExisting == ActionOnExisting::SkipAll )
396 {
397 child = child.nextSiblingElement();
398 continue;
399 }
400 mManager->setObjectKeySequence( previousObj, QString() );
401 }
402 mManager->setObjectKeySequence( obj, actionShortcut );
403 }
404 }
405
406 child = child.nextSiblingElement();
407 }
408
409 treeActions->clear();
410 populateActions();
411}
412
413void QgsConfigureShortcutsDialog::changeShortcut()
414{
415 setFocus(); // make sure we have focus
416 setGettingShortcut( true );
417}
418
419void QgsConfigureShortcutsDialog::resetShortcut()
420{
421 QObject *object = currentObject();
422 const QString sequence = mManager->objectDefaultKeySequence( object );
423 setCurrentActionShortcut( sequence );
424}
425
426void QgsConfigureShortcutsDialog::setNoShortcut()
427{
428 setCurrentActionShortcut( QKeySequence() );
429}
430
431QAction *QgsConfigureShortcutsDialog::currentAction()
432{
433 return qobject_cast<QAction *>( currentObject() );
434}
435
436QShortcut *QgsConfigureShortcutsDialog::currentShortcut()
437{
438 return qobject_cast<QShortcut *>( currentObject() );
439}
440
441void QgsConfigureShortcutsDialog::actionChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
442{
443 Q_UNUSED( current )
444 Q_UNUSED( previous )
445 // cancel previous shortcut setting (if any)
446 setGettingShortcut( false );
447
448 QString shortcut;
449 QKeySequence sequence;
450 if ( QAction *action = currentAction() )
451 {
452 // show which one is the default action
453 shortcut = mManager->defaultKeySequence( action );
454 sequence = action->shortcut();
455 }
456 else if ( QShortcut *object = currentShortcut() )
457 {
458 // show which one is the default action
459 shortcut = mManager->defaultKeySequence( object );
460 sequence = object->key();
461 }
462 else
463 {
464 return;
465 }
466
467 if ( shortcut.isEmpty() )
468 shortcut = tr( "None" );
469 btnResetShortcut->setText( tr( "Set default (%1)" ).arg( shortcut ) );
470
471 // if there's no shortcut, disable set none
472 btnSetNoShortcut->setEnabled( !sequence.isEmpty() );
473 // if the shortcut is default, disable set default
474 btnResetShortcut->setEnabled( sequence != QKeySequence( shortcut ) );
475}
476
478{
479 if ( !mGettingShortcut )
480 {
481 QDialog::keyPressEvent( event );
482 return;
483 }
484
485 const int key = event->key();
486 switch ( key )
487 {
488 // modifiers
489 case Qt::Key_Meta:
490 mModifiers |= Qt::META;
491 updateShortcutText();
492 break;
493 case Qt::Key_Alt:
494 mModifiers |= Qt::ALT;
495 updateShortcutText();
496 break;
497 case Qt::Key_Control:
498 mModifiers |= Qt::CTRL;
499 updateShortcutText();
500 break;
501 case Qt::Key_Shift:
502 mModifiers |= Qt::SHIFT;
503 updateShortcutText();
504 break;
505
506 // escape aborts the acquisition of shortcut
507 case Qt::Key_Escape:
508 setGettingShortcut( false );
509 break;
510
511 default:
512 mKey = key;
513 updateShortcutText();
514 }
515}
516
518{
519 if ( !mGettingShortcut )
520 {
521 QDialog::keyReleaseEvent( event );
522 return;
523 }
524
525 const int key = event->key();
526 switch ( key )
527 {
528 // modifiers
529 case Qt::Key_Meta:
530 mModifiers &= ~Qt::META;
531 updateShortcutText();
532 break;
533 case Qt::Key_Alt:
534 mModifiers &= ~Qt::ALT;
535 updateShortcutText();
536 break;
537 case Qt::Key_Control:
538 mModifiers &= ~Qt::CTRL;
539 updateShortcutText();
540 break;
541 case Qt::Key_Shift:
542 mModifiers &= ~Qt::SHIFT;
543 updateShortcutText();
544 break;
545
546 case Qt::Key_Escape:
547 break;
548
549 default:
550 {
551 // an ordinary key - set it with modifiers as a shortcut
552 setCurrentActionShortcut( QKeySequence( mModifiers + mKey ) );
553 setGettingShortcut( false );
554 }
555 }
556}
557
558QObject *QgsConfigureShortcutsDialog::currentObject()
559{
560 if ( !treeActions->currentItem() )
561 return nullptr;
562
563 QObject *object = treeActions->currentItem()->data( 0, Qt::UserRole ).value<QObject *>();
564 return object;
565}
566
567void QgsConfigureShortcutsDialog::updateShortcutText()
568{
569 // update text of the button so that user can see what has typed already
570 const QKeySequence s( mModifiers + mKey );
571 btnChangeShortcut->setText( tr( "Input: " ) + s.toString( QKeySequence::NativeText ) );
572}
573
574void QgsConfigureShortcutsDialog::setGettingShortcut( bool getting )
575{
576 mModifiers = 0;
577 mKey = 0;
578 mGettingShortcut = getting;
579 if ( !getting )
580 {
581 btnChangeShortcut->setChecked( false );
582 btnChangeShortcut->setText( tr( "Change" ) );
583 }
584 else
585 {
586 updateShortcutText();
587 }
588}
589
590void QgsConfigureShortcutsDialog::setCurrentActionShortcut( const QKeySequence &s )
591{
592 QObject *object = currentObject();
593 if ( !object )
594 return;
595
596 // first check whether this action is not taken already
597 QObject *otherObject = mManager->objectForSequence( s );
598 if ( otherObject == object )
599 return;
600
601 if ( otherObject )
602 {
603 QString otherText;
604 if ( QAction *otherAction = qobject_cast<QAction *>( otherObject ) )
605 {
606 otherText = otherAction->text();
607 otherText.remove( '&' ); // remove the accelerator
608 }
609 else if ( QShortcut *otherShortcut = qobject_cast<QShortcut *>( otherObject ) )
610 {
611 otherText = otherShortcut->whatsThis();
612 }
613
614 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 );
615
616 if ( res != QMessageBox::Yes )
617 return;
618
619 // reset action of the conflicting other action!
620 mManager->setObjectKeySequence( otherObject, QString() );
621 QList<QTreeWidgetItem *> items = treeActions->findItems( otherText, Qt::MatchExactly );
622 if ( !items.isEmpty() ) // there should be exactly one
623 items[0]->setText( 1, QString() );
624 }
625
626 // update manager
627 mManager->setObjectKeySequence( object, s.toString( QKeySequence::NativeText ) );
628
629 // update gui
630 treeActions->currentItem()->setText( 1, s.toString( QKeySequence::NativeText ) );
631
632 actionChanged( treeActions->currentItem(), nullptr );
633}
634
635void QgsConfigureShortcutsDialog::mLeFilter_textChanged( const QString &text )
636{
637 for ( int i = 0; i < treeActions->topLevelItemCount(); i++ )
638 {
639 QTreeWidgetItem *item = treeActions->topLevelItem( i );
640 if ( !item->text( 0 ).contains( text, Qt::CaseInsensitive ) && !item->text( 1 ).contains( text, Qt::CaseInsensitive ) )
641 {
642 item->setHidden( true );
643 }
644 else
645 {
646 item->setHidden( false );
647 }
648 }
649}
650
651void QgsConfigureShortcutsDialog::showHelp()
652{
653 QgsHelp::openHelp( u"introduction/qgis_configuration.html#shortcuts"_s );
654}
655
656void QgsConfigureShortcutsDialog::saveShortcutsPdf()
657{
658 QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Shortcuts" ), QDir::homePath(), tr( "PDF file" ) + " (*.pdf);;" + tr( "All files" ) + " (*)" );
659 // return dialog focus on Mac
660 activateWindow();
661 raise();
662
663 if ( fileName.isEmpty() )
664 return;
665
666 if ( !fileName.endsWith( ".pdf"_L1, Qt::CaseInsensitive ) )
667 {
668 fileName += ".pdf"_L1;
669 }
670
671 QTextDocument *document = new QTextDocument;
672 QTextCursor cursor( document );
673
674 QTextTableFormat tableFormat;
675 tableFormat.setBorder( 0 );
676 tableFormat.setCellSpacing( 0 );
677 tableFormat.setCellPadding( 4 );
678 tableFormat.setHeaderRowCount( 1 );
679
680 QVector<QTextLength> constraints;
681 constraints << QTextLength( QTextLength::PercentageLength, 5 );
682 constraints << QTextLength( QTextLength::PercentageLength, 80 );
683 constraints << QTextLength( QTextLength::PercentageLength, 15 );
684 tableFormat.setColumnWidthConstraints( constraints );
685
686 QTextTableCellFormat headerFormat;
687 headerFormat.setFontWeight( QFont::Bold );
688 headerFormat.setBottomPadding( 4 );
689
690 QTextCharFormat rowFormat;
691 rowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );
692
693 QTextCharFormat altRowFormat;
694 altRowFormat.setBackground( QBrush( QColor( 238, 238, 236 ) ) );
695 altRowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );
696
697 int row = 0;
698 QTextTable *table = cursor.insertTable( 1, 3, tableFormat );
699 table->mergeCells( 0, 0, 1, 2 );
700 QTextCursor c = table->cellAt( row, 0 ).firstCursorPosition();
701 c.setCharFormat( headerFormat );
702 c.insertText( tr( "Action" ) );
703 c = table->cellAt( row, 2 ).firstCursorPosition();
704 c.setCharFormat( headerFormat );
705 c.insertText( tr( "Shortcut" ) );
706
707 const QList<QObject *> objects = mManager->listAll();
708 for ( QObject *obj : objects )
709 {
710 QString actionText;
711 QString sequence;
712 QIcon icon;
713
714 if ( QAction *action = qobject_cast<QAction *>( obj ) )
715 {
716 actionText = action->text().remove( '&' );
717 sequence = action->shortcut().toString( QKeySequence::NativeText );
718 icon = action->icon();
719 }
720 else if ( QShortcut *shortcut = qobject_cast<QShortcut *>( obj ) )
721 {
722 actionText = shortcut->whatsThis();
723 sequence = shortcut->key().toString( QKeySequence::NativeText );
724 icon = shortcut->property( "Icon" ).value<QIcon>();
725 }
726 else
727 {
728 continue;
729 }
730
731 // skip actions without shortcut and name
732 if ( actionText.isEmpty() || sequence.isEmpty() )
733 {
734 continue;
735 }
736
737 row += 1;
738 table->appendRows( 1 );
739
740 if ( row % 2 )
741 {
742 table->cellAt( row, 0 ).setFormat( altRowFormat );
743 table->cellAt( row, 1 ).setFormat( altRowFormat );
744 table->cellAt( row, 2 ).setFormat( altRowFormat );
745 }
746 else
747 {
748 table->cellAt( row, 0 ).setFormat( rowFormat );
749 table->cellAt( row, 1 ).setFormat( rowFormat );
750 table->cellAt( row, 2 ).setFormat( rowFormat );
751 }
752
753 if ( !icon.isNull() )
754 {
755 c = table->cellAt( row, 0 ).firstCursorPosition();
756 c.insertImage( icon.pixmap( QSize( 24, 24 ) ).toImage() );
757 }
758 table->cellAt( row, 1 ).firstCursorPosition().insertText( actionText );
759 table->cellAt( row, 2 ).firstCursorPosition().insertText( sequence );
760 }
761
762 QPdfWriter pdfWriter( fileName );
763 pdfWriter.setPageLayout( QPageLayout( QPageSize( QPageSize::A4 ), QPageLayout::Portrait, QMarginsF( 20, 10, 10, 10 ) ) );
764 document->setPageSize( QSizeF( pdfWriter.pageLayout().fullRect( QPageLayout::Point ).size() ) );
765 document->print( &pdfWriter );
766}
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