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