Skip to content
Permalink
Browse files
Merge pull request #44942 from alexbruy/shortcuts-export
Option to export all keyboard shortcuts to XML and PDF
  • Loading branch information
alexbruy committed Sep 8, 2021
2 parents bd8a8d5 + 50cb706 commit da9b9b0fa0eb656cb95ce0f0cca1c79edc4fbf15
Showing with 181 additions and 13 deletions.
  1. +173 −12 src/gui/qgsconfigureshortcutsdialog.cpp
  2. +8 −1 src/gui/qgsconfigureshortcutsdialog.h
@@ -28,14 +28,38 @@
#include <QDomDocument>
#include <QFileDialog>
#include <QTextStream>
#include <QDebug>
#include <QMenu>
#include <QAction>
#include <QPrinter>
#include <QTextDocument>
#include <QTextCursor>
#include <QTextTable>
#include <QTextTableFormat>
#include <QTextTableCellFormat>
#include <QTextCharFormat>

QgsConfigureShortcutsDialog::QgsConfigureShortcutsDialog( QWidget *parent, QgsShortcutsManager *manager )
: QDialog( parent )
, mManager( manager )
{
setupUi( this );
QgsGui::enableAutoGeometryRestore( this );

mSaveMenu = new QMenu( this );
mSaveUserShortcuts = new QAction( tr( "Save User Shortcuts…" ), this );
mSaveMenu->addAction( mSaveUserShortcuts );
connect( mSaveUserShortcuts, &QAction::triggered, this, [this] { saveShortcuts( false ); } );

mSaveAllShortcuts = new QAction( tr( "Save All Shortcuts…" ), this );
mSaveMenu->addAction( mSaveAllShortcuts );
connect( mSaveAllShortcuts, &QAction::triggered, this, [this] { saveShortcuts(); } );

mSaveAsPdf = new QAction( tr( "Save as PDF…" ), this );
mSaveMenu->addAction( mSaveAsPdf );
connect( mSaveAsPdf, &QAction::triggered, this, &QgsConfigureShortcutsDialog::saveShortcutsPdf );

btnSaveShortcuts->setMenu( mSaveMenu );

connect( mLeFilter, &QgsFilterLineEdit::textChanged, this, &QgsConfigureShortcutsDialog::mLeFilter_textChanged );

if ( !mManager )
@@ -45,7 +69,6 @@ QgsConfigureShortcutsDialog::QgsConfigureShortcutsDialog( QWidget *parent, QgsSh
connect( btnChangeShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::changeShortcut );
connect( btnResetShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::resetShortcut );
connect( btnSetNoShortcut, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::setNoShortcut );
connect( btnSaveShortcuts, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::saveShortcuts );
connect( btnLoadShortcuts, &QAbstractButton::clicked, this, &QgsConfigureShortcutsDialog::loadShortcuts );

connect( treeActions, &QTreeWidget::currentItemChanged,
@@ -107,7 +130,7 @@ void QgsConfigureShortcutsDialog::populateActions()
actionChanged( treeActions->currentItem(), nullptr );
}

void QgsConfigureShortcutsDialog::saveShortcuts()
void QgsConfigureShortcutsDialog::saveShortcuts( bool saveAll )
{
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Shortcuts" ), QDir::homePath(),
tr( "XML file" ) + " (*.xml);;" + tr( "All files" ) + " (*)" );
@@ -139,18 +162,42 @@ void QgsConfigureShortcutsDialog::saveShortcuts()
root.setAttribute( QStringLiteral( "locale" ), settings.value( QgsApplication::settingsLocaleUserLocale.key(), "en_US" ).toString() );
doc.appendChild( root );

settings.beginGroup( mManager->settingsPath() );
QStringList keys = settings.childKeys();
const QList<QObject *> objects = mManager->listAll();
for ( QObject *obj : objects )
{
QString actionText;
QString actionShortcut;
QKeySequence sequence;

QString actionText;
QString actionShortcut;
if ( QAction *action = qobject_cast< QAction * >( obj ) )
{
actionText = action->text().remove( '&' );
actionShortcut = action->shortcut().toString( QKeySequence::NativeText );
sequence = mManager->defaultKeySequence( action );
}
else if ( QShortcut *shortcut = qobject_cast< QShortcut * >( obj ) )
{
actionText = shortcut->whatsThis();
actionShortcut = shortcut->key().toString( QKeySequence::NativeText );
sequence = mManager->defaultKeySequence( shortcut );
}
else
{
continue;
}

for ( int i = 0; i < keys.count(); ++i )
{
actionText = keys[ i ];
actionShortcut = settings.value( actionText, "" ).toString();
if ( actionText.isEmpty() || actionShortcut.isEmpty() )
{
continue;
}

// skip unchanged shortcuts if only user-definied were requested
if ( !saveAll && sequence == QKeySequence( actionShortcut ) )
{
continue;
}

QDomElement el = doc.createElement( QStringLiteral( "act" ) );
QDomElement el = doc.createElement( QStringLiteral( "action" ) );
el.setAttribute( QStringLiteral( "name" ), actionText );
el.setAttribute( QStringLiteral( "shortcut" ), actionShortcut );
root.appendChild( el );
@@ -483,3 +530,117 @@ void QgsConfigureShortcutsDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "introduction/qgis_configuration.html#keyboard-shortcuts" ) );
}

void QgsConfigureShortcutsDialog::saveShortcutsPdf()
{
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save Shortcuts" ), QDir::homePath(),
tr( "PDF file" ) + " (*.pdf);;" + tr( "All files" ) + " (*)" );

if ( fileName.isEmpty() )
return;

if ( !fileName.endsWith( QLatin1String( ".pdf" ), Qt::CaseInsensitive ) )
{
fileName += QLatin1String( ".pdf" );
}

QTextDocument *document = new QTextDocument;
QTextCursor cursor( document );

QTextTableFormat tableFormat;
tableFormat.setBorder( 0 );
tableFormat.setCellSpacing( 0 );
tableFormat.setCellPadding( 4 );
tableFormat.setHeaderRowCount( 1 );

QVector<QTextLength> constraints;
constraints << QTextLength( QTextLength::PercentageLength, 5 );
constraints << QTextLength( QTextLength::PercentageLength, 80 );
constraints << QTextLength( QTextLength::PercentageLength, 15 );
tableFormat.setColumnWidthConstraints( constraints );

QTextTableCellFormat headerFormat;
headerFormat.setFontWeight( QFont::Bold );
headerFormat.setBottomPadding( 4 );

QTextCharFormat rowFormat;
rowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );

