Skip to content

Commit

Permalink
Use NavigationStyle for Vi/Emacs option
Browse files Browse the repository at this point in the history
  • Loading branch information
hluk committed Sep 25, 2024
1 parent 7c40fe0 commit aba654f
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 113 deletions.
2 changes: 1 addition & 1 deletion src/app/clipboardserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ void ClipboardServer::loadSettings(AppConfig *appConfig)
m_sharedData->editor = appConfig->option<Config::editor>();
m_sharedData->maxItems = appConfig->option<Config::maxitems>();
m_sharedData->textWrap = appConfig->option<Config::text_wrap>();
m_sharedData->viMode = appConfig->option<Config::vi>();
m_sharedData->navigationStyle = appConfig->option<Config::vi>();
m_sharedData->saveOnReturnKey = !appConfig->option<Config::edit_ctrl_return>();
m_sharedData->moveItemOnReturnKey = appConfig->option<Config::move>();
m_sharedData->showSimpleItems = appConfig->option<Config::show_simple_items>();
Expand Down
51 changes: 38 additions & 13 deletions src/common/appconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#ifndef APPCONFIG_H
#define APPCONFIG_H

#include "common/navigationstyle.h"
#include "common/settings.h"

class QString;
Expand All @@ -20,6 +21,14 @@ struct Config {
static Value defaultValue() { return Value(); }
static Value value(Value v) { return v; }
static const char *description() { return nullptr; }
// Convert the value read from QSettings or a QWidget in Preferences dialog
static Value fromVariant(const QVariant &value) {
return Config::value(value.value<Value>());
}
// Convert the value to store in QSettings
static QVariant toVariant(const Value &value) {
return QVariant::fromValue(value);
}
};

