Skip to content

Commit

Permalink
feature: Allow to configure main window shortcuts (#26)
Browse files Browse the repository at this point in the history
Add named shortcuts for main window actions.
Store shortcuts as human readable array.

Change "go to line" shortcut to Ctrl+L (#334)
  • Loading branch information
variar committed Jun 9, 2021
1 parent 9d5f252 commit 406e4ba
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 57 deletions.
4 changes: 3 additions & 1 deletion src/ui/include/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class MainWindow : public QMainWindow {
// Drag and drop support
void dragEnterEvent( QDragEnterEvent* event ) override;
void dropEvent( QDropEvent* event ) override;
void keyPressEvent( QKeyEvent* keyEvent ) override;

bool event( QEvent* event ) override;

Expand Down Expand Up @@ -204,6 +203,7 @@ class MainWindow : public QMainWindow {
void removeFromFavorites( const QString& pathToRemove );
void removeFromRecent( const QString& pathToRemove );
void tryOpenClipboard( int tryTimes );
void updateShortcuts();

WindowSession session_;
QString loadingFileName;
Expand Down Expand Up @@ -270,6 +270,8 @@ class MainWindow : public QMainWindow {
QActionGroup* openedFilesGroup;
QActionGroup* highlightersActionGroup = nullptr;

std::map<QString, QShortcut*> shortcuts_;

QSystemTrayIcon* trayIcon_;

QIcon mainIcon_;
Expand Down
101 changes: 54 additions & 47 deletions src/ui/src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
#include "readablesize.h"
#include "recentfiles.h"
#include "sessioninfo.h"
#include "shortcuts.h"
#include "styles.h"
#include "tabbedcrawlerwidget.h"

Expand Down Expand Up @@ -275,20 +276,18 @@ void MainWindow::loadInitialFile( QString fileName, bool followFile )
void MainWindow::createActions()
{
const auto& config = Configuration::get();
const auto shortcuts = config.shortcuts();

newWindowAction = new QAction( tr( "&New window" ), this );
newWindowAction->setShortcut( QKeySequence::New );
newWindowAction->setStatusTip( tr( "Create new klogg window" ) );
connect( newWindowAction, &QAction::triggered, [ = ] { emit newWindow(); } );
newWindowAction->setVisible( config.allowMultipleWindows() );

openAction = new QAction( tr( "&Open..." ), this );
openAction->setShortcuts( QKeySequence::keyBindings( QKeySequence::Open ) );
openAction->setStatusTip( tr( "Open a file" ) );
connect( openAction, &QAction::triggered, [ this ]( auto ) { this->open(); } );

closeAction = new QAction( tr( "&Close" ), this );
closeAction->setShortcuts( QKeySequence::keyBindings( QKeySequence::Close ) );
closeAction->setStatusTip( tr( "Close document" ) );
connect( closeAction, &QAction::triggered, [ this ]( auto ) { this->closeTab(); } );

Expand All @@ -305,28 +304,23 @@ void MainWindow::createActions()
}

exitAction = new QAction( tr( "E&xit" ), this );
exitAction->setShortcut( tr( "Ctrl+Q" ) );
exitAction->setStatusTip( tr( "Exit the application" ) );
connect( exitAction, &QAction::triggered, this, &MainWindow::exitRequested );

copyAction = new QAction( tr( "&Copy" ), this );
copyAction->setShortcuts( QKeySequence::keyBindings( QKeySequence::Copy ) );
copyAction->setStatusTip( tr( "Copy the selection" ) );
connect( copyAction, &QAction::triggered, [ this ]( auto ) { this->copy(); } );

selectAllAction = new QAction( tr( "Select &All" ), this );
selectAllAction->setShortcut( tr( "Ctrl+A" ) );
selectAllAction->setStatusTip( tr( "Select all the text" ) );
connect( selectAllAction, &QAction::triggered, [ this ]( auto ) { this->selectAll(); } );

findAction = new QAction( tr( "&Find..." ), this );
findAction->setShortcut( QKeySequence::Find );
findAction->setStatusTip( tr( "Find the text" ) );
connect( findAction, &QAction::triggered, [ this ]( auto ) { this->find(); } );

clearLogAction = new QAction( tr( "Clear file..." ), this );
clearLogAction->setStatusTip( tr( "Clear current file" ) );
clearLogAction->setShortcuts( QKeySequence::Cut );
connect( clearLogAction, &QAction::triggered, [ this ]( auto ) { this->clearLog(); } );

openContainingFolderAction = new QAction( tr( "Open containing folder" ), this );
Expand All @@ -345,7 +339,6 @@ void MainWindow::createActions()

openClipboardAction = new QAction( tr( "Open from clipboard" ), this );
openClipboardAction->setStatusTip( tr( "Open clipboard as log file" ) );
openClipboardAction->setShortcuts( QKeySequence::keyBindings( QKeySequence::Paste ) );
connect( openClipboardAction, &QAction::triggered,
[ this ]( auto ) { this->openClipboard(); } );

Expand Down Expand Up @@ -373,16 +366,11 @@ void MainWindow::createActions()
&MainWindow::toggleFilteredLineNumbersVisibility );

followAction = new QAction( tr( "&Follow File" ), this );

followAction->setShortcuts( QList<QKeySequence>()
<< QKeySequence( Qt::Key_F ) << QKeySequence( Qt::Key_F10 ) );

followAction->setCheckable( true );
followAction->setEnabled( config.anyFileWatchEnabled() );
connect( followAction, &QAction::toggled, this, &MainWindow::followSet );

reloadAction = new QAction( tr( "&Reload" ), this );
reloadAction->setShortcuts( QKeySequence::keyBindings( QKeySequence::Refresh ) );
signalMux_.connect( reloadAction, SIGNAL( triggered() ), SLOT( reload() ) );

stopAction = new QAction( tr( "&Stop" ), this );
Expand Down Expand Up @@ -464,13 +452,61 @@ void MainWindow::createActions()
selectOpenFileAction = new QAction( tr( "Switch to opened file..." ), this );
connect( selectOpenFileAction, &QAction::triggered,
[ this ]( auto ) { this->selectOpenedFile(); } );
selectOpenFileAction->setShortcuts( QList<QKeySequence>()
<< QKeySequence( Qt::SHIFT | Qt::CTRL | Qt::Key_O ) );

predefinedFiltersDialogAction = new QAction( tr( "Predefined filters..." ), this );
predefinedFiltersDialogAction->setStatusTip( tr( "Show dialog to configure filters" ) );
connect( predefinedFiltersDialogAction, &QAction::triggered,
[ this ]( auto ) { this->editPredefinedFilters(); } );

updateShortcuts();
}

void MainWindow::updateShortcuts()
{
const auto& config = Configuration::get();
const auto shortcuts = config.shortcuts();

for ( auto& shortcut : shortcuts_ ) {
shortcut.second->deleteLater();
}

shortcuts_.clear();
ShortcutAction::registerShortcut( shortcuts, shortcuts_, this, Qt::WindowShortcut,
ShortcutAction::MainWindowOpenQfForward,
[ this ] { displayQuickFindBar( QuickFindMux::Forward ); } );
ShortcutAction::registerShortcut( shortcuts, shortcuts_, this, Qt::WindowShortcut,
ShortcutAction::MainWindowOpenQfBackward,
[ this ] { displayQuickFindBar( QuickFindMux::Backward ); } );
ShortcutAction::registerShortcut( shortcuts, shortcuts_, this, Qt::WindowShortcut,
ShortcutAction::MainWindowFocusSearchInput, [ this ] {
if ( auto crawler = currentCrawlerWidget() ) {
crawler->focusSearchEdit();
}
} );

auto setShortcuts = [ &shortcuts ]( auto* action, const auto& actionName ) {
action->setShortcuts( ShortcutAction::shortcutKeys( actionName, shortcuts ) );
};

setShortcuts( newWindowAction, ShortcutAction::MainWindowNewWindow );
setShortcuts( openAction, ShortcutAction::MainWindowOpenFile );
setShortcuts( closeAction, ShortcutAction::MainWindowCloseFile );
setShortcuts( closeAllAction, ShortcutAction::MainWindowCloseAll );
setShortcuts( exitAction, ShortcutAction::MainWindowQuit );
setShortcuts( copyAction, ShortcutAction::MainWindowCopy );
setShortcuts( selectAllAction, ShortcutAction::MainWindowSelectAll );
setShortcuts( findAction, ShortcutAction::MainWindowOpenQf );
setShortcuts( clearLogAction, ShortcutAction::MainWindowClearFile );
setShortcuts( openContainingFolderAction, ShortcutAction::MainWindowOpenContainingFolder );
setShortcuts( openInEditorAction, ShortcutAction::MainWindowOpenInEditor );
setShortcuts( copyPathToClipboardAction, ShortcutAction::MainWindowCopyPathToClipboard );
setShortcuts( openClipboardAction, ShortcutAction::MainWindowOpenFromClipboard );
setShortcuts( openUrlAction, ShortcutAction::MainWindowOpenFromUrl );
setShortcuts( followAction, ShortcutAction::MainWindowFollowFile );
setShortcuts( reloadAction, ShortcutAction::MainWindowReload );
setShortcuts( stopAction, ShortcutAction::MainWindowStop );
setShortcuts( showScratchPadAction, ShortcutAction::MainWindowScratchpad );
setShortcuts( selectOpenFileAction, ShortcutAction::MainWindowSelectOpenFile );
}

void MainWindow::loadIcons()
Expand Down Expand Up @@ -922,6 +958,8 @@ void MainWindow::options()

newWindowAction->setVisible( config.allowMultipleWindows() );
followAction->setEnabled( config.anyFileWatchEnabled() );

updateShortcuts();
} );
dialog.exec();

Expand Down Expand Up @@ -1288,37 +1326,6 @@ void MainWindow::dropEvent( QDropEvent* event )
}
}