QTextCharFormat altRowFormat;
altRowFormat.setBackground( QBrush( QColor( 238, 238, 236 ) ) );
altRowFormat.setVerticalAlignment( QTextCharFormat::AlignMiddle );

int row = 0;
QTextTable *table = cursor.insertTable( 1, 3, tableFormat );
table->mergeCells( 0, 0, 1, 2 );
QTextCursor c = table->cellAt( row, 0 ).firstCursorPosition();
c.setCharFormat( headerFormat );
c.insertText( tr( "Action" ) );
c = table->cellAt( row, 2 ).firstCursorPosition();
c.setCharFormat( headerFormat );
c.insertText( tr( "Shortcut" ) );

const QList<QObject *> objects = mManager->listAll();
for ( QObject *obj : objects )
{
QString actionText;
QString sequence;
QIcon icon;

if ( QAction *action = qobject_cast< QAction * >( obj ) )
{
actionText = action->text().remove( '&' );
sequence = action->shortcut().toString( QKeySequence::NativeText );
icon = action->icon();
}
else if ( QShortcut *shortcut = qobject_cast< QShortcut * >( obj ) )
{
actionText = shortcut->whatsThis();
sequence = shortcut->key().toString( QKeySequence::NativeText );
icon = shortcut->property( "Icon" ).value<QIcon>();
}
else
{
continue;
}

// skip actions without shortcut and name
if ( actionText.isEmpty() || sequence.isEmpty() )
{
continue;
}

row += 1;
table->appendRows( 1 );

if ( row % 2 )
{
table->cellAt( row, 0 ).setFormat( altRowFormat );
table->cellAt( row, 1 ).setFormat( altRowFormat );
table->cellAt( row, 2 ).setFormat( altRowFormat );
}
else
{
table->cellAt( row, 0 ).setFormat( rowFormat );
table->cellAt( row, 1 ).setFormat( rowFormat );
table->cellAt( row, 2 ).setFormat( rowFormat );
}

if ( !icon.isNull() )
{
c = table->cellAt( row, 0 ).firstCursorPosition();
c.insertImage( icon.pixmap( QSize( 24, 24 ) ).toImage() );
}
table->cellAt( row, 1 ).firstCursorPosition().insertText( actionText );
table->cellAt( row, 2 ).firstCursorPosition().insertText( sequence );
}

QPrinter printer( QPrinter::ScreenResolution );
printer.setOutputFormat( QPrinter::PdfFormat );
printer.setPaperSize( QPrinter::A4 );
printer.setPageOrientation( QPageLayout::Portrait );
printer.setPageMargins( QMarginsF( 20, 10, 10, 10 ), QPageLayout::Millimeter );
printer.setOutputFileName( fileName );
document->setPageSize( QSizeF( printer.pageRect().size() ) );
document->print( &printer );
}
@@ -55,8 +55,8 @@ class GUI_EXPORT QgsConfigureShortcutsDialog : public QDialog, private Ui::QgsCo
void changeShortcut();
void resetShortcut();
void setNoShortcut();
void saveShortcuts();
void loadShortcuts();
void saveShortcutsPdf();
void mLeFilter_textChanged( const QString &text );

void actionChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous );
@@ -78,11 +78,18 @@ class GUI_EXPORT QgsConfigureShortcutsDialog : public QDialog, private Ui::QgsCo
//! Returns the currently selected QShortcut, or NULLPTR if no shortcut selected
QShortcut *currentShortcut();

//! Saves custom or all shortcuts to XML file
void saveShortcuts( bool saveAll = true );

void setGettingShortcut( bool getting );
void setCurrentActionShortcut( const QKeySequence &s );
void updateShortcutText();

QgsShortcutsManager *mManager = nullptr;
QMenu *mSaveMenu = nullptr;
QAction *mSaveUserShortcuts = nullptr;
QAction *mSaveAllShortcuts = nullptr;
QAction *mSaveAsPdf = nullptr;

bool mGettingShortcut = false;
int mModifiers = 0, mKey = 0;

0 comments on commit da9b9b0

Please sign in to comment.