struct autostart : Config<bool> {
Expand Down Expand Up @@ -120,12 +129,33 @@ struct confirm_exit : Config<bool> {
static Value defaultValue() { return true; }
};

struct vi : Config<bool> {
struct vi : Config<NavigationStyle> {
static QString name() { return QStringLiteral("vi"); }
};
static Value fromVariant(const QVariant &value) {
// Backwards-compatibility
const QByteArray text = value.toByteArray().toLower();
if (text == "true" || text == "vi")
return NavigationStyle::Vi;
if (text == "emacs")
return NavigationStyle::Emacs;

struct emacs : Config<bool> {
static QString name() { return "emacs"; }
const int n = value.toInt();
if (n >= 0 && n <= NavigationStyleLastValue)
return static_cast<NavigationStyle>(n);

return NavigationStyle::Default;
}
static QVariant toVariant(const NavigationStyle &value) {
switch (value) {
case NavigationStyle::Default:
return QStringLiteral("false");
case NavigationStyle::Vi:
return QStringLiteral("true");
case NavigationStyle::Emacs:
return QStringLiteral("emacs");
}
return {};
}
};

struct save_filter_history : Config<bool> {
Expand Down Expand Up @@ -535,18 +565,13 @@ class AppConfig final
public:
QVariant option(const QString &name) const;

template <typename T>
T option(const QString &name, T defaultValue) const
{
const QVariant value = option(name);
return value.isValid() ? value.value<T>() : defaultValue;
}

template <typename T>
typename T::Value option() const
{
typename T::Value value = option(T::name(), T::defaultValue());
return T::value(value);
const QVariant variant = option(T::name());
if (!variant.isValid())
return T::defaultValue();
return T::fromVariant(variant);
}

void setOption(const QString &name, const QVariant &value);
Expand Down
9 changes: 9 additions & 0 deletions src/common/navigationstyle.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once

enum class NavigationStyle {
Default = 0,
Vi = 1,
Emacs = 2
};
constexpr int NavigationStyleLastValue = 2;
17 changes: 13 additions & 4 deletions src/common/option.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ Option::Option()
{}

Option::Option(const QVariant &default_value, const char *property_name,
QObject *obj)
QObject *obj, OptionValueConverterPtr &&converter)
: m_default_value(default_value)
, m_value(m_default_value)
, m_property_name(property_name)
, m_obj(obj)
, m_converter(std::move(converter))
{
if (m_obj)
m_obj->setProperty(m_property_name, m_default_value);
setValue(m_default_value);
}

Option::Option(const QVariant &default_value, const char *description)
Expand All @@ -50,11 +51,19 @@ Option::Option(const QVariant &default_value, const char *description)

QVariant Option::value() const
{
return m_obj != nullptr ? m_obj->property(m_property_name) : m_value;
if (m_obj == nullptr)
return m_value;

const QVariant value = m_obj->property(m_property_name);
if (m_converter)
return m_converter->save(value);
return value;
}

bool Option::setValue(const QVariant &value)
bool Option::setValue(const QVariant &rawValue)
{
const QVariant value = m_converter ? m_converter->read(rawValue) : rawValue;

if (m_obj != nullptr) {
m_obj->setProperty(m_property_name, value);
return m_obj->property(m_property_name) == value;
Expand Down
15 changes: 14 additions & 1 deletion src/common/option.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@

#include <QVariant>

#include <functional>
#include <memory>

class QObject;

class OptionValueConverter {
public:
virtual QVariant read(const QVariant &value) const = 0;
virtual QVariant save(const QVariant &value) const = 0;
};

using OptionValueConverterPtr = std::shared_ptr<OptionValueConverter>;

/**
* Configuration option.
*/
Expand All @@ -21,7 +32,8 @@ class Option final {
explicit Option(
const QVariant &default_value,
const char *property_name,
QObject *obj
QObject *obj,
OptionValueConverterPtr &&converter = nullptr
);

explicit Option(
Expand Down Expand Up @@ -51,6 +63,7 @@ class Option final {
const char *m_property_name = nullptr;
const char *m_description = nullptr;
QObject *m_obj = nullptr;
OptionValueConverterPtr m_converter = nullptr;
};

#endif // OPTION_H
4 changes: 2 additions & 2 deletions src/gui/clipboardbrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,13 +1378,13 @@ void ClipboardBrowser::keyPressEvent(QKeyEvent *event)
return;

// translate keys for vi mode
if (m_sharedData->viMode && handleViKey(event, this)) {
if (m_sharedData->navigationStyle == NavigationStyle::Vi && handleViKey(event, this)) {
d.updateIfNeeded();
return;
}

// translate keys for emacs mode
if (m_sharedData->emacsMode && handleEmacsKey(event, this))
if (m_sharedData->navigationStyle == NavigationStyle::Emacs && handleEmacsKey(event, this))
return;

const Qt::KeyboardModifiers mods = event->modifiers();
Expand Down
4 changes: 2 additions & 2 deletions src/gui/clipboardbrowsershared.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#ifndef CLIPBOARDBROWSERSHARED_H
#define CLIPBOARDBROWSERSHARED_H

#include "common/navigationstyle.h"
#include "gui/menuitems.h"
#include "gui/theme.h"

Expand All @@ -17,8 +18,7 @@ struct ClipboardBrowserShared {
QString editor;
int maxItems = 100;
bool textWrap = true;
bool viMode = false;
bool emacsMode = false;
NavigationStyle navigationStyle = NavigationStyle::Default;
bool saveOnReturnKey = false;
bool moveItemOnReturnKey = false;
bool showSimpleItems = false;
Expand Down
40 changes: 27 additions & 13 deletions src/gui/configurationmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@

namespace {

template <typename Config>
class AppConfigValueConverter final : public OptionValueConverter {
public:
QVariant read(const QVariant &variant) const override {
const auto value = Config::fromVariant(variant);
return QVariant::fromValue(value);
}
QVariant save(const QVariant &variant) const override {
const auto value = Config::fromVariant(variant);
return Config::toVariant(value);
}
};

class TabItem final : public ItemOrderList::Item {
public:
explicit TabItem(QWidget *widget) noexcept
Expand Down Expand Up @@ -257,8 +270,7 @@ void ConfigurationManager::initOptions()
bind<Config::move>(m_tabHistory->checkBoxMove);
bind<Config::check_clipboard>(m_tabGeneral->checkBoxClip);
bind<Config::confirm_exit>(m_tabGeneral->checkBoxConfirmExit);
bind<Config::vi>(m_tabGeneral->radioButtonViMode);
bind<Config::emacs>(m_tabGeneral->radioButtonEmacsMode);
bind<Config::vi>(m_tabGeneral->comboBoxNavigationStyle);
bind<Config::save_filter_history>(m_tabGeneral->checkBoxSaveFilterHistory);
bind<Config::autocompletion>(m_tabGeneral->checkBoxAutocompleteCommands);
bind<Config::always_on_top>(m_tabGeneral->checkBoxAlwaysOnTop);
Expand Down Expand Up @@ -348,7 +360,9 @@ void ConfigurationManager::initOptions()
template <typename Config, typename Widget>
void ConfigurationManager::bind(Widget *obj)
{
bind(Config::name(), obj, Config::defaultValue());
//OptionValueConverterPtr converter = std::make_shared<AppConfigValueConverter<Config>>();
OptionValueConverterPtr converter(new AppConfigValueConverter<Config>());
bind(Config::name(), obj, Config::defaultValue(), std::move(converter));
}

template <typename Config>
Expand All @@ -357,29 +371,29 @@ void ConfigurationManager::bind()
bind(Config::name(), QVariant::fromValue(Config::defaultValue()), Config::description());
}

void ConfigurationManager::bind(const QString &optionKey, QCheckBox *obj, bool defaultValue)
void ConfigurationManager::bind(const QString &optionKey, QCheckBox *obj, bool defaultValue, OptionValueConverterPtr &&converter)
{
m_options[optionKey] = Option(defaultValue, "checked", obj);
m_options[optionKey] = Option(defaultValue, "checked", obj, std::move(converter));
}

void ConfigurationManager::bind(const QString &optionKey, QRadioButton *obj, bool defaultValue)
void ConfigurationManager::bind(const QString &optionKey, QSpinBox *obj, int defaultValue, OptionValueConverterPtr &&converter)
{
m_options[optionKey] = Option(defaultValue, "checked", obj);
m_options[optionKey] = Option(defaultValue, "value", obj, std::move(converter));
}

void ConfigurationManager::bind(const QString &optionKey, QSpinBox *obj, int defaultValue)
void ConfigurationManager::bind(const QString &optionKey, QLineEdit *obj, const QString &defaultValue, OptionValueConverterPtr &&converter)
{
m_options[optionKey] = Option(defaultValue, "value", obj);
m_options[optionKey] = Option(defaultValue, "text", obj, std::move(converter));
}

void ConfigurationManager::bind(const QString &optionKey, QLineEdit *obj, const QString &defaultValue)
void ConfigurationManager::bind(const QString &optionKey, QComboBox *obj, int defaultValue, OptionValueConverterPtr &&converter)
{
m_options[optionKey] = Option(defaultValue, "text", obj);
m_options[optionKey] = Option(defaultValue, "currentIndex", obj, std::move(converter));
}

void ConfigurationManager::bind(const QString &optionKey, QComboBox *obj, int defaultValue)
void ConfigurationManager::bind(const QString &optionKey, QComboBox *obj, NavigationStyle defaultValue, OptionValueConverterPtr &&converter)
{
m_options[optionKey] = Option(defaultValue, "currentIndex", obj);
m_options[optionKey] = Option(static_cast<int>(defaultValue), "currentIndex", obj, std::move(converter));
}

void ConfigurationManager::bind(const QString &optionKey, const QVariant &defaultValue, const char *description)
Expand Down
14 changes: 7 additions & 7 deletions src/gui/configurationmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#ifndef CONFIGURATIONMANAGER_H
#define CONFIGURATIONMANAGER_H

#include "common/option.h"
#include "item/itemwidget.h"

#include <QDialog>
Expand All @@ -24,15 +25,14 @@ class ConfigTabAppearance;
class ConfigTabTabs;
class ItemFactory;
class ItemOrderList;
class Option;
class ShortcutsWidget;
class QAbstractButton;
class QCheckBox;
class QRadioButton;
class QComboBox;
class QLineEdit;
class QListWidgetItem;
class QSpinBox;
enum class NavigationStyle;

/**
* Configuration dialog.
Expand Down Expand Up @@ -106,11 +106,11 @@ class ConfigurationManager final : public QDialog
template <typename Config>
void bind();

void bind(const QString &optionKey, QCheckBox *obj, bool defaultValue);
void bind(const QString &optionKey, QRadioButton *obj, bool defaultValue);
void bind(const QString &optionKey, QSpinBox *obj, int defaultValue);
void bind(const QString &optionKey, QLineEdit *obj, const QString &defaultValue);
void bind(const QString &optionKey, QComboBox *obj, int defaultValue);
void bind(const QString &optionKey, QCheckBox *obj, bool defaultValue, OptionValueConverterPtr &&converter);
void bind(const QString &optionKey, QSpinBox *obj, int defaultValue, OptionValueConverterPtr &&converter);
void bind(const QString &optionKey, QLineEdit *obj, const QString &defaultValue, OptionValueConverterPtr &&converter);
void bind(const QString &optionKey, QComboBox *obj, int defaultValue, OptionValueConverterPtr &&converter);
void bind(const QString &optionKey, QComboBox *obj, NavigationStyle defaultValue, OptionValueConverterPtr &&converter);
void bind(const QString &optionKey, const QVariant &defaultValue, const char *description);

void updateTabComboBoxes();
Expand Down
18 changes: 6 additions & 12 deletions src/gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1345,7 +1345,7 @@ void MainWindow::onSearchShowRequest(const QString &text)

enterSearchMode();

if (!m_options.viMode || text != "/") {
if (m_options.navigationStyle != NavigationStyle::Vi || text != "/") {
ui->searchBar->setText(text);
ui->searchBar->end(false);
}
Expand Down Expand Up @@ -2530,7 +2530,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
if (m_options.hideTabs && key == Qt::Key_Alt)
setHideTabs(false);

if (m_options.viMode) {
if (m_options.navigationStyle == NavigationStyle::Vi) {
if (modifiers == Qt::ControlModifier && key == Qt::Key_BracketLeft) {
onEscape();
return;
Expand All @@ -2557,7 +2557,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
}
}

if (m_options.emacsMode) {
if (m_options.navigationStyle == NavigationStyle::Emacs) {
if ((modifiers == Qt::ControlModifier && key == Qt::Key_G)
|| (key == Qt::Key_Escape)) {
onEscape();
Expand Down Expand Up @@ -2714,15 +2714,9 @@ void MainWindow::loadSettings(QSettings &settings, AppConfig *appConfig)
setAlwaysOnTop(this, alwaysOnTop);
setAlwaysOnTop(m_commandDialog.data(), alwaysOnTop);

// Vi mode
m_options.viMode = appConfig->option<Config::vi>();
m_trayMenu->setViModeEnabled(m_options.viMode);
m_menu->setViModeEnabled(m_options.viMode);

// Emacs mode
m_options.emacsMode = appConfig->option<Config::emacs>();
m_trayMenu->setEmacsModeEnabled(m_options.emacsMode);
m_menu->setEmacsModeEnabled(m_options.emacsMode);
m_options.navigationStyle = appConfig->option<Config::vi>();
m_trayMenu->setNavigationStyle(m_options.navigationStyle);
m_menu->setNavigationStyle(m_options.navigationStyle);

// Number search
m_trayMenu->setNumberSearchEnabled(m_sharedData->numberSearch);
Expand Down
Loading

0 comments on commit aba654f

Please sign in to comment.