From d7f7c36bb3cf4496cb824901730fd8b1b3f42333 Mon Sep 17 00:00:00 2001 From: AT Date: Fri, 19 Jul 2024 14:28:54 -0400 Subject: [PATCH] Fix settings translations (#2690) Signed-off-by: Adam Treat --- gpt4all-chat/modellist.cpp | 40 ++-------- gpt4all-chat/modellist.h | 7 +- gpt4all-chat/mysettings.cpp | 8 +- gpt4all-chat/qml/ApplicationSettings.qml | 97 +++++++++++++++++++----- gpt4all-chat/server.cpp | 9 ++- 5 files changed, 98 insertions(+), 63 deletions(-) diff --git a/gpt4all-chat/modellist.cpp b/gpt4all-chat/modellist.cpp index f6f215d2..4333b99c 100644 --- a/gpt4all-chat/modellist.cpp +++ b/gpt4all-chat/modellist.cpp @@ -526,45 +526,17 @@ QString ModelList::incompleteDownloadPath(const QString &modelFile) return MySettings::globalInstance()->modelPath() + "incomplete-" + modelFile; } -const QList ModelList::exportModelList() const +const QList ModelList::selectableModelList() const { + // FIXME: This needs to be kept in sync with m_selectableModels so should probably be merged QMutexLocker locker(&m_mutex); QList infos; for (ModelInfo *info : m_models) - if (info->installed) + if (info->installed && !info->isEmbeddingModel) infos.append(*info); return infos; } -const QList ModelList::userDefaultModelList() const -{ - QMutexLocker locker(&m_mutex); - - const QString userDefaultModelName = MySettings::globalInstance()->userDefaultModel(); - QList models; - bool foundUserDefault = false; - for (ModelInfo *info : m_models) { - - // Only installed chat models are suitable as a default - if (!info->installed || info->isEmbeddingModel) - continue; - - if (info->id() == userDefaultModelName) { - foundUserDefault = true; - models.prepend(info->name()); - } else { - models.append(info->name()); - } - } - - const QString defaultId = "Application default"; - if (foundUserDefault) - models.append(defaultId); - else - models.prepend(defaultId); - return models; -} - ModelInfo ModelList::defaultModelInfo() const { QMutexLocker locker(&m_mutex); @@ -681,7 +653,7 @@ void ModelList::addModel(const QString &id) m_mutex.unlock(); endInsertRows(); - emit userDefaultModelListChanged(); + emit selectableModelListChanged(); } void ModelList::changeId(const QString &oldId, const QString &newId) @@ -1029,7 +1001,7 @@ void ModelList::updateData(const QString &id, const QVector m_installedModels->invalidate(); m_downloadableModels->invalidate(); - emit userDefaultModelListChanged(); + emit selectableModelListChanged(); } void ModelList::resortModel() @@ -1169,7 +1141,7 @@ void ModelList::removeInternal(const ModelInfo &model) delete info; } endRemoveRows(); - emit userDefaultModelListChanged(); + emit selectableModelListChanged(); MySettings::globalInstance()->eraseModel(model); } diff --git a/gpt4all-chat/modellist.h b/gpt4all-chat/modellist.h index c60a7067..88c00e70 100644 --- a/gpt4all-chat/modellist.h +++ b/gpt4all-chat/modellist.h @@ -265,7 +265,7 @@ class ModelList : public QAbstractListModel Q_PROPERTY(InstalledModels* installedModels READ installedModels NOTIFY installedModelsChanged) Q_PROPERTY(InstalledModels* selectableModels READ selectableModels NOTIFY selectableModelsChanged) Q_PROPERTY(DownloadableModels* downloadableModels READ downloadableModels NOTIFY downloadableModelsChanged) - Q_PROPERTY(QList userDefaultModelList READ userDefaultModelList NOTIFY userDefaultModelListChanged) + Q_PROPERTY(QList selectableModelList READ selectableModelList NOTIFY selectableModelListChanged) Q_PROPERTY(bool asyncModelRequestOngoing READ asyncModelRequestOngoing NOTIFY asyncModelRequestOngoingChanged) Q_PROPERTY(int discoverLimit READ discoverLimit WRITE setDiscoverLimit NOTIFY discoverLimitChanged) Q_PROPERTY(int discoverSortDirection READ discoverSortDirection WRITE setDiscoverSortDirection NOTIFY discoverSortDirectionChanged) @@ -408,8 +408,7 @@ public: void addModel(const QString &id); void changeId(const QString &oldId, const QString &newId); - const QList exportModelList() const; - const QList userDefaultModelList() const; + const QList selectableModelList() const; InstalledModels *installedModels() const { return m_installedModels; } InstalledModels *selectableModels() const { return m_selectableModels; } @@ -452,7 +451,7 @@ Q_SIGNALS: void installedModelsChanged(); void selectableModelsChanged(); void downloadableModelsChanged(); - void userDefaultModelListChanged(); + void selectableModelListChanged(); void asyncModelRequestOngoingChanged(); void discoverLimitChanged(); void discoverSortDirectionChanged(); diff --git a/gpt4all-chat/mysettings.cpp b/gpt4all-chat/mysettings.cpp index 3567b4d0..b29ec431 100644 --- a/gpt4all-chat/mysettings.cpp +++ b/gpt4all-chat/mysettings.cpp @@ -39,7 +39,7 @@ static const bool forceMetal = false; static const bool networkIsActive = false; static const bool networkUsageStatsActive = false; static const QString device = "Auto"; -static const QString languageAndLocale = "Default"; +static const QString languageAndLocale = "System Locale"; } // namespace defaults @@ -91,7 +91,7 @@ static QString defaultLocalModelsPath() static QStringList getDevices(bool skipKompute = false) { - QStringList deviceList { "Auto" }; + QStringList deviceList; #if defined(Q_OS_MAC) && defined(__aarch64__) deviceList << "Metal"; #else @@ -121,7 +121,7 @@ static QString getUiLanguage(const QString directory, const QString fileName) static QStringList getUiLanguages(const QString &modelPath) { - QStringList languageList( { QObject::tr("Default") } ); + QStringList languageList; // Add the language translations from model path files first which is used by translation developers // to load translations in progress without having to rebuild all of GPT4All from source @@ -627,7 +627,7 @@ void MySettings::setLanguageAndLocale(const QString &bcp47Name) // to either the default which is the system locale or the one explicitly set by the user previously. QLocale locale; const QString l = languageAndLocale(); - if (l == "Default") + if (l == "System Locale") locale = QLocale::system(); else locale = QLocale(l); diff --git a/gpt4all-chat/qml/ApplicationSettings.qml b/gpt4all-chat/qml/ApplicationSettings.qml index f7c6a0b8..118d9f49 100644 --- a/gpt4all-chat/qml/ApplicationSettings.qml +++ b/gpt4all-chat/qml/ApplicationSettings.qml @@ -179,23 +179,41 @@ MySettingsTab { Layout.maximumWidth: 200 Layout.fillWidth: false Layout.alignment: Qt.AlignRight - model: MySettings.uiLanguages - Accessible.name: fontLabel.text - Accessible.description: fontLabel.helpText + model: ListModel { + Component.onCompleted: { + for (var i = 0; i < MySettings.uiLanguages.length; ++i) + append({"text": MySettings.uiLanguages[i]}); + languageBox.updateModel(); + } + ListElement { text: qsTr("System Locale") } + } + + Accessible.name: languageLabel.text + Accessible.description: languageLabel.helpText function updateModel() { - languageBox.currentIndex = languageBox.indexOfValue(MySettings.languageAndLocale); + // This usage of 'System Locale' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (MySettings.languageAndLocale === "System Locale") + languageBox.currentIndex = 0 + else + languageBox.currentIndex = languageBox.indexOfValue(MySettings.languageAndLocale); } Component.onCompleted: { languageBox.updateModel() } onActivated: { - MySettings.languageAndLocale = languageBox.currentText + // This usage of 'System Locale' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (languageBox.currentIndex === 0) + MySettings.languageAndLocale = "System Locale"; + else + MySettings.languageAndLocale = languageBox.currentText; } } MySettingsLabel { id: deviceLabel text: qsTr("Device") - helpText: qsTr('The compute device used for text generation. "Auto" uses Vulkan or Metal.') + helpText: qsTr('The compute device used for text generation.') Layout.row: 5 Layout.column: 0 } @@ -207,11 +225,24 @@ MySettingsTab { Layout.maximumWidth: 400 Layout.fillWidth: false Layout.alignment: Qt.AlignRight - model: MySettings.deviceList + model: ListModel { + Component.onCompleted: { + for (var i = 0; i < MySettings.deviceList.length; ++i) + append({"text": MySettings.deviceList[i]}); + deviceBox.updateModel(); + } + ListElement { text: qsTr("Application default") } + } + Accessible.name: deviceLabel.text Accessible.description: deviceLabel.helpText function updateModel() { - deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device); + // This usage of 'Auto' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (MySettings.device === "Auto") + deviceBox.currentIndex = 0 + else + deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device); } Component.onCompleted: { deviceBox.updateModel(); @@ -223,7 +254,12 @@ MySettingsTab { } } onActivated: { - MySettings.device = deviceBox.currentText; + // This usage of 'Auto' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (deviceBox.currentIndex === 0) + MySettings.device = "Auto"; + else + MySettings.device = deviceBox.currentText; } } MySettingsLabel { @@ -234,29 +270,54 @@ MySettingsTab { Layout.column: 0 } MyComboBox { - id: comboBox + id: defaultModelBox Layout.row: 6 Layout.column: 2 Layout.minimumWidth: 400 Layout.maximumWidth: 400 Layout.alignment: Qt.AlignRight - model: ModelList.userDefaultModelList + model: ListModel { + id: defaultModelBoxModel + Component.onCompleted: { + defaultModelBox.rebuildModel() + } + } Accessible.name: defaultModelLabel.text Accessible.description: defaultModelLabel.helpText - function updateModel() { - comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel); + function rebuildModel() { + defaultModelBoxModel.clear(); + defaultModelBoxModel.append({"text": qsTr("Application default")}); + for (var i = 0; i < ModelList.selectableModelList.length; ++i) + defaultModelBoxModel.append({"text": ModelList.selectableModelList[i].name}); + defaultModelBox.updateModel(); } - Component.onCompleted: { - comboBox.updateModel() + function updateModel() { + // This usage of 'Application default' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (MySettings.userDefaultModel === "Application default") + defaultModelBox.currentIndex = 0 + else + defaultModelBox.currentIndex = defaultModelBox.indexOfValue(MySettings.userDefaultModel); + } + onActivated: { + // This usage of 'Application default' should not be translated + // FIXME: Make this refer to a string literal variable accessed by both QML and C++ + if (defaultModelBox.currentIndex === 0) + MySettings.userDefaultModel = "Application default"; + else + MySettings.userDefaultModel = defaultModelBox.currentText; } Connections { target: MySettings function onUserDefaultModelChanged() { - comboBox.updateModel() + defaultModelBox.updateModel() } } - onActivated: { - MySettings.userDefaultModel = comboBox.currentText + Connections { + target: ModelList + function onSelectableModelListChanged() { + defaultModelBox.rebuildModel() + } } } MySettingsLabel { diff --git a/gpt4all-chat/server.cpp b/gpt4all-chat/server.cpp index af11663a..c8485d93 100644 --- a/gpt4all-chat/server.cpp +++ b/gpt4all-chat/server.cpp @@ -97,11 +97,12 @@ void Server::start() if (!MySettings::globalInstance()->serverChat()) return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized); - const QList modelList = ModelList::globalInstance()->exportModelList(); + const QList modelList = ModelList::globalInstance()->selectableModelList(); QJsonObject root; root.insert("object", "list"); QJsonArray data; for (const ModelInfo &info : modelList) { + Q_ASSERT(info.installed); if (!info.installed) continue; data.append(modelToJson(info)); @@ -116,9 +117,10 @@ void Server::start() if (!MySettings::globalInstance()->serverChat()) return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized); - const QList modelList = ModelList::globalInstance()->exportModelList(); + const QList modelList = ModelList::globalInstance()->selectableModelList(); QJsonObject object; for (const ModelInfo &info : modelList) { + Q_ASSERT(info.installed); if (!info.installed) continue; @@ -232,8 +234,9 @@ QHttpServerResponse Server::handleCompletionRequest(const QHttpServerRequest &re const QString modelRequested = body["model"].toString(); ModelInfo modelInfo = ModelList::globalInstance()->defaultModelInfo(); - const QList modelList = ModelList::globalInstance()->exportModelList(); + const QList modelList = ModelList::globalInstance()->selectableModelList(); for (const ModelInfo &info : modelList) { + Q_ASSERT(info.installed); if (!info.installed) continue; if (modelRequested == info.name() || modelRequested == info.filename()) {