From 8006988b2048586b125ecab2c4c1209bf36e9d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 12 Aug 2024 10:01:43 +0200 Subject: [PATCH] Start updating the settings tab for extension. --- CMakePresets.json | 2 +- src/CMakeLists.txt | 2 +- src/extensionmanager.cpp | 20 +++- src/extensionmanager.h | 7 ++ src/extensionsettings.cpp | 48 ++++++++- src/extensionsettings.h | 40 ++++++++ src/instancemanager.cpp | 2 +- src/moapplication.cpp | 2 +- src/nxmaccessmanager.cpp | 8 +- src/organizer_en.ts | 76 ++++++++------- src/pluginmanager.cpp | 32 ++---- src/pluginmanager.h | 5 - src/settings.cpp | 17 +++- src/settings.h | 4 + src/settingsdialogextensioninfo.cpp | 145 +++++++++++++++++++++++++++- src/settingsdialogextensioninfo.h | 24 +++++ src/settingsdialogextensioninfo.ui | 29 +----- src/settingsdialogextensions.cpp | 2 + src/texteditor.cpp | 2 +- src/translationmanager.cpp | 2 +- 20 files changed, 361 insertions(+), 108 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index eeeaaacd0..bda8b9afd 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -29,7 +29,7 @@ "value": "x64" }, "cacheVariables": { - "CMAKE_CXX_FLAGS": "/EHsc /MP /W4", + "CMAKE_CXX_FLAGS": "/EHsc /MP /W3", "VCPKG_TARGET_TRIPLET": { "type": "STRING", "value": "x64-windows-static-md" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e57081a8..e4f0cc1cb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,7 +25,7 @@ set_target_properties(organizer PROPERTIES # disable translations because we want to be able to install somewhere else if # required -mo2_configure_target(organizer WARNINGS 4 TRANSLATIONS OFF) +mo2_configure_target(organizer WARNINGS 3 TRANSLATIONS OFF) # we add translations "manually" to handle MO2_INSTALL_IS_BIN mo2_add_translations(organizer diff --git a/src/extensionmanager.cpp b/src/extensionmanager.cpp index 3df56f7dd..422bd0e6f 100644 --- a/src/extensionmanager.cpp +++ b/src/extensionmanager.cpp @@ -1,10 +1,14 @@ #include "extensionmanager.h" -#include +#include + +#include "organizercore.h" using namespace MOBase; namespace fs = std::filesystem; +ExtensionManager::ExtensionManager(OrganizerCore* core) : m_core{core} {} + void ExtensionManager::loadExtensions(fs::path const& directory) { for (const auto& entry : fs::directory_iterator{directory}) { @@ -60,8 +64,18 @@ const IExtension* ExtensionManager::extension(QString const& identifier) const bool ExtensionManager::isEnabled(MOBase::IExtension const& extension) const { - // TODO - return true; + if (!m_core) { + return true; + } + + for (auto& requirement : extension.metadata().requirements()) { + // TODO: needs an organizerproxy... + // if (!requirement.check(m_core)) { + // return false; + //} + } + + return m_core->settings().extensions().isEnabled(extension, true); } bool ExtensionManager::isEnabled(QString const& identifier) const diff --git a/src/extensionmanager.h b/src/extensionmanager.h index 3cef8d689..a3f7f0711 100644 --- a/src/extensionmanager.h +++ b/src/extensionmanager.h @@ -10,10 +10,15 @@ #include #include "extensionwatcher.h" +#include "organizerproxy.h" + +class OrganizerCore; class ExtensionManager { public: + ExtensionManager(OrganizerCore* core); + // retrieve the list of currently loaded extensions // const auto& extensions() const { return m_extensions; } @@ -58,6 +63,8 @@ class ExtensionManager void triggerWatchers(const MOBase::IExtension& extension) const; private: + OrganizerCore* m_core; + std::unique_ptr m_proxy; std::vector> m_extensions; using WatcherMap = boost::fusion::map< diff --git a/src/extensionsettings.cpp b/src/extensionsettings.cpp index 7e1a9dc8a..669a3d5a8 100644 --- a/src/extensionsettings.cpp +++ b/src/extensionsettings.cpp @@ -4,9 +4,55 @@ using namespace MOBase; +static const QString EXTENSIONS_GROUP = "Extensions"; +static const QString EXTENSIONS_ENABLED_GROUP = "ExtensionsEnabled"; static const QString PLUGINS_GROUP = "Plugins"; static const QString PLUGINS_PERSISTENT_GROUP = "PluginPersistance"; +ExtensionSettings::ExtensionSettings(QSettings& settings) : m_Settings(settings) {} + +QString ExtensionSettings::path(const IExtension& extension, const Setting& setting) +{ + QString path = extension.metadata().identifier(); + if (!setting.group().isEmpty()) { + path += "/" + setting.group(); + } + return path + "/" + setting.name(); +} + +bool ExtensionSettings::isEnabled(const MOBase::IExtension& extension, + bool defaultValue) const +{ + return get(m_Settings, EXTENSIONS_ENABLED_GROUP, + extension.metadata().identifier(), defaultValue); +} + +void ExtensionSettings::setEnabled(const MOBase::IExtension& extension, + bool enabled) const +{ + set(m_Settings, EXTENSIONS_ENABLED_GROUP, extension.metadata().identifier(), enabled); +} + +QVariant ExtensionSettings::setting(const IExtension& extension, + const Setting& setting) const +{ + return get(m_Settings, EXTENSIONS_GROUP, path(extension, setting), + setting.defaultValue()); +} + +void ExtensionSettings::setSetting(const IExtension& extension, const Setting& setting, + const QVariant& value) +{ + set(m_Settings, EXTENSIONS_GROUP, path(extension, setting), value); +} + +// commits all the settings to the ini +// +void ExtensionSettings::save() +{ + m_Settings.sync(); +} + PluginSettings::PluginSettings(QSettings& settings) : m_Settings(settings) {} QString PluginSettings::path(const QString& pluginName, const QString& key) @@ -57,7 +103,7 @@ void PluginSettings::fixPluginEnabledSetting(const IPlugin* plugin) QVariant PluginSettings::setting(const QString& pluginName, const QString& key, const QVariant& defaultValue) const { - return get(m_Settings, "Settings", path(pluginName, key), defaultValue); + return get(m_Settings, PLUGINS_GROUP, path(pluginName, key), defaultValue); } void PluginSettings::setSetting(const QString& pluginName, const QString& key, diff --git a/src/extensionsettings.h b/src/extensionsettings.h index 80caa9b91..ca91423b9 100644 --- a/src/extensionsettings.h +++ b/src/extensionsettings.h @@ -4,8 +4,48 @@ #include #include +#include #include +// settings about extensions +class ExtensionSettings : public QObject +{ + Q_OBJECT + +public: + ExtensionSettings(QSettings& settings); + + // check if the specified extension is enabled in the settings + // + bool isEnabled(const MOBase::IExtension& extension, bool defaultValue = true) const; + + // set the extension as enabled or disabled in the settings + // + void setEnabled(const MOBase::IExtension& extension, bool enabled) const; + + // returns the plugin setting for the given key + // + QVariant setting(const MOBase::IExtension& extension, + const MOBase::Setting& setting) const; + + // sets the plugin setting for the given key + // + void setSetting(const MOBase::IExtension& extension, const MOBase::Setting& setting, + const QVariant& value); + + // commits all the settings to the ini + // + void save(); + +private: + QSettings& m_Settings; + + // retrieve the path to the given setting + // + static QString path(const MOBase::IExtension& extension, + const MOBase::Setting& setting); +}; + // settings about plugins // class PluginSettings : public QObject diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp index 29640776a..ebdf939d7 100644 --- a/src/instancemanager.cpp +++ b/src/instancemanager.cpp @@ -704,7 +704,7 @@ std::unique_ptr selectInstance() // since there is no instance currently active, load plugins with a null // OrganizerCore; see PluginManager::initPlugin() NexusInterface ni(nullptr); - ExtensionManager ec; + ExtensionManager ec(nullptr); ec.loadExtensions(QDir(QCoreApplication::applicationDirPath() + "/extensions") .filesystemAbsolutePath()); diff --git a/src/moapplication.cpp b/src/moapplication.cpp index 18626ff9a..79994938d 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -215,7 +215,7 @@ int MOApplication::setup(MOMultiProcess& multiProcess, bool forceSelect) m_themes = std::make_unique(this); m_translations = std::make_unique(this); - m_extensions = std::make_unique(); + m_extensions = std::make_unique(m_core.get()); m_extensions->registerWatcher(*m_themes); m_extensions->registerWatcher(*m_translations); diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp index 3efdcda01..ade36e3ab 100644 --- a/src/nxmaccessmanager.cpp +++ b/src/nxmaccessmanager.cpp @@ -162,11 +162,9 @@ NexusSSOLogin::NexusSSOLogin() : m_keyReceived(false), m_active(false) onConnected(); }); - QObject::connect(&m_socket, - qOverload(&QWebSocket::error), - [&](auto&& e) { - onError(e); - }); + QObject::connect(&m_socket, &QWebSocket::errorOccurred, [&](auto&& e) { + onError(e); + }); QObject::connect(&m_socket, &QWebSocket::sslErrors, [&](auto&& errors) { onSslErrors(errors); diff --git a/src/organizer_en.ts b/src/organizer_en.ts index 1c3ac2859..410b22d52 100644 --- a/src/organizer_en.ts +++ b/src/organizer_en.ts @@ -1786,22 +1786,12 @@ Right now the only case I know of where this needs to be overwritten is for the - + Key - - Value - - - - - No plugin found. - - - - + Translation and theme extensions cannot be disabled. @@ -1822,6 +1812,24 @@ Right now the only case I know of where this needs to be overwritten is for the + + ExtensionSettingWidget + + + False + + + + + True + + + + + Edit + + + FileTree @@ -7382,94 +7390,94 @@ Destination: - + Connecting to Nexus... - + Waiting for Nexus... - + Opened Nexus in browser. - + Switch to your browser and accept the request. - + Finished. - + No answer from Nexus. - - + + A firewall might be blocking Mod Organizer. - + Nexus closed the connection. - + Cancelled. - + Failed to request %1 - - + + Cancelled - + Internal error - + HTTP code %1 - + Invalid JSON - + Bad response - + API key is empty - + SSL error - + Timed out @@ -7537,12 +7545,12 @@ This program is known to cause issues with Mod Organizer, such as freezing or bl - + Failed - + Failed to start the helper application: %1 diff --git a/src/pluginmanager.cpp b/src/pluginmanager.cpp index 882c84a86..48a6e09fe 100644 --- a/src/pluginmanager.cpp +++ b/src/pluginmanager.cpp @@ -73,7 +73,7 @@ PluginDetails::PluginDetails(PluginManager* manager, PluginExtension const& exte void PluginDetails::fetchRequirements() { - // m_requirements = m_plugin->requirements(); + m_requirements = m_plugin->requirements(); } std::vector PluginDetails::problems() const @@ -133,6 +133,11 @@ PluginManager::PluginManager(ExtensionManager const& manager, OrganizerCore* cor m_gameFeatures(std::make_unique(core, this)) { m_loaders = makeLoaders(); + + if (m_core) { + bf::at_key(m_plugins).push_back(m_core); + m_core->connectPlugins(this); + } } QStringList PluginManager::implementedInterfaces(IPlugin* plugin) const @@ -249,12 +254,7 @@ bool PluginManager::isEnabled(MOBase::IPlugin* plugin) const return plugin == m_core->managedGame(); } - // check the master of the group - const auto& d = details(plugin); - if (d.master() && d.master() != plugin) { - return isEnabled(d.master()); - } - + // TODO: allow disabling/enabling plugins alone? return m_extensions.isEnabled(details(plugin).extension()); } @@ -499,28 +499,12 @@ bool PluginManager::loadPlugins(const MOBase::PluginExtension& extension) continue; } - // find the best interface - auto it = std::min_element(std::begin(objectGroup), std::end(objectGroup), - [&](auto const& lhs, auto const& rhs) { - return isBetterInterface(lhs, rhs); - }); - IPlugin* master = qobject_cast(*it); - // register plugins in the group for (auto* object : objectGroup) { - IPlugin* plugin = registerPlugin(extension, object, objectGroup); - - if (plugin) { - m_details.at(plugin).m_master = master; - } + registerPlugin(extension, object, objectGroup); } } - // TODO: move this elsewhere, e.g., in core - if (m_core) { - bf::at_key(m_plugins).push_back(m_core); - m_core->connectPlugins(this); - } return true; } diff --git a/src/pluginmanager.h b/src/pluginmanager.h index 11c56f170..b51b6d229 100644 --- a/src/pluginmanager.h +++ b/src/pluginmanager.h @@ -48,10 +48,6 @@ class PluginDetails // const auto* proxy() const { return m_organizer; } - // the "master" of the group this plugin belongs to - // - MOBase::IPlugin* master() const { return m_master; } - // the extension containing this plugin // const MOBase::PluginExtension& extension() const { return *m_extension; } @@ -79,7 +75,6 @@ class PluginDetails PluginManager* m_manager; MOBase::IPlugin* m_plugin; const MOBase::PluginExtension* m_extension; - MOBase::IPlugin* m_master; std::vector> m_requirements; OrganizerProxy* m_organizer; diff --git a/src/settings.cpp b/src/settings.cpp index 84e32fea5..53b5bc96c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -64,9 +64,10 @@ Settings* Settings::s_Instance = nullptr; Settings::Settings(const QString& path, bool globalInstance) : m_Settings(path, QSettings::IniFormat), m_Game(m_Settings), m_Geometry(m_Settings), m_Widgets(m_Settings, globalInstance), - m_Colors(m_Settings), m_Plugins(m_Settings), m_Paths(m_Settings), - m_Network(m_Settings, globalInstance), m_Nexus(*this, m_Settings), - m_Steam(*this, m_Settings), m_Interface(m_Settings), m_Diagnostics(m_Settings) + m_Colors(m_Settings), m_Extensions(m_Settings), m_Plugins(m_Settings), + m_Paths(m_Settings), m_Network(m_Settings, globalInstance), + m_Nexus(*this, m_Settings), m_Steam(*this, m_Settings), m_Interface(m_Settings), + m_Diagnostics(m_Settings) { if (globalInstance) { if (s_Instance != nullptr) { @@ -457,6 +458,16 @@ const ColorSettings& Settings::colors() const return m_Colors; } +ExtensionSettings& Settings::extensions() +{ + return m_Extensions; +} + +const ExtensionSettings& Settings::extensions() const +{ + return m_Extensions; +} + PluginSettings& Settings::plugins() { return m_Plugins; diff --git a/src/settings.h b/src/settings.h index 68a281428..b0a01db1f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -768,6 +768,9 @@ class Settings : public QObject ColorSettings& colors(); const ColorSettings& colors() const; + ExtensionSettings& extensions(); + const ExtensionSettings& extensions() const; + PluginSettings& plugins(); const PluginSettings& plugins() const; @@ -818,6 +821,7 @@ public slots: GeometrySettings m_Geometry; WidgetSettings m_Widgets; ColorSettings m_Colors; + ExtensionSettings m_Extensions; PluginSettings m_Plugins; PathSettings m_Paths; NetworkSettings m_Network; diff --git a/src/settingsdialogextensioninfo.cpp b/src/settingsdialogextensioninfo.cpp index 9a98745e4..96dd33d4a 100644 --- a/src/settingsdialogextensioninfo.cpp +++ b/src/settingsdialogextensioninfo.cpp @@ -4,10 +4,99 @@ #include +#include + #include +#include "extensionmanager.h" +#include "pluginmanager.h" +#include "settings.h" + using namespace MOBase; +ExtensionSettingWidget::ExtensionSettingWidget(Setting const& setting, + QVariant const& value, QWidget* parent) + : QWidget(parent), m_value(value) +{ + setLayout(new QVBoxLayout()); + + { + auto* titleLabel = new QLabel(setting.title()); + auto font = titleLabel->font(); + font.setBold(true); + titleLabel->setFont(font); + layout()->addWidget(titleLabel); + } + + if (!setting.description().isEmpty()) { + auto* descriptionLabel = new QLabel(setting.description()); + auto font = descriptionLabel->font(); + font.setItalic(true); + font.setPointSize(static_cast(font.pointSize() * 0.85)); + descriptionLabel->setFont(font); + layout()->addWidget(descriptionLabel); + } + + { + QWidget* valueWidget = nullptr; + switch (setting.defaultValue().typeId()) { + case QMetaType::Bool: { + auto* comboBox = new QComboBox(); + comboBox->addItems({tr("False"), tr("True")}); + comboBox->setCurrentIndex(value.toBool()); + valueWidget = comboBox; + } break; + case QMetaType::QString: { + auto* lineEdit = new QLineEdit(value.toString()); + valueWidget = lineEdit; + } break; + case QMetaType::Float: + case QMetaType::Double: { + auto* lineEdit = new QLineEdit(QString::number(value.toInt())); + lineEdit->setValidator(new QDoubleValidator(lineEdit)); + valueWidget = lineEdit; + } break; + case QMetaType::Int: + case QMetaType::LongLong: + case QMetaType::UInt: + case QMetaType::ULongLong: { + auto* lineEdit = new QLineEdit(QString::number(value.toInt())); + lineEdit->setValidator(new QIntValidator(lineEdit)); + valueWidget = lineEdit; + } break; + case QMetaType::QColor: { + valueWidget = new QWidget(this); + auto* layout = new QHBoxLayout(); + valueWidget->setLayout(layout); + + const auto color = m_value.value(); + auto* textWidget = new QLabel(color.name()); + auto* colorWidget = new QLabel(""); + colorWidget->setStyleSheet( + QString("QLabel { background-color: %1; }").arg(color.name())); + auto* button = new QPushButton(tr("Edit")); + connect(button, &QPushButton::clicked, [textWidget, colorWidget, this]() { + const auto newColor = QColorDialog::getColor(m_value.value()); + if (newColor.isValid()) { + m_value = newColor; + textWidget->setText(newColor.name()); + colorWidget->setStyleSheet( + QString("QLabel { background-color: %1; }").arg(newColor.name())); + } + }); + + layout->addWidget(textWidget); + layout->addWidget(colorWidget, 1); + layout->addWidget(button); + } break; + } + + if (valueWidget) { + layout()->addWidget(valueWidget); + } + } +} + ExtensionListInfoWidget::ExtensionListInfoWidget(QWidget* parent) : QWidget(parent), ui{new Ui::ExtensionListInfoWidget()} { @@ -15,12 +104,30 @@ ExtensionListInfoWidget::ExtensionListInfoWidget(QWidget* parent) ui->authorLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); ui->authorLabel->setOpenExternalLinks(true); + + ui->pluginSettingsList->setRootIsDecorated(true); + ui->pluginSettingsList->setSelectionMode(QAbstractItemView::NoSelection); + ui->pluginSettingsList->setItemsExpandable(true); + ui->pluginSettingsList->setColumnCount(1); + ui->pluginSettingsList->header()->setSectionResizeMode( + 0, QHeaderView::ResizeMode::Stretch); +} + +void ExtensionListInfoWidget::setup(Settings& settings, + ExtensionManager& extensionManager, + PluginManager& pluginManager) +{ + m_settings = &settings; + m_extensionManager = &extensionManager; + m_pluginManager = &pluginManager; } void ExtensionListInfoWidget::setExtension(const IExtension& extension) { m_extension = &extension; + // update the header for the extension + const auto& metadata = m_extension->metadata(); const auto& author = metadata.author(); @@ -40,9 +147,43 @@ void ExtensionListInfoWidget::setExtension(const IExtension& extension) ui->enabledCheckbox->setToolTip( tr("Translation and theme extensions cannot be disabled.")); } else { - // TODO: - // ui->enabledCheckbox->setChecked(); + ui->enabledCheckbox->setChecked(m_extensionManager->isEnabled(extension)); ui->enabledCheckbox->setEnabled(true); ui->enabledCheckbox->setToolTip(QString()); } + + ui->pluginSettingsList->clear(); + + // update the list of settings + if (const auto* pluginExtension = dynamic_cast(m_extension)) { + + // TODO: refactor code somewhere to have direct access of the plugins for a given + // extension + for (auto& plugin : m_pluginManager->plugins()) { + if (&m_pluginManager->details(plugin).extension() != m_extension) { + continue; + } + + const auto settings = plugin->settings(); + if (settings.isEmpty()) { + continue; + } + + QTreeWidgetItem* pluginItem = new QTreeWidgetItem({plugin->localizedName()}); + ui->pluginSettingsList->addTopLevelItem(pluginItem); + + for (auto& setting : settings) { + auto* settingItem = new QTreeWidgetItem(); + auto* settingWidget = new ExtensionSettingWidget( + setting, m_settings->plugins().setting(plugin->name(), setting.name(), + setting.defaultValue())); + pluginItem->addChild(settingItem); + ui->pluginSettingsList->setItemWidget(settingItem, 0, settingWidget); + settingItem->setSizeHint(0, settingWidget->sizeHint()); + } + + pluginItem->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); + pluginItem->setExpanded(true); + } + } } diff --git a/src/settingsdialogextensioninfo.h b/src/settingsdialogextensioninfo.h index 3c013a9f3..0a134a4fb 100644 --- a/src/settingsdialogextensioninfo.h +++ b/src/settingsdialogextensioninfo.h @@ -10,11 +10,31 @@ namespace Ui class ExtensionListInfoWidget; } +class ExtensionManager; +class PluginManager; +class Settings; + +class ExtensionSettingWidget : public QWidget +{ + Q_OBJECT +public: + ExtensionSettingWidget(MOBase::Setting const& setting, QVariant const& value, + QWidget* parent = nullptr); + +private: + QVariant m_value; +}; + class ExtensionListInfoWidget : public QWidget { public: ExtensionListInfoWidget(QWidget* parent = nullptr); + // setup the widget, should be called before any other functions + // + void setup(Settings& settings, ExtensionManager& extensionManager, + PluginManager& pluginManager); + // set the extension to display // void setExtension(const MOBase::IExtension& extension); @@ -22,6 +42,10 @@ class ExtensionListInfoWidget : public QWidget private: Ui::ExtensionListInfoWidget* ui; + Settings* m_settings; + ExtensionManager* m_extensionManager; + PluginManager* m_pluginManager; + // currently displayed extension (default to nullptr) const MOBase::IExtension* m_extension{nullptr}; }; diff --git a/src/settingsdialogextensioninfo.ui b/src/settingsdialogextensioninfo.ui index 3951e3037..ab479aa7e 100644 --- a/src/settingsdialogextensioninfo.ui +++ b/src/settingsdialogextensioninfo.ui @@ -101,41 +101,20 @@ 0 - - false - - - false + + true - - false + + 1 false - - 170 - Key - - - Value - - - - - - - - No plugin found. - - - Qt::AlignCenter - diff --git a/src/settingsdialogextensions.cpp b/src/settingsdialogextensions.cpp index 9a86e76f9..813f39917 100644 --- a/src/settingsdialogextensions.cpp +++ b/src/settingsdialogextensions.cpp @@ -17,6 +17,8 @@ ExtensionsSettingsTab::ExtensionsSettingsTab(Settings& s, : SettingsTab(s, d), m_extensionManager(&extensionManager), m_pluginManager(&pluginManager) { + ui->infoWidget->setup(s, extensionManager, pluginManager); + // TODO: use Qt system to sort extensions instead of sorting beforehand std::vector extensions; for (auto& extension : m_extensionManager->extensions()) { diff --git a/src/texteditor.cpp b/src/texteditor.cpp index 281a545d7..b618d8c26 100644 --- a/src/texteditor.cpp +++ b/src/texteditor.cpp @@ -464,7 +464,7 @@ TextEditorToolbar::TextEditorToolbar(TextEditor& editor) m_save = new QAction(QIcon(":/MO/gui/save"), QObject::tr("&Save"), &editor); m_save->setShortcutContext(Qt::WidgetWithChildrenShortcut); - m_save->setShortcut(Qt::CTRL + Qt::Key_S); + m_save->setShortcut(Qt::CTRL | Qt::Key_S); m_editor.addAction(m_save); m_wordWrap = diff --git a/src/translationmanager.cpp b/src/translationmanager.cpp index 339209417..1eeafe167 100644 --- a/src/translationmanager.cpp +++ b/src/translationmanager.cpp @@ -47,7 +47,7 @@ void TranslationManager::addOldFormatTranslations() QString languageString = QString("%1 (%2)") .arg(locale.nativeLanguageName()) - .arg(locale.nativeCountryName()); + .arg(locale.nativeTerritoryName()); if (locale.language() == QLocale::Chinese) { if (languageCode == "zh_TW") {