void MainWindow::keyPressEvent( QKeyEvent* keyEvent )
{
LOG_DEBUG << "keyPressEvent received";

switch ( keyEvent->key() ) {
case Qt::Key_Apostrophe:
displayQuickFindBar( QuickFindMux::Forward );
break;
case Qt::Key_QuoteDbl:
displayQuickFindBar( QuickFindMux::Backward );
break;
default:
keyEvent->ignore();
}

if ( ( keyEvent->modifiers().testFlag( Qt::ControlModifier )
&& keyEvent->key() == Qt::Key_S ) // Ctrl+S
|| ( keyEvent->modifiers().testFlag( Qt::ControlModifier ) // Ctrl+Shift+F
&& keyEvent->modifiers().testFlag( Qt::ShiftModifier )
&& keyEvent->key() == Qt::Key_F ) ) {

if ( auto crawler = currentCrawlerWidget() ) {
keyEvent->accept();
crawler->focusSearchEdit();
}
}

if ( !keyEvent->isAccepted() )
QMainWindow::keyPressEvent( keyEvent );
}

bool MainWindow::event( QEvent* event )
{
if ( event->type() == QEvent::WindowActivate ) {
Expand Down
92 changes: 86 additions & 6 deletions src/utils/include/shortcuts.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
#ifndef KLOGG_SHORTCUTS_H
#define KLOGG_SHORTCUTS_H

#include <algorithm>
#include <map>
#include <qkeysequence.h>
#include <qnamespace.h>
#include <qobject.h>
#include <qwidget.h>
#include <string>
Expand All @@ -43,6 +46,7 @@ struct ShortcutAction {
static constexpr auto MainWindowCloseFile = "mainwindow.close_file";
static constexpr auto MainWindowCloseAll = "mainwindow.close_all";
static constexpr auto MainWindowQuit = "mainwindow.quit";
static constexpr auto MainWindowCopy = "mainwindow.copy_selection";
static constexpr auto MainWindowSelectAll = "mainwindow.select_all";
static constexpr auto MainWindowOpenQf = "mainwindow.open_qf";
static constexpr auto MainWindowOpenQfForward = "mainwindow.open_qf_forward";
Expand All @@ -51,7 +55,14 @@ struct ShortcutAction {
static constexpr auto MainWindowClearFile = "mainwindow.clear_file";
static constexpr auto MainWindowFollowFile = "mainwindow.follow_file";
static constexpr auto MainWindowReload = "mainwindow.reload";
static constexpr auto MainWindowStop = "mainwindow.stop";
static constexpr auto MainWindowScratchpad = "mainwindow.scratchpad";
static constexpr auto MainWindowSelectOpenFile = "mainwindow.select_open_file";
static constexpr auto MainWindowOpenContainingFolder = "mainwindow.open_containing_folder";
static constexpr auto MainWindowOpenInEditor = "mainwindow.open_in_editor";
static constexpr auto MainWindowCopyPathToClipboard = "mainwindow.copy_path_to_clipboard";
static constexpr auto MainWindowOpenFromClipboard = "mainwindow.open_from_clipboard";
static constexpr auto MainWindowOpenFromUrl = "mainwindow.open_from_url";

static constexpr auto LogViewMark = "logview.mark";
static constexpr auto LogViewNextMark = "logview.next_mark";
Expand Down Expand Up @@ -92,6 +103,35 @@ struct ShortcutAction {
return stringBindings;
};

shortcuts.emplace( MainWindowNewWindow, QStringList() );
shortcuts.emplace( MainWindowOpenFile, getKeyBindings( QKeySequence::Open ) );
shortcuts.emplace( MainWindowCloseFile, getKeyBindings( QKeySequence::Close ) );
shortcuts.emplace( MainWindowCloseAll, QStringList() );
shortcuts.emplace( MainWindowQuit, QStringList() << "Ctrl+Q" );
shortcuts.emplace( MainWindowCopy, getKeyBindings( QKeySequence::Copy ) );
shortcuts.emplace( MainWindowSelectAll, QStringList() << "Ctrl+A" );
shortcuts.emplace( MainWindowFocusSearchInput, QStringList() << "Ctrl+S"
<< "Ctrl+Shift+F" );
shortcuts.emplace( MainWindowOpenQf, getKeyBindings( QKeySequence::Find ) );
shortcuts.emplace( MainWindowOpenQfForward,
QStringList() << QKeySequence( Qt::Key_Apostrophe ).toString() );
shortcuts.emplace( MainWindowOpenQfBackward,
QStringList() << QKeySequence( Qt::Key_QuoteDbl ).toString() );

shortcuts.emplace( MainWindowClearFile, getKeyBindings( QKeySequence::Cut ) );
shortcuts.emplace( MainWindowOpenContainingFolder, QStringList() );
shortcuts.emplace( MainWindowOpenInEditor, QStringList() );
shortcuts.emplace( MainWindowCopyPathToClipboard, QStringList() );
shortcuts.emplace( MainWindowOpenFromClipboard, getKeyBindings( QKeySequence::Paste ) );
shortcuts.emplace( MainWindowOpenFromUrl, QStringList() );
shortcuts.emplace( MainWindowFollowFile,
QStringList() << QKeySequence( Qt::Key_F ).toString()
<< QKeySequence( Qt::Key_F10 ).toString() );
shortcuts.emplace( MainWindowReload, getKeyBindings( QKeySequence::Refresh ) );
shortcuts.emplace( MainWindowStop, getKeyBindings( QKeySequence::Cancel ) );
shortcuts.emplace( MainWindowScratchpad, QStringList() );
shortcuts.emplace( MainWindowSelectOpenFile, QStringList() << "Ctrl+Shift+O" );

shortcuts.emplace( CrawlerChangeVisibility,
QStringList() << QKeySequence( Qt::Key_V ).toString() );
shortcuts.emplace( CrawlerIncreseTopViewSize,
Expand Down Expand Up @@ -132,7 +172,7 @@ struct ShortcutAction {
shortcuts.emplace( LogViewJumpToButtom, QStringList() << "Ctrl+End"
<< "Shift+G" );
shortcuts.emplace( LogViewJumpToTop, QStringList() << "Ctrl+Home" );
shortcuts.emplace( LogViewJumpToLine, QStringList() << "Alt+G" );
shortcuts.emplace( LogViewJumpToLine, QStringList() << "Ctrl+L" );
shortcuts.emplace( LogViewQfForward, getKeyBindings( QKeySequence::FindNext )
<< QKeySequence( Qt::Key_N ).toString()
<< "Ctrl+G" );
Expand Down Expand Up @@ -171,6 +211,29 @@ struct ShortcutAction {
static const std::map<std::string, QString> actionNames = []() {
std::map<std::string, QString> shortcuts;

shortcuts.emplace( MainWindowNewWindow, "Open new window" );
shortcuts.emplace( MainWindowOpenFile, "Open file" );
shortcuts.emplace( MainWindowCloseFile, "Close file" );
shortcuts.emplace( MainWindowCloseAll, "Close all files" );
shortcuts.emplace( MainWindowSelectAll, "Select all" );
shortcuts.emplace( MainWindowCopy, "Copy selection to clipboard" );
shortcuts.emplace( MainWindowQuit, "Exit application" );
shortcuts.emplace( MainWindowOpenQf, "Open quick find" );
shortcuts.emplace( MainWindowOpenQfForward, "Quick find forward" );
shortcuts.emplace( MainWindowOpenQfBackward, "Quick find backward" );
shortcuts.emplace( MainWindowFocusSearchInput, "Set focus to search input" );
shortcuts.emplace( MainWindowClearFile, "Clear file" );
shortcuts.emplace( MainWindowOpenContainingFolder, "Open containgin folder" );
shortcuts.emplace( MainWindowOpenInEditor, "Open file in editor" );
shortcuts.emplace( MainWindowCopyPathToClipboard, "Copy file path to clipboard" );
shortcuts.emplace( MainWindowOpenFromClipboard, "Paste text from clipboard" );
shortcuts.emplace( MainWindowOpenFromUrl, "Open file from URL" );
shortcuts.emplace( MainWindowFollowFile, "Monitor file changes" );
shortcuts.emplace( MainWindowReload, "Reload file" );
shortcuts.emplace( MainWindowStop, "Stop file loading" );
shortcuts.emplace( MainWindowScratchpad, "Open scratchpad" );
shortcuts.emplace( MainWindowSelectOpenFile, "Switch to file" );

shortcuts.emplace( CrawlerChangeVisibility, "Change filtered lines visibility" );
shortcuts.emplace( CrawlerIncreseTopViewSize, "Increase main view" );
shortcuts.emplace( CrawlerDecreaseTopViewSize, "Decrease main view" );
Expand Down Expand Up @@ -214,15 +277,17 @@ struct ShortcutAction {
return name != actionNames.end() ? name->second : QString::fromStdString( action );
}

static void registerShortcut( const std::map<std::string, QStringList>& configuredShortcuts,
using ConfiguredShortcuts = std::map<std::string, QStringList>;

static void registerShortcut( const ConfiguredShortcuts& configuredShortcuts,
std::map<QString, QShortcut*>& shortcutsStorage,
QWidget* shortcutsParent, Qt::ShortcutContext context,
const std::string& action, std::function<void()> func )
{
auto keysConfiguration = configuredShortcuts.find( action );
auto keys = keysConfiguration != configuredShortcuts.end()
? keysConfiguration->second
: ShortcutAction::defaultShortcuts( action );
const auto keysConfiguration = configuredShortcuts.find( action );
const auto keys = keysConfiguration != configuredShortcuts.end()
? keysConfiguration->second
: ShortcutAction::defaultShortcuts( action );

for ( const auto& key : qAsConst( keys ) ) {
if ( key.isEmpty() ) {
Expand All @@ -240,6 +305,21 @@ struct ShortcutAction {
}
}
}

static QList<QKeySequence> shortcutKeys( const std::string& action,
const ConfiguredShortcuts& configuredShortcuts )
{
const auto keysConfiguration = configuredShortcuts.find( action );
const auto keys = keysConfiguration != configuredShortcuts.end()
? keysConfiguration->second
: ShortcutAction::defaultShortcuts( action );

QList<QKeySequence> shortcuts;
std::transform( keys.begin(), keys.end(), std::back_inserter( shortcuts ),
[]( const QString& hotkeys ) { return QKeySequence( hotkeys ); } );

return shortcuts;
}
};

#endif
Loading

0 comments on commit 406e4ba

Please sign in to comment.