* Add error handling functions to ConfigHandler Refurbished functions setValue and value which were previously unused. These functions now set/get a setting with error handling. Currently recognizes only errors recognizable by QSettings. * Make use of value and setValue in ConfigHandler Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add checker for unrecognized general options Extraneous config options in [General] will be reported as errors. Added some placeholder functions to be implemented in future commits. * Introduce keysFromGroup function Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Check shortcut names for duplicates Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix notification spam Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Implement shortcut conflict checking Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix reading of fallbacks on error If there is a config error, some values would not be loaded correctly. Using the newly implemented function ConfigHandler::contains instead of QSettings::contains solves this issue. These changes reveal u bug that causes a crash on startup. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix crashes introduced in previous commit Because ConfigHandler is a dependency of most other classes, calling functions from those classes inside ConfigHandler caused infinite recursions in some cases. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add config file watcher Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add missing config options Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix bug in shortcut conflict detection Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add error resolved notification Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add GUI error message overlay Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add indicator in config window Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Use ConfigHandler::fileChanged in ConfigWindow Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix watcher sometimes not firing Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Improve config file watching performance Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add new way to handle config This is only a fundamental implementation. Future commits will replace everything with this new paradigm. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix getButtons and related functions Also refactored related code to use QList instead of QVector because QSettings does not work well with QVector. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make good use of the new way * Implement proper checking for basic types Everything is covered, apart from KeySequence. * Move fallback path to ExistingDir value handler Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Use consistent naming scheme in ConfigHandler Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Implement config getters/setters via macro Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Surround text with tr and clang-format Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix colors being saved obfuscated Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add ValueHandler::represenation Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move ValueHandler to separate files Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * confighandler.cpp: rename macro CUSTOM to OPTION Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix bug with shortcut conflict checker Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Update docs and fix setAllTheButtons Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Handle filenamePattern properly Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix failing build due to wrong function name Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix QSet error due to Qt version mismatch Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Replace QSharedPointer::get with data for older Qt versions Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix failing build on MacOS and ubuntu 18.04 Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add column headers to recognizedGeneralOptions map Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix ubuntu 18.04 error Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix false positive when shortcuts empty Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix wrong shortcut group prefix Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Implement proper shortcut checking Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add shortcut map in ConfigHandler Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move ConfigShortcuts functions to ShortcutsWidget Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix minor bugs Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add fallback scheme: Pictures, HOME, TMP Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add config --check CLI option Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add config error log to GUI Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Rename ValueHandler::description to expected * Convert Qt's #AARRGGBB to #RRGGBBAA and vice versa Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove obsolete `saveAfterCopyPath` Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix errors in example config Also added an additional ; in front of actual comments to differentiate them from commented options. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Allow special value 'picker' in userColors Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Allow only name, #RRGGBB, and #RRGGBBAA color formats Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com>
236 lines
8.1 KiB
C++
236 lines
8.1 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// SPDX-FileCopyrightText: 2020 Yurii Puchkov at Namecheap & Contributors
|
|
|
|
#include "shortcutswidget.h"
|
|
#include "capturetool.h"
|
|
#include "setshortcutwidget.h"
|
|
#include "src/core/qguiappcurrentscreen.h"
|
|
#include <QHeaderView>
|
|
#include <QIcon>
|
|
#include <QKeyEvent>
|
|
#include <QLabel>
|
|
#include <QStringList>
|
|
#include <QTableWidget>
|
|
#include <QVBoxLayout>
|
|
#include <QVector>
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
|
#include <QCursor>
|
|
#include <QRect>
|
|
#include <QScreen>
|
|
#endif
|
|
|
|
ShortcutsWidget::ShortcutsWidget(QWidget* parent)
|
|
: QWidget(parent)
|
|
{
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
setWindowIcon(QIcon(":img/app/flameshot.svg"));
|
|
setWindowTitle(tr("Hot Keys"));
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
|
QRect position = frameGeometry();
|
|
QScreen* screen = QGuiAppCurrentScreen().currentScreen();
|
|
position.moveCenter(screen->availableGeometry().center());
|
|
move(position.topLeft());
|
|
#endif
|
|
|
|
m_layout = new QVBoxLayout(this);
|
|
m_layout->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
|
|
|
initShortcuts();
|
|
initInfoTable();
|
|
show();
|
|
}
|
|
|
|
const QList<QStringList>& ShortcutsWidget::shortcuts()
|
|
{
|
|
return m_shortcuts;
|
|
}
|
|
|
|
void ShortcutsWidget::initInfoTable()
|
|
{
|
|
m_table = new QTableWidget(this);
|
|
m_table->setToolTip(tr("Available shortcuts in the screen capture mode."));
|
|
|
|
m_layout->addWidget(m_table);
|
|
|
|
m_table->setColumnCount(2);
|
|
m_table->setRowCount(m_shortcuts.size());
|
|
m_table->setSelectionMode(QAbstractItemView::NoSelection);
|
|
m_table->setFocusPolicy(Qt::NoFocus);
|
|
m_table->verticalHeader()->hide();
|
|
|
|
// header creation
|
|
QStringList names;
|
|
names << tr("Description") << tr("Key");
|
|
m_table->setHorizontalHeaderLabels(names);
|
|
connect(m_table,
|
|
SIGNAL(cellClicked(int, int)),
|
|
this,
|
|
SLOT(slotShortcutCellClicked(int, int)));
|
|
|
|
// add content
|
|
for (int i = 0; i < shortcuts().size(); ++i) {
|
|
const auto current_shortcut = m_shortcuts.at(i);
|
|
const auto identifier = current_shortcut.at(0);
|
|
const auto description = current_shortcut.at(1);
|
|
const auto default_key_sequence = current_shortcut.at(2);
|
|
m_table->setItem(i, 0, new QTableWidgetItem(description));
|
|
|
|
const auto key_sequence = identifier.isEmpty()
|
|
? default_key_sequence
|
|
: m_config.shortcut(identifier);
|
|
#if defined(Q_OS_MACOS)
|
|
QTableWidgetItem* item =
|
|
new QTableWidgetItem(nativeOSHotKeyText(key_sequence));
|
|
#else
|
|
QTableWidgetItem* item = new QTableWidgetItem(key_sequence);
|
|
#endif
|
|
item->setTextAlignment(Qt::AlignCenter);
|
|
m_table->setItem(i, 1, item);
|
|
|
|
if (identifier.isEmpty()) {
|
|
QFont font;
|
|
font.setBold(true);
|
|
item->setFont(font);
|
|
item->setFlags(item->flags() ^ Qt::ItemIsEnabled);
|
|
m_table->item(i, 1)->setFont(font);
|
|
}
|
|
}
|
|
|
|
// Read-only table items
|
|
for (int x = 0; x < m_table->rowCount(); ++x) {
|
|
for (int y = 0; y < m_table->columnCount(); ++y) {
|
|
QTableWidgetItem* item = m_table->item(x, y);
|
|
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
|
|
}
|
|
}
|
|
|
|
// adjust size
|
|
m_table->resizeColumnsToContents();
|
|
m_table->resizeRowsToContents();
|
|
m_table->horizontalHeader()->setMinimumSectionSize(200);
|
|
m_table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
|
m_table->horizontalHeader()->setSizePolicy(QSizePolicy::Expanding,
|
|
QSizePolicy::Expanding);
|
|
}
|
|
|
|
void ShortcutsWidget::slotShortcutCellClicked(int row, int col)
|
|
{
|
|
if (col == 1) {
|
|
// Ignore non-changable shortcuts
|
|
if (Qt::ItemIsEnabled !=
|
|
(Qt::ItemIsEnabled & m_table->item(row, col)->flags())) {
|
|
return;
|
|
}
|
|
|
|
SetShortcutDialog* setShortcutDialog = new SetShortcutDialog();
|
|
if (0 != setShortcutDialog->exec()) {
|
|
QString shortcutName = m_shortcuts.at(row).at(0);
|
|
QKeySequence shortcutValue = setShortcutDialog->shortcut();
|
|
|
|
// set no shortcut is Backspace
|
|
#if defined(Q_OS_MACOS)
|
|
if (shortcutValue == QKeySequence(Qt::CTRL + Qt::Key_Backspace)) {
|
|
shortcutValue = QKeySequence("");
|
|
}
|
|
#else
|
|
if (shortcutValue == QKeySequence(Qt::Key_Backspace)) {
|
|
shortcutValue = QKeySequence("");
|
|
}
|
|
#endif
|
|
|
|
if (m_config.setShortcut(shortcutName, shortcutValue.toString())) {
|
|
#if defined(Q_OS_MACOS)
|
|
QTableWidgetItem* item = new QTableWidgetItem(
|
|
nativeOSHotKeyText(shortcutValue.toString()));
|
|
#else
|
|
QTableWidgetItem* item =
|
|
new QTableWidgetItem(shortcutValue.toString());
|
|
#endif
|
|
item->setTextAlignment(Qt::AlignCenter);
|
|
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
|
|
m_table->setItem(row, col, item);
|
|
}
|
|
}
|
|
delete setShortcutDialog;
|
|
}
|
|
}
|
|
|
|
void ShortcutsWidget::initShortcuts()
|
|
{
|
|
auto buttons = CaptureToolButton::getIterableButtonTypes();
|
|
|
|
// get shortcuts names from capture buttons
|
|
for (const CaptureToolButton::ButtonType& t : buttons) {
|
|
CaptureToolButton* b = new CaptureToolButton(t, nullptr);
|
|
QString shortcutName = QVariant::fromValue(t).toString();
|
|
if (shortcutName != "TYPE_IMAGEUPLOADER") {
|
|
appendShortcut(shortcutName, b->tool()->description());
|
|
}
|
|
delete b;
|
|
}
|
|
|
|
// additional tools that don't have their own buttons
|
|
appendShortcut("TYPE_TOGGLE_PANEL", "Toggle side panel");
|
|
appendShortcut("TYPE_RESIZE_LEFT", "Resize selection left 1px");
|
|
appendShortcut("TYPE_RESIZE_RIGHT", "Resize selection right 1px");
|
|
appendShortcut("TYPE_RESIZE_UP", "Resize selection up 1px");
|
|
appendShortcut("TYPE_RESIZE_DOWN", "Resize selection down 1px");
|
|
appendShortcut("TYPE_SELECT_ALL", "Select entire screen");
|
|
appendShortcut("TYPE_MOVE_LEFT", "Move selection left 1px");
|
|
appendShortcut("TYPE_MOVE_RIGHT", "Move selection right 1px");
|
|
appendShortcut("TYPE_MOVE_UP", "Move selection up 1px");
|
|
appendShortcut("TYPE_MOVE_DOWN", "Move selection down 1px");
|
|
appendShortcut("TYPE_COMMIT_CURRENT_TOOL", "Commit text in text area");
|
|
appendShortcut("TYPE_DELETE_CURRENT_TOOL", "Delete current tool");
|
|
|
|
// non-editable shortcuts have an empty shortcut name
|
|
|
|
m_shortcuts << (QStringList() << "" << QObject::tr("Quit capture")
|
|
<< QKeySequence(Qt::Key_Escape).toString());
|
|
|
|
// Global hotkeys
|
|
#if defined(Q_OS_MACOS)
|
|
m_shortcuts << (QStringList()
|
|
<< "" << QObject::tr("Screenshot history") << "⇧⌘⌥H");
|
|
m_shortcuts << (QStringList()
|
|
<< "" << QObject::tr("Capture screen") << "⇧⌘⌥4");
|
|
#elif defined(Q_OS_WIN)
|
|
m_shortcuts << (QStringList() << "" << QObject::tr("Screenshot history")
|
|
<< "Shift+Print Screen");
|
|
m_shortcuts << (QStringList()
|
|
<< "" << QObject::tr("Capture screen") << "Print Screen");
|
|
#else
|
|
// TODO - Linux doesn't support global shortcuts for (XServer and Wayland),
|
|
// possibly it will be solved in the QHotKey library later. So it is
|
|
// disabled for now.
|
|
#endif
|
|
m_shortcuts << (QStringList()
|
|
<< "" << QObject::tr("Show color picker") << "Right Click");
|
|
m_shortcuts << (QStringList()
|
|
<< "" << QObject::tr("Change the tool's thickness")
|
|
<< "Mouse Wheel");
|
|
}
|
|
|
|
void ShortcutsWidget::appendShortcut(const QString& shortcutName,
|
|
const QString& description)
|
|
{
|
|
m_shortcuts << (QStringList()
|
|
<< shortcutName
|
|
<< QObject::tr(description.toStdString().c_str())
|
|
<< ConfigHandler().shortcut(shortcutName));
|
|
}
|
|
|
|
#if defined(Q_OS_MACOS)
|
|
const QString& ShortcutsWidget::nativeOSHotKeyText(const QString& text)
|
|
{
|
|
m_res = text;
|
|
m_res.replace("Ctrl+", "⌘");
|
|
m_res.replace("Alt+", "⌥");
|
|
m_res.replace("Meta+", "⌃");
|
|
m_res.replace("Shift+", "⇧");
|
|
return m_res;
|
|
}
|
|
#endif
|