mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
KeyboardLayout: support specifying keyboard layout mappings
Captain mode now supports different layout mappings.
This commit is contained in:
parent
d014842bbf
commit
574aa4e70a
497
src/dialog/vkeyboardlayoutmappingdialog.cpp
Normal file
497
src/dialog/vkeyboardlayoutmappingdialog.cpp
Normal file
@ -0,0 +1,497 @@
|
||||
#include "vkeyboardlayoutmappingdialog.h"
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "vlineedit.h"
|
||||
#include "utils/vkeyboardlayoutmanager.h"
|
||||
#include "utils/vutils.h"
|
||||
#include "utils/viconutils.h"
|
||||
#include "vconfigmanager.h"
|
||||
|
||||
extern VConfigManager *g_config;
|
||||
|
||||
VKeyboardLayoutMappingDialog::VKeyboardLayoutMappingDialog(QWidget *p_parent)
|
||||
: QDialog(p_parent),
|
||||
m_mappingModified(false),
|
||||
m_listenIndex(-1)
|
||||
{
|
||||
setupUI();
|
||||
|
||||
loadAvailableMappings();
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::setupUI()
|
||||
{
|
||||
QString info = tr("Manage keybaord layout mappings to used in shortcuts.");
|
||||
info += "\n";
|
||||
info += tr("Double click an item to set mapping key.");
|
||||
QLabel *infoLabel = new QLabel(info, this);
|
||||
|
||||
// Selector.
|
||||
m_selectorCombo = VUtils::getComboBox(this);
|
||||
connect(m_selectorCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, [this](int p_idx) {
|
||||
loadMappingInfo(m_selectorCombo->itemData(p_idx).toString());
|
||||
});
|
||||
|
||||
// Add.
|
||||
m_addBtn = new QPushButton(VIconUtils::buttonIcon(":/resources/icons/add.svg"), "", this);
|
||||
m_addBtn->setToolTip(tr("New Mapping"));
|
||||
m_addBtn->setProperty("FlatBtn", true);
|
||||
connect(m_addBtn, &QPushButton::clicked,
|
||||
this, &VKeyboardLayoutMappingDialog::newMapping);
|
||||
|
||||
// Delete.
|
||||
m_deleteBtn = new QPushButton(VIconUtils::buttonDangerIcon(":/resources/icons/delete.svg"),
|
||||
"",
|
||||
this);
|
||||
m_deleteBtn->setToolTip(tr("Delete Mapping"));
|
||||
m_deleteBtn->setProperty("FlatBtn", true);
|
||||
connect(m_deleteBtn, &QPushButton::clicked,
|
||||
this, &VKeyboardLayoutMappingDialog::deleteCurrentMapping);
|
||||
|
||||
QHBoxLayout *selectLayout = new QHBoxLayout();
|
||||
selectLayout->addWidget(new QLabel(tr("Keyboard layout mapping:"), this));
|
||||
selectLayout->addWidget(m_selectorCombo);
|
||||
selectLayout->addWidget(m_addBtn);
|
||||
selectLayout->addWidget(m_deleteBtn);
|
||||
selectLayout->addStretch();
|
||||
|
||||
// Name.
|
||||
m_nameEdit = new VLineEdit(this);
|
||||
connect(m_nameEdit, &QLineEdit::textEdited,
|
||||
this, [this](const QString &p_text) {
|
||||
Q_UNUSED(p_text);
|
||||
setModified(true);
|
||||
});
|
||||
|
||||
QHBoxLayout *editLayout = new QHBoxLayout();
|
||||
editLayout->addWidget(new QLabel(tr("Name:"), this));
|
||||
editLayout->addWidget(m_nameEdit);
|
||||
editLayout->addStretch();
|
||||
|
||||
// Tree.
|
||||
m_contentTree = new QTreeWidget(this);
|
||||
m_contentTree->setProperty("ItemBorder", true);
|
||||
m_contentTree->setRootIsDecorated(false);
|
||||
m_contentTree->setColumnCount(2);
|
||||
m_contentTree->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
QStringList headers;
|
||||
headers << tr("Key") << tr("New Key");
|
||||
m_contentTree->setHeaderLabels(headers);
|
||||
|
||||
m_contentTree->installEventFilter(this);
|
||||
|
||||
connect(m_contentTree, &QTreeWidget::itemDoubleClicked,
|
||||
this, [this](QTreeWidgetItem *p_item, int p_column) {
|
||||
Q_UNUSED(p_column);
|
||||
int idx = m_contentTree->indexOfTopLevelItem(p_item);
|
||||
if (m_listenIndex == -1) {
|
||||
// Listen key for this item.
|
||||
setListeningKey(idx);
|
||||
} else if (idx == m_listenIndex) {
|
||||
// Cancel listening key for this item.
|
||||
cancelListeningKey();
|
||||
} else {
|
||||
// Recover previous item.
|
||||
cancelListeningKey();
|
||||
setListeningKey(idx);
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_contentTree, &QTreeWidget::itemClicked,
|
||||
this, [this](QTreeWidgetItem *p_item, int p_column) {
|
||||
Q_UNUSED(p_column);
|
||||
int idx = m_contentTree->indexOfTopLevelItem(p_item);
|
||||
if (idx != m_listenIndex) {
|
||||
cancelListeningKey();
|
||||
}
|
||||
});
|
||||
|
||||
QVBoxLayout *infoLayout = new QVBoxLayout();
|
||||
infoLayout->addLayout(editLayout);
|
||||
infoLayout->addWidget(m_contentTree);
|
||||
|
||||
QGroupBox *box = new QGroupBox(tr("Mapping Information"));
|
||||
box->setLayout(infoLayout);
|
||||
|
||||
// Ok is the default button.
|
||||
QDialogButtonBox *btnBox = new QDialogButtonBox(QDialogButtonBox::Ok
|
||||
| QDialogButtonBox::Apply
|
||||
| QDialogButtonBox::Cancel);
|
||||
connect(btnBox, &QDialogButtonBox::accepted,
|
||||
this, [this]() {
|
||||
if (applyChanges()) {
|
||||
QDialog::accept();
|
||||
}
|
||||
});
|
||||
connect(btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QPushButton *okBtn = btnBox->button(QDialogButtonBox::Ok);
|
||||
okBtn->setProperty("SpecialBtn", true);
|
||||
|
||||
m_applyBtn = btnBox->button(QDialogButtonBox::Apply);
|
||||
connect(m_applyBtn, &QPushButton::clicked,
|
||||
this, &VKeyboardLayoutMappingDialog::applyChanges);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->addWidget(infoLabel);
|
||||
mainLayout->addLayout(selectLayout);
|
||||
mainLayout->addWidget(box);
|
||||
mainLayout->addWidget(btnBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
setWindowTitle(tr("Keyboard Layout Mappings"));
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::newMapping()
|
||||
{
|
||||
QString name = getNewMappingName();
|
||||
if (!VKeyboardLayoutManager::addLayout(name)) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to add mapping <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle)
|
||||
.arg(name),
|
||||
tr("Please check the configuration file and try again."),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
return;
|
||||
}
|
||||
|
||||
loadAvailableMappings();
|
||||
|
||||
setCurrentMapping(name);
|
||||
}
|
||||
|
||||
QString VKeyboardLayoutMappingDialog::getNewMappingName() const
|
||||
{
|
||||
QString name;
|
||||
QString baseName("layout_mapping");
|
||||
int seq = 1;
|
||||
do {
|
||||
name = QString("%1_%2").arg(baseName).arg(QString::number(seq++), 3, '0');
|
||||
} while (m_selectorCombo->findData(name) != -1);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::deleteCurrentMapping()
|
||||
{
|
||||
QString mapping = currentMapping();
|
||||
if (mapping.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Are you sure to delete mapping <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle)
|
||||
.arg(mapping),
|
||||
"",
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
if (ret != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!VKeyboardLayoutManager::removeLayout(mapping)) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to delete mapping <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle)
|
||||
.arg(mapping),
|
||||
tr("Please check the configuration file and try again."),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
}
|
||||
|
||||
loadAvailableMappings();
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::loadAvailableMappings()
|
||||
{
|
||||
m_selectorCombo->setCurrentIndex(-1);
|
||||
m_selectorCombo->clear();
|
||||
|
||||
QStringList layouts = VKeyboardLayoutManager::availableLayouts();
|
||||
for (auto const & layout : layouts) {
|
||||
m_selectorCombo->addItem(layout, layout);
|
||||
}
|
||||
|
||||
if (m_selectorCombo->count() > 0) {
|
||||
m_selectorCombo->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
static QList<int> keysNeededToMap()
|
||||
{
|
||||
QList<int> keys;
|
||||
|
||||
for (int i = Qt::Key_0; i <= Qt::Key_9; ++i) {
|
||||
keys.append(i);
|
||||
}
|
||||
|
||||
for (int i = Qt::Key_A; i <= Qt::Key_Z; ++i) {
|
||||
keys.append(i);
|
||||
}
|
||||
|
||||
QList<int> addi = g_config->getKeyboardLayoutMappingKeys();
|
||||
for (auto tmp : addi) {
|
||||
if (!keys.contains(tmp)) {
|
||||
keys.append(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
static void recoverTreeItem(QTreeWidgetItem *p_item)
|
||||
{
|
||||
int key = p_item->data(0, Qt::UserRole).toInt();
|
||||
QString text0 = QString("%1 (%2)").arg(VUtils::keyToChar(key, false))
|
||||
.arg(key);
|
||||
p_item->setText(0, text0);
|
||||
|
||||
int newKey = p_item->data(1, Qt::UserRole).toInt();
|
||||
QString text1;
|
||||
if (newKey > 0) {
|
||||
text1 = QString("%1 (%2)").arg(VUtils::keyToChar(newKey, false))
|
||||
.arg(newKey);
|
||||
}
|
||||
|
||||
p_item->setText(1, text1);
|
||||
}
|
||||
|
||||
// @p_newKey, 0 if there is no mapping.
|
||||
static void fillTreeItem(QTreeWidgetItem *p_item, int p_key, int p_newKey)
|
||||
{
|
||||
p_item->setData(0, Qt::UserRole, p_key);
|
||||
p_item->setData(1, Qt::UserRole, p_newKey);
|
||||
recoverTreeItem(p_item);
|
||||
}
|
||||
|
||||
static void setTreeItemMapping(QTreeWidgetItem *p_item, int p_newKey)
|
||||
{
|
||||
p_item->setData(1, Qt::UserRole, p_newKey);
|
||||
}
|
||||
|
||||
static void fillMappingTree(QTreeWidget *p_tree, const QHash<int, int> &p_mappings)
|
||||
{
|
||||
QList<int> keys = keysNeededToMap();
|
||||
|
||||
for (auto key : keys) {
|
||||
int val = 0;
|
||||
auto it = p_mappings.find(key);
|
||||
if (it != p_mappings.end()) {
|
||||
val = it.value();
|
||||
}
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(p_tree);
|
||||
fillTreeItem(item, key, val);
|
||||
}
|
||||
}
|
||||
|
||||
static QHash<int, int> retrieveMappingFromTree(QTreeWidget *p_tree)
|
||||
{
|
||||
QHash<int, int> mappings;
|
||||
int cnt = p_tree->topLevelItemCount();
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
QTreeWidgetItem *item = p_tree->topLevelItem(i);
|
||||
int key = item->data(0, Qt::UserRole).toInt();
|
||||
int newKey = item->data(1, Qt::UserRole).toInt();
|
||||
if (newKey > 0) {
|
||||
mappings.insert(key, newKey);
|
||||
}
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::loadMappingInfo(const QString &p_layout)
|
||||
{
|
||||
setModified(false);
|
||||
|
||||
if (p_layout.isEmpty()) {
|
||||
m_nameEdit->clear();
|
||||
m_contentTree->clear();
|
||||
m_nameEdit->setEnabled(false);
|
||||
m_contentTree->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_nameEdit->setText(p_layout);
|
||||
m_nameEdit->setEnabled(true);
|
||||
|
||||
m_contentTree->clear();
|
||||
if (!p_layout.isEmpty()) {
|
||||
auto mappings = VKeyboardLayoutManager::readLayoutMapping(p_layout);
|
||||
fillMappingTree(m_contentTree, mappings);
|
||||
}
|
||||
m_contentTree->setEnabled(true);
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::updateButtons()
|
||||
{
|
||||
QString mapping = currentMapping();
|
||||
|
||||
m_deleteBtn->setEnabled(!mapping.isEmpty());
|
||||
m_applyBtn->setEnabled(m_mappingModified);
|
||||
}
|
||||
|
||||
QString VKeyboardLayoutMappingDialog::currentMapping() const
|
||||
{
|
||||
return m_selectorCombo->currentData().toString();
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::setCurrentMapping(const QString &p_layout)
|
||||
{
|
||||
return m_selectorCombo->setCurrentIndex(m_selectorCombo->findData(p_layout));
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutMappingDialog::applyChanges()
|
||||
{
|
||||
if (!m_mappingModified) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString mapping = currentMapping();
|
||||
if (mapping.isEmpty()) {
|
||||
setModified(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the name.
|
||||
QString newName = m_nameEdit->text();
|
||||
if (newName.isEmpty() || newName.toLower() == "global") {
|
||||
// Set back the original name.
|
||||
m_nameEdit->setText(mapping);
|
||||
m_nameEdit->selectAll();
|
||||
m_nameEdit->setFocus();
|
||||
return false;
|
||||
} else if (newName != mapping) {
|
||||
// Rename the mapping.
|
||||
if (!VKeyboardLayoutManager::renameLayout(mapping, newName)) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to rename mapping <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle)
|
||||
.arg(mapping),
|
||||
tr("Please check the configuration file and try again."),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
m_nameEdit->setText(mapping);
|
||||
m_nameEdit->selectAll();
|
||||
m_nameEdit->setFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the combobox.
|
||||
int idx = m_selectorCombo->currentIndex();
|
||||
m_selectorCombo->setItemText(idx, newName);
|
||||
m_selectorCombo->setItemData(idx, newName);
|
||||
|
||||
mapping = newName;
|
||||
}
|
||||
|
||||
// Check the mappings.
|
||||
QHash<int, int> mappings = retrieveMappingFromTree(m_contentTree);
|
||||
if (!VKeyboardLayoutManager::updateLayout(mapping, mappings)) {
|
||||
VUtils::showMessage(QMessageBox::Warning,
|
||||
tr("Warning"),
|
||||
tr("Fail to update mapping <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle)
|
||||
.arg(mapping),
|
||||
tr("Please check the configuration file and try again."),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
this);
|
||||
return false;
|
||||
}
|
||||
|
||||
setModified(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutMappingDialog::eventFilter(QObject *p_obj, QEvent *p_event)
|
||||
{
|
||||
if (p_obj == m_contentTree) {
|
||||
switch (p_event->type()) {
|
||||
case QEvent::FocusOut:
|
||||
cancelListeningKey();
|
||||
break;
|
||||
|
||||
case QEvent::KeyPress:
|
||||
if (listenKey(static_cast<QKeyEvent *>(p_event))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QDialog::eventFilter(p_obj, p_event);
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutMappingDialog::listenKey(QKeyEvent *p_event)
|
||||
{
|
||||
if (m_listenIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int key = p_event->key();
|
||||
|
||||
if (VUtils::isMetaKey(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key == Qt::Key_Escape) {
|
||||
cancelListeningKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the mapping.
|
||||
QTreeWidgetItem *item = m_contentTree->topLevelItem(m_listenIndex);
|
||||
setTreeItemMapping(item, key);
|
||||
setModified(true);
|
||||
|
||||
// Try next item automatically.
|
||||
int nextIdx = m_listenIndex + 1;
|
||||
cancelListeningKey();
|
||||
|
||||
if (nextIdx < m_contentTree->topLevelItemCount()) {
|
||||
QTreeWidgetItem *item = m_contentTree->topLevelItem(nextIdx);
|
||||
m_contentTree->clearSelection();
|
||||
m_contentTree->setCurrentItem(item);
|
||||
|
||||
setListeningKey(nextIdx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::cancelListeningKey()
|
||||
{
|
||||
if (m_listenIndex > -1) {
|
||||
// Recover that item.
|
||||
recoverTreeItem(m_contentTree->topLevelItem(m_listenIndex));
|
||||
|
||||
m_listenIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void VKeyboardLayoutMappingDialog::setListeningKey(int p_idx)
|
||||
{
|
||||
Q_ASSERT(m_listenIndex == -1 && p_idx > -1);
|
||||
m_listenIndex = p_idx;
|
||||
QTreeWidgetItem *item = m_contentTree->topLevelItem(m_listenIndex);
|
||||
item->setText(1, tr("Press key to set mapping"));
|
||||
}
|
73
src/dialog/vkeyboardlayoutmappingdialog.h
Normal file
73
src/dialog/vkeyboardlayoutmappingdialog.h
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef VKEYBOARDLAYOUTMAPPINGDIALOG_H
|
||||
#define VKEYBOARDLAYOUTMAPPINGDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QString;
|
||||
class QTreeWidget;
|
||||
class VLineEdit;
|
||||
class QPushButton;
|
||||
class QComboBox;
|
||||
|
||||
class VKeyboardLayoutMappingDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VKeyboardLayoutMappingDialog(QWidget *p_parent = nullptr);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE;
|
||||
|
||||
private slots:
|
||||
void newMapping();
|
||||
|
||||
void deleteCurrentMapping();
|
||||
|
||||
// Return true if changes are saved.
|
||||
bool applyChanges();
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
||||
void loadAvailableMappings();
|
||||
|
||||
void loadMappingInfo(const QString &p_layout);
|
||||
|
||||
void updateButtons();
|
||||
|
||||
QString currentMapping() const;
|
||||
|
||||
void setCurrentMapping(const QString &p_layout);
|
||||
|
||||
QString getNewMappingName() const;
|
||||
|
||||
bool listenKey(QKeyEvent *p_event);
|
||||
|
||||
void cancelListeningKey();
|
||||
|
||||
void setListeningKey(int p_idx);
|
||||
|
||||
void setModified(bool p_modified);
|
||||
|
||||
QComboBox *m_selectorCombo;
|
||||
QPushButton *m_addBtn;
|
||||
QPushButton *m_deleteBtn;
|
||||
VLineEdit *m_nameEdit;
|
||||
QTreeWidget *m_contentTree;
|
||||
QPushButton *m_applyBtn;
|
||||
|
||||
bool m_mappingModified;
|
||||
|
||||
// Index of the item in the tree which is listening key.
|
||||
// -1 for not listening.
|
||||
int m_listenIndex;
|
||||
};
|
||||
|
||||
inline void VKeyboardLayoutMappingDialog::setModified(bool p_modified)
|
||||
{
|
||||
m_mappingModified = p_modified;
|
||||
updateButtons();
|
||||
}
|
||||
#endif // VKEYBOARDLAYOUTMAPPINGDIALOG_H
|
@ -9,6 +9,8 @@
|
||||
#include "vlineedit.h"
|
||||
#include "vplantumlhelper.h"
|
||||
#include "vgraphvizhelper.h"
|
||||
#include "utils/vkeyboardlayoutmanager.h"
|
||||
#include "dialog/vkeyboardlayoutmappingdialog.h"
|
||||
|
||||
extern VConfigManager *g_config;
|
||||
|
||||
@ -324,11 +326,29 @@ VGeneralTab::VGeneralTab(QWidget *p_parent)
|
||||
qaLayout->addWidget(m_quickAccessEdit);
|
||||
qaLayout->addWidget(browseBtn);
|
||||
|
||||
// Keyboard layout mappings.
|
||||
m_keyboardLayoutCombo = VUtils::getComboBox(this);
|
||||
m_keyboardLayoutCombo->setToolTip(tr("Choose the keyboard layout mapping to use in shortcuts"));
|
||||
|
||||
QPushButton *editLayoutBtn = new QPushButton(tr("Edit"), this);
|
||||
connect(editLayoutBtn, &QPushButton::clicked,
|
||||
this, [this]() {
|
||||
VKeyboardLayoutMappingDialog dialog(this);
|
||||
dialog.exec();
|
||||
loadKeyboardLayoutMapping();
|
||||
});
|
||||
|
||||
QHBoxLayout *klLayout = new QHBoxLayout();
|
||||
klLayout->addWidget(m_keyboardLayoutCombo);
|
||||
klLayout->addWidget(editLayoutBtn);
|
||||
klLayout->addStretch();
|
||||
|
||||
QFormLayout *optionLayout = new QFormLayout();
|
||||
optionLayout->addRow(tr("Language:"), m_langCombo);
|
||||
optionLayout->addRow(m_systemTray);
|
||||
optionLayout->addRow(tr("Startup pages:"), startupLayout);
|
||||
optionLayout->addRow(tr("Quick access:"), qaLayout);
|
||||
optionLayout->addRow(tr("Keyboard layout mapping:"), klLayout);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->addLayout(optionLayout);
|
||||
@ -409,6 +429,10 @@ bool VGeneralTab::loadConfiguration()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!loadKeyboardLayoutMapping()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -430,6 +454,10 @@ bool VGeneralTab::saveConfiguration()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!saveKeyboardLayoutMapping()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -528,6 +556,38 @@ bool VGeneralTab::saveQuickAccess()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VGeneralTab::loadKeyboardLayoutMapping()
|
||||
{
|
||||
m_keyboardLayoutCombo->clear();
|
||||
|
||||
m_keyboardLayoutCombo->addItem(tr("None"), "");
|
||||
|
||||
QStringList layouts = VKeyboardLayoutManager::availableLayouts();
|
||||
for (auto const & layout : layouts) {
|
||||
m_keyboardLayoutCombo->addItem(layout, layout);
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
const auto &cur = VKeyboardLayoutManager::currentLayout();
|
||||
if (!cur.m_name.isEmpty()) {
|
||||
idx = m_keyboardLayoutCombo->findData(cur.m_name);
|
||||
if (idx == -1) {
|
||||
idx = 0;
|
||||
VKeyboardLayoutManager::setCurrentLayout("");
|
||||
}
|
||||
}
|
||||
|
||||
m_keyboardLayoutCombo->setCurrentIndex(idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VGeneralTab::saveKeyboardLayoutMapping()
|
||||
{
|
||||
g_config->setKeyboardLayout(m_keyboardLayoutCombo->currentData().toString());
|
||||
VKeyboardLayoutManager::update();
|
||||
return true;
|
||||
}
|
||||
|
||||
VLookTab::VLookTab(QWidget *p_parent)
|
||||
: QWidget(p_parent)
|
||||
{
|
||||
|
@ -40,6 +40,9 @@ private:
|
||||
bool loadQuickAccess();
|
||||
bool saveQuickAccess();
|
||||
|
||||
bool loadKeyboardLayoutMapping();
|
||||
bool saveKeyboardLayoutMapping();
|
||||
|
||||
// Language
|
||||
QComboBox *m_langCombo;
|
||||
|
||||
@ -58,6 +61,9 @@ private:
|
||||
// Quick access note path.
|
||||
VLineEdit *m_quickAccessEdit;
|
||||
|
||||
// Keyboard layout mappings.
|
||||
QComboBox *m_keyboardLayoutCombo;
|
||||
|
||||
static const QVector<QString> c_availableLangs;
|
||||
};
|
||||
|
||||
|
7
src/resources/icons/add.svg
Normal file
7
src/resources/icons/add.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<polygon style="fill:#000000" points="448,224 288,224 288,64 224,64 224,224 64,224 64,288 224,288 224,448 288,448 288,288 448,288 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 618 B |
10
src/resources/icons/delete.svg
Normal file
10
src/resources/icons/delete.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path style="fill:#000000" d="M341,128V99c0-19.1-14.5-35-34.5-35H205.4C185.5,64,171,79.9,171,99v29H80v32h9.2c0,0,5.4,0.6,8.2,3.4c2.8,2.8,3.9,9,3.9,9
|
||||
l19,241.7c1.5,29.4,1.5,33.9,36,33.9h199.4c34.5,0,34.5-4.4,36-33.8l19-241.6c0,0,1.1-6.3,3.9-9.1c2.8-2.8,8.2-3.4,8.2-3.4h9.2v-32
|
||||
h-91V128z M192,99c0-9.6,7.8-15,17.7-15h91.7c9.9,0,18.6,5.5,18.6,15v29H192V99z M183.5,384l-10.3-192h20.3L204,384H183.5z
|
||||
M267.1,384h-22V192h22V384z M328.7,384h-20.4l10.5-192h20.3L328.7,384z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 955 B |
@ -256,10 +256,6 @@ max_num_of_tag_labels=3
|
||||
; 2 - web to editor
|
||||
smart_live_preview=3
|
||||
|
||||
; Support multiple keyboard layout
|
||||
; Not valid on macOS
|
||||
multiple_keyboard_layout=true
|
||||
|
||||
; Whether insert new note in front
|
||||
insert_new_note_in_front=false
|
||||
|
||||
@ -269,6 +265,13 @@ highlight_matches_in_page=true
|
||||
; Incremental search in page
|
||||
find_incremental_search=true
|
||||
|
||||
; Additional Qt::Key_XXX which will be mapped in different layouts
|
||||
; List of integer values.
|
||||
keyboard_layout_mapping_keys=
|
||||
|
||||
; Chosen keyboard layout mapping from keyboard_layouts.ini
|
||||
keyboard_layout=
|
||||
|
||||
[editor]
|
||||
; Auto indent as previous line
|
||||
auto_indent=true
|
||||
|
@ -146,7 +146,9 @@ SOURCES += main.cpp\
|
||||
pegmarkdownhighlighter.cpp \
|
||||
pegparser.cpp \
|
||||
peghighlighterresult.cpp \
|
||||
vtexteditcompleter.cpp
|
||||
vtexteditcompleter.cpp \
|
||||
utils/vkeyboardlayoutmanager.cpp \
|
||||
dialog/vkeyboardlayoutmappingdialog.cpp
|
||||
|
||||
HEADERS += vmainwindow.h \
|
||||
vdirectorytree.h \
|
||||
@ -285,7 +287,9 @@ HEADERS += vmainwindow.h \
|
||||
pegparser.h \
|
||||
peghighlighterresult.h \
|
||||
vtexteditcompleter.h \
|
||||
vtextdocumentlayoutdata.h
|
||||
vtextdocumentlayoutdata.h \
|
||||
utils/vkeyboardlayoutmanager.h \
|
||||
dialog/vkeyboardlayoutmappingdialog.h
|
||||
|
||||
RESOURCES += \
|
||||
vnote.qrc \
|
||||
|
298
src/utils/vkeyboardlayoutmanager.cpp
Normal file
298
src/utils/vkeyboardlayoutmanager.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
#include "vkeyboardlayoutmanager.h"
|
||||
|
||||
#include <QSharedPointer>
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
|
||||
#include "vconfigmanager.h"
|
||||
|
||||
extern VConfigManager *g_config;
|
||||
|
||||
VKeyboardLayoutManager *VKeyboardLayoutManager::s_inst = NULL;
|
||||
|
||||
VKeyboardLayoutManager *VKeyboardLayoutManager::inst()
|
||||
{
|
||||
if (!s_inst) {
|
||||
s_inst = new VKeyboardLayoutManager();
|
||||
s_inst->update(g_config);
|
||||
}
|
||||
|
||||
return s_inst;
|
||||
}
|
||||
|
||||
static QSharedPointer<QSettings> layoutSettings(const VConfigManager *p_config,
|
||||
bool p_create = false)
|
||||
{
|
||||
QSharedPointer<QSettings> settings;
|
||||
QString file = p_config->getKeyboardLayoutConfigFilePath();
|
||||
if (file.isEmpty()) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(file) && !p_create) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings.reset(new QSettings(file, QSettings::IniFormat));
|
||||
return settings;
|
||||
}
|
||||
|
||||
static void clearLayoutMapping(const QSharedPointer<QSettings> &p_settings,
|
||||
const QString &p_name)
|
||||
{
|
||||
p_settings->beginGroup(p_name);
|
||||
p_settings->remove("");
|
||||
p_settings->endGroup();
|
||||
}
|
||||
|
||||
static QHash<int, int> readLayoutMappingInternal(const QSharedPointer<QSettings> &p_settings,
|
||||
const QString &p_name)
|
||||
{
|
||||
QHash<int, int> mappings;
|
||||
|
||||
p_settings->beginGroup(p_name);
|
||||
QStringList keys = p_settings->childKeys();
|
||||
for (auto const & key : keys) {
|
||||
if (key.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int keyNum = key.toInt(&ok);
|
||||
if (!ok) {
|
||||
qWarning() << "readLayoutMappingInternal() skip bad key" << key << "in layout" << p_name;
|
||||
continue;
|
||||
}
|
||||
|
||||
int valNum = p_settings->value(key).toInt();
|
||||
mappings.insert(keyNum, valNum);
|
||||
}
|
||||
|
||||
p_settings->endGroup();
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
static bool writeLayoutMapping(const QSharedPointer<QSettings> &p_settings,
|
||||
const QString &p_name,
|
||||
const QHash<int, int> &p_mappings)
|
||||
{
|
||||
clearLayoutMapping(p_settings, p_name);
|
||||
|
||||
p_settings->beginGroup(p_name);
|
||||
for (auto it = p_mappings.begin(); it != p_mappings.end(); ++it) {
|
||||
p_settings->setValue(QString::number(it.key()), it.value());
|
||||
}
|
||||
p_settings->endGroup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VKeyboardLayoutManager::update(VConfigManager *p_config)
|
||||
{
|
||||
m_layout.clear();
|
||||
|
||||
m_layout.m_name = p_config->getKeyboardLayout();
|
||||
if (m_layout.m_name.isEmpty()) {
|
||||
// No mapping.
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "using keyboard layout mapping" << m_layout.m_name;
|
||||
|
||||
auto settings = layoutSettings(p_config);
|
||||
if (settings.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_layout.setMapping(readLayoutMappingInternal(settings, m_layout.m_name));
|
||||
}
|
||||
|
||||
void VKeyboardLayoutManager::update()
|
||||
{
|
||||
inst()->update(g_config);
|
||||
}
|
||||
|
||||
const VKeyboardLayoutManager::Layout &VKeyboardLayoutManager::currentLayout()
|
||||
{
|
||||
return inst()->m_layout;
|
||||
}
|
||||
|
||||
static QStringList readAvailableLayoutMappings(const QSharedPointer<QSettings> &p_settings)
|
||||
{
|
||||
QString fullKey("global/layout_mappings");
|
||||
return p_settings->value(fullKey).toStringList();
|
||||
}
|
||||
|
||||
static void writeAvailableLayoutMappings(const QSharedPointer<QSettings> &p_settings,
|
||||
const QStringList &p_layouts)
|
||||
{
|
||||
QString fullKey("global/layout_mappings");
|
||||
return p_settings->setValue(fullKey, p_layouts);
|
||||
}
|
||||
|
||||
QStringList VKeyboardLayoutManager::availableLayouts()
|
||||
{
|
||||
QStringList layouts;
|
||||
auto settings = layoutSettings(g_config);
|
||||
if (settings.isNull()) {
|
||||
return layouts;
|
||||
}
|
||||
|
||||
layouts = readAvailableLayoutMappings(settings);
|
||||
return layouts;
|
||||
}
|
||||
|
||||
void VKeyboardLayoutManager::setCurrentLayout(const QString &p_name)
|
||||
{
|
||||
auto mgr = inst();
|
||||
if (mgr->m_layout.m_name == p_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_config->setKeyboardLayout(p_name);
|
||||
mgr->update(g_config);
|
||||
}
|
||||
|
||||
static bool isValidLayoutName(const QString &p_name)
|
||||
{
|
||||
return !p_name.isEmpty() && p_name.toLower() != "global";
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutManager::addLayout(const QString &p_name)
|
||||
{
|
||||
Q_ASSERT(isValidLayoutName(p_name));
|
||||
|
||||
auto settings = layoutSettings(g_config, true);
|
||||
if (settings.isNull()) {
|
||||
qWarning() << "fail to open keyboard layout QSettings";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList layouts = readAvailableLayoutMappings(settings);
|
||||
if (layouts.contains(p_name)) {
|
||||
qWarning() << "Keyboard layout mapping" << p_name << "already exists";
|
||||
return false;
|
||||
}
|
||||
|
||||
layouts.append(p_name);
|
||||
writeAvailableLayoutMappings(settings, layouts);
|
||||
|
||||
clearLayoutMapping(settings, p_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutManager::removeLayout(const QString &p_name)
|
||||
{
|
||||
Q_ASSERT(isValidLayoutName(p_name));
|
||||
|
||||
auto settings = layoutSettings(g_config, true);
|
||||
if (settings.isNull()) {
|
||||
qWarning() << "fail to open keyboard layout QSettings";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList layouts = readAvailableLayoutMappings(settings);
|
||||
int idx = layouts.indexOf(p_name);
|
||||
if (idx == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
layouts.removeAt(idx);
|
||||
writeAvailableLayoutMappings(settings, layouts);
|
||||
|
||||
clearLayoutMapping(settings, p_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutManager::renameLayout(const QString &p_name, const QString &p_newName)
|
||||
{
|
||||
Q_ASSERT(isValidLayoutName(p_name));
|
||||
Q_ASSERT(isValidLayoutName(p_newName));
|
||||
|
||||
auto settings = layoutSettings(g_config, true);
|
||||
if (settings.isNull()) {
|
||||
qWarning() << "fail to open keyboard layout QSettings";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList layouts = readAvailableLayoutMappings(settings);
|
||||
int idx = layouts.indexOf(p_name);
|
||||
if (idx == -1) {
|
||||
qWarning() << "fail to find keyboard layout mapping" << p_name << "to rename";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layouts.indexOf(p_newName) != -1) {
|
||||
qWarning() << "keyboard layout mapping" << p_newName << "already exists";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto content = readLayoutMappingInternal(settings, p_name);
|
||||
// Copy the group.
|
||||
if (!writeLayoutMapping(settings, p_newName, content)) {
|
||||
qWarning() << "fail to write new layout mapping" << p_newName;
|
||||
return false;
|
||||
}
|
||||
|
||||
clearLayoutMapping(settings, p_name);
|
||||
|
||||
layouts.replace(idx, p_newName);
|
||||
writeAvailableLayoutMappings(settings, layouts);
|
||||
|
||||
// Check current layout.
|
||||
if (g_config->getKeyboardLayout() == p_name) {
|
||||
Q_ASSERT(inst()->m_layout.m_name == p_name);
|
||||
g_config->setKeyboardLayout(p_newName);
|
||||
inst()->m_layout.m_name = p_newName;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QHash<int, int> VKeyboardLayoutManager::readLayoutMapping(const QString &p_name)
|
||||
{
|
||||
QHash<int, int> mappings;
|
||||
if (p_name.isEmpty()) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
auto settings = layoutSettings(g_config);
|
||||
if (settings.isNull()) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
return readLayoutMappingInternal(settings, p_name);
|
||||
}
|
||||
|
||||
bool VKeyboardLayoutManager::updateLayout(const QString &p_name,
|
||||
const QHash<int, int> &p_mapping)
|
||||
{
|
||||
Q_ASSERT(isValidLayoutName(p_name));
|
||||
|
||||
auto settings = layoutSettings(g_config, true);
|
||||
if (settings.isNull()) {
|
||||
qWarning() << "fail to open keyboard layout QSettings";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList layouts = readAvailableLayoutMappings(settings);
|
||||
int idx = layouts.indexOf(p_name);
|
||||
if (idx == -1) {
|
||||
qWarning() << "fail to find keyboard layout mapping" << p_name << "to update";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!writeLayoutMapping(settings, p_name, p_mapping)) {
|
||||
qWarning() << "fail to write layout mapping" << p_name;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check current layout.
|
||||
if (inst()->m_layout.m_name == p_name) {
|
||||
inst()->m_layout.setMapping(p_mapping);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
79
src/utils/vkeyboardlayoutmanager.h
Normal file
79
src/utils/vkeyboardlayoutmanager.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef VKEYBOARDLAYOUTMANAGER_H
|
||||
#define VKEYBOARDLAYOUTMANAGER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QHash>
|
||||
|
||||
class VConfigManager;
|
||||
|
||||
class VKeyboardLayoutManager
|
||||
{
|
||||
public:
|
||||
struct Layout
|
||||
{
|
||||
void clear()
|
||||
{
|
||||
m_name.clear();
|
||||
m_mapping.clear();
|
||||
}
|
||||
|
||||
void setMapping(const QHash<int, int> &p_mapping)
|
||||
{
|
||||
m_mapping.clear();
|
||||
|
||||
for (auto it = p_mapping.begin(); it != p_mapping.end(); ++it) {
|
||||
m_mapping.insert(it.value(), it.key());
|
||||
}
|
||||
}
|
||||
|
||||
QString m_name;
|
||||
// Reversed mapping.
|
||||
QHash<int, int> m_mapping;
|
||||
};
|
||||
|
||||
static void update();
|
||||
|
||||
static const VKeyboardLayoutManager::Layout ¤tLayout();
|
||||
|
||||
static void setCurrentLayout(const QString &p_name);
|
||||
|
||||
static QStringList availableLayouts();
|
||||
|
||||
static bool addLayout(const QString &p_name);
|
||||
|
||||
static bool removeLayout(const QString &p_name);
|
||||
|
||||
static bool renameLayout(const QString &p_name, const QString &p_newName);
|
||||
|
||||
static bool updateLayout(const QString &p_name, const QHash<int, int> &p_mapping);
|
||||
|
||||
static QHash<int, int> readLayoutMapping(const QString &p_name);
|
||||
|
||||
static int mapKey(int p_key);
|
||||
|
||||
private:
|
||||
VKeyboardLayoutManager() {}
|
||||
|
||||
static VKeyboardLayoutManager *inst();
|
||||
|
||||
void update(VConfigManager *p_config);
|
||||
|
||||
Layout m_layout;
|
||||
|
||||
static VKeyboardLayoutManager *s_inst;
|
||||
};
|
||||
|
||||
inline int VKeyboardLayoutManager::mapKey(int p_key)
|
||||
{
|
||||
const Layout &layout = inst()->m_layout;
|
||||
if (!layout.m_name.isEmpty()) {
|
||||
auto it = layout.m_mapping.find(p_key);
|
||||
if (it != layout.m_mapping.end()) {
|
||||
return it.value();
|
||||
}
|
||||
}
|
||||
|
||||
return p_key;
|
||||
}
|
||||
#endif // VKEYBOARDLAYOUTMANAGER_H
|
@ -1376,6 +1376,10 @@ bool VUtils::isMetaKey(int p_key)
|
||||
return p_key == Qt::Key_Control
|
||||
|| p_key == Qt::Key_Shift
|
||||
|| p_key == Qt::Key_Meta
|
||||
#if defined(Q_OS_LINUX)
|
||||
// For mapping Caps as Ctrl in KDE.
|
||||
|| p_key == Qt::Key_CapsLock
|
||||
#endif
|
||||
|| p_key == Qt::Key_Alt;
|
||||
}
|
||||
|
||||
|
@ -571,11 +571,7 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, int *p_autoIndentPos)
|
||||
|
||||
if (m_registerPending) {
|
||||
// Ctrl and Shift may be sent out first.
|
||||
if (key == Qt::Key_Control
|
||||
|| key == Qt::Key_Shift
|
||||
|| key == Qt::Key_Meta
|
||||
// For mapping Caps as Ctrl in KDE.
|
||||
|| key == Qt::Key_CapsLock) {
|
||||
if (VUtils::isMetaKey(key)) {
|
||||
goto accept;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "vfilelist.h"
|
||||
#include "vnavigationmode.h"
|
||||
#include "vconfigmanager.h"
|
||||
#include "utils/vkeyboardlayoutmanager.h"
|
||||
|
||||
extern VConfigManager *g_config;
|
||||
|
||||
@ -95,10 +96,7 @@ void VCaptain::keyPressEvent(QKeyEvent *p_event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_config->getMultipleKeyboardLayout()) {
|
||||
// Use virtual key here for different layout.
|
||||
key = p_event->nativeVirtualKey();
|
||||
}
|
||||
key = VKeyboardLayoutManager::mapKey(key);
|
||||
|
||||
if (handleKeyPress(key, modifiers)) {
|
||||
p_event->accept();
|
||||
|
@ -29,6 +29,8 @@ const QString VConfigManager::c_sessionConfigFile = QString("session.ini");
|
||||
|
||||
const QString VConfigManager::c_snippetConfigFile = QString("snippet.json");
|
||||
|
||||
const QString VConfigManager::c_keyboardLayoutConfigFile = QString("keyboard_layouts.ini");
|
||||
|
||||
const QString VConfigManager::c_styleConfigFolder = QString("styles");
|
||||
|
||||
const QString VConfigManager::c_themeConfigFolder = QString("themes");
|
||||
@ -314,13 +316,6 @@ void VConfigManager::initialize()
|
||||
m_smartLivePreview = getConfigFromSettings("global",
|
||||
"smart_live_preview").toInt();
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
|
||||
m_multipleKeyboardLayout = false;
|
||||
#else
|
||||
m_multipleKeyboardLayout = getConfigFromSettings("global",
|
||||
"multiple_keyboard_layout").toBool();
|
||||
#endif
|
||||
|
||||
m_insertNewNoteInFront = getConfigFromSettings("global",
|
||||
"insert_new_note_in_front").toBool();
|
||||
|
||||
@ -862,6 +857,11 @@ const QString &VConfigManager::getSnippetConfigFilePath() const
|
||||
return path;
|
||||
}
|
||||
|
||||
const QString VConfigManager::getKeyboardLayoutConfigFilePath() const
|
||||
{
|
||||
return QDir(getConfigFolder()).filePath(c_keyboardLayoutConfigFile);
|
||||
}
|
||||
|
||||
QString VConfigManager::getThemeFile() const
|
||||
{
|
||||
auto it = m_themes.find(m_theme);
|
||||
|
@ -449,6 +449,8 @@ public:
|
||||
|
||||
const QString &getSnippetConfigFilePath() const;
|
||||
|
||||
const QString getKeyboardLayoutConfigFilePath() const;
|
||||
|
||||
// Read all available templates files in c_templateConfigFolder.
|
||||
QVector<QString> getNoteTemplates(DocType p_type = DocType::Unknown) const;
|
||||
|
||||
@ -565,11 +567,14 @@ public:
|
||||
int getSmartLivePreview() const;
|
||||
void setSmartLivePreview(int p_preview);
|
||||
|
||||
bool getMultipleKeyboardLayout() const;
|
||||
|
||||
bool getInsertNewNoteInFront() const;
|
||||
void setInsertNewNoteInFront(bool p_enabled);
|
||||
|
||||
QString getKeyboardLayout() const;
|
||||
void setKeyboardLayout(const QString &p_name);
|
||||
|
||||
QList<int> getKeyboardLayoutMappingKeys() const;
|
||||
|
||||
private:
|
||||
// Look up a config from user and default settings.
|
||||
QVariant getConfigFromSettings(const QString §ion, const QString &key) const;
|
||||
@ -1019,9 +1024,6 @@ private:
|
||||
// Smart live preview.
|
||||
int m_smartLivePreview;
|
||||
|
||||
// Support multiple keyboard layout.
|
||||
bool m_multipleKeyboardLayout;
|
||||
|
||||
// Whether insert new note in front.
|
||||
bool m_insertNewNoteInFront;
|
||||
|
||||
@ -1040,6 +1042,9 @@ private:
|
||||
// The name of the config file for snippets folder.
|
||||
static const QString c_snippetConfigFile;
|
||||
|
||||
// The name of the config file for keyboard layouts.
|
||||
static const QString c_keyboardLayoutConfigFile;
|
||||
|
||||
// QSettings for the user configuration
|
||||
QSettings *userSettings;
|
||||
|
||||
@ -2613,11 +2618,6 @@ inline void VConfigManager::setSmartLivePreview(int p_preview)
|
||||
setConfigToSettings("global", "smart_live_preview", m_smartLivePreview);
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getMultipleKeyboardLayout() const
|
||||
{
|
||||
return m_multipleKeyboardLayout;
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getInsertNewNoteInFront() const
|
||||
{
|
||||
return m_insertNewNoteInFront;
|
||||
@ -2657,4 +2657,31 @@ inline void VConfigManager::setHighlightMatchesInPage(bool p_enabled)
|
||||
m_highlightMatchesInPage = p_enabled;
|
||||
setConfigToSettings("global", "highlight_matches_in_page", m_highlightMatchesInPage);
|
||||
}
|
||||
|
||||
inline QString VConfigManager::getKeyboardLayout() const
|
||||
{
|
||||
return getConfigFromSettings("global", "keyboard_layout").toString();
|
||||
}
|
||||
|
||||
inline void VConfigManager::setKeyboardLayout(const QString &p_name)
|
||||
{
|
||||
setConfigToSettings("global", "keyboard_layout", p_name);
|
||||
}
|
||||
|
||||
inline QList<int> VConfigManager::getKeyboardLayoutMappingKeys() const
|
||||
{
|
||||
QStringList keyStrs = getConfigFromSettings("global",
|
||||
"keyboard_layout_mapping_keys").toStringList();
|
||||
|
||||
QList<int> keys;
|
||||
for (auto & str : keyStrs) {
|
||||
bool ok;
|
||||
int tmp = str.toInt(&ok);
|
||||
if (ok) {
|
||||
keys.append(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
#endif // VCONFIGMANAGER_H
|
||||
|
@ -274,5 +274,7 @@
|
||||
<file>resources/export/export_template.html</file>
|
||||
<file>resources/export/outline.css</file>
|
||||
<file>resources/export/outline.js</file>
|
||||
<file>resources/icons/add.svg</file>
|
||||
<file>resources/icons/delete.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Loading…
x
Reference in New Issue
Block a user