Fix settings translations (#2690)

Signed-off-by: Adam Treat <treat.adam@gmail.com>
This commit is contained in:
AT 2024-07-19 14:28:54 -04:00 committed by GitHub
parent 56d5a23001
commit d7f7c36bb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 98 additions and 63 deletions

View File

@ -526,45 +526,17 @@ QString ModelList::incompleteDownloadPath(const QString &modelFile)
return MySettings::globalInstance()->modelPath() + "incomplete-" + modelFile; return MySettings::globalInstance()->modelPath() + "incomplete-" + modelFile;
} }
const QList<ModelInfo> ModelList::exportModelList() const const QList<ModelInfo> ModelList::selectableModelList() const
{ {
// FIXME: This needs to be kept in sync with m_selectableModels so should probably be merged
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
QList<ModelInfo> infos; QList<ModelInfo> infos;
for (ModelInfo *info : m_models) for (ModelInfo *info : m_models)
if (info->installed) if (info->installed && !info->isEmbeddingModel)
infos.append(*info); infos.append(*info);
return infos; return infos;
} }
const QList<QString> ModelList::userDefaultModelList() const
{
QMutexLocker locker(&m_mutex);
const QString userDefaultModelName = MySettings::globalInstance()->userDefaultModel();
QList<QString> 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 ModelInfo ModelList::defaultModelInfo() const
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
@ -681,7 +653,7 @@ void ModelList::addModel(const QString &id)
m_mutex.unlock(); m_mutex.unlock();
endInsertRows(); endInsertRows();
emit userDefaultModelListChanged(); emit selectableModelListChanged();
} }
void ModelList::changeId(const QString &oldId, const QString &newId) void ModelList::changeId(const QString &oldId, const QString &newId)
@ -1029,7 +1001,7 @@ void ModelList::updateData(const QString &id, const QVector<QPair<int, QVariant>
m_installedModels->invalidate(); m_installedModels->invalidate();
m_downloadableModels->invalidate(); m_downloadableModels->invalidate();
emit userDefaultModelListChanged(); emit selectableModelListChanged();
} }
void ModelList::resortModel() void ModelList::resortModel()
@ -1169,7 +1141,7 @@ void ModelList::removeInternal(const ModelInfo &model)
delete info; delete info;
} }
endRemoveRows(); endRemoveRows();
emit userDefaultModelListChanged(); emit selectableModelListChanged();
MySettings::globalInstance()->eraseModel(model); MySettings::globalInstance()->eraseModel(model);
} }

View File

@ -265,7 +265,7 @@ class ModelList : public QAbstractListModel
Q_PROPERTY(InstalledModels* installedModels READ installedModels NOTIFY installedModelsChanged) Q_PROPERTY(InstalledModels* installedModels READ installedModels NOTIFY installedModelsChanged)
Q_PROPERTY(InstalledModels* selectableModels READ selectableModels NOTIFY selectableModelsChanged) Q_PROPERTY(InstalledModels* selectableModels READ selectableModels NOTIFY selectableModelsChanged)
Q_PROPERTY(DownloadableModels* downloadableModels READ downloadableModels NOTIFY downloadableModelsChanged) Q_PROPERTY(DownloadableModels* downloadableModels READ downloadableModels NOTIFY downloadableModelsChanged)
Q_PROPERTY(QList<QString> userDefaultModelList READ userDefaultModelList NOTIFY userDefaultModelListChanged) Q_PROPERTY(QList<ModelInfo> selectableModelList READ selectableModelList NOTIFY selectableModelListChanged)
Q_PROPERTY(bool asyncModelRequestOngoing READ asyncModelRequestOngoing NOTIFY asyncModelRequestOngoingChanged) Q_PROPERTY(bool asyncModelRequestOngoing READ asyncModelRequestOngoing NOTIFY asyncModelRequestOngoingChanged)
Q_PROPERTY(int discoverLimit READ discoverLimit WRITE setDiscoverLimit NOTIFY discoverLimitChanged) Q_PROPERTY(int discoverLimit READ discoverLimit WRITE setDiscoverLimit NOTIFY discoverLimitChanged)
Q_PROPERTY(int discoverSortDirection READ discoverSortDirection WRITE setDiscoverSortDirection NOTIFY discoverSortDirectionChanged) Q_PROPERTY(int discoverSortDirection READ discoverSortDirection WRITE setDiscoverSortDirection NOTIFY discoverSortDirectionChanged)
@ -408,8 +408,7 @@ public:
void addModel(const QString &id); void addModel(const QString &id);
void changeId(const QString &oldId, const QString &newId); void changeId(const QString &oldId, const QString &newId);
const QList<ModelInfo> exportModelList() const; const QList<ModelInfo> selectableModelList() const;
const QList<QString> userDefaultModelList() const;
InstalledModels *installedModels() const { return m_installedModels; } InstalledModels *installedModels() const { return m_installedModels; }
InstalledModels *selectableModels() const { return m_selectableModels; } InstalledModels *selectableModels() const { return m_selectableModels; }
@ -452,7 +451,7 @@ Q_SIGNALS:
void installedModelsChanged(); void installedModelsChanged();
void selectableModelsChanged(); void selectableModelsChanged();
void downloadableModelsChanged(); void downloadableModelsChanged();
void userDefaultModelListChanged(); void selectableModelListChanged();
void asyncModelRequestOngoingChanged(); void asyncModelRequestOngoingChanged();
void discoverLimitChanged(); void discoverLimitChanged();
void discoverSortDirectionChanged(); void discoverSortDirectionChanged();

View File

@ -39,7 +39,7 @@ static const bool forceMetal = false;
static const bool networkIsActive = false; static const bool networkIsActive = false;
static const bool networkUsageStatsActive = false; static const bool networkUsageStatsActive = false;
static const QString device = "Auto"; static const QString device = "Auto";
static const QString languageAndLocale = "Default"; static const QString languageAndLocale = "System Locale";
} // namespace defaults } // namespace defaults
@ -91,7 +91,7 @@ static QString defaultLocalModelsPath()
static QStringList getDevices(bool skipKompute = false) static QStringList getDevices(bool skipKompute = false)
{ {
QStringList deviceList { "Auto" }; QStringList deviceList;
#if defined(Q_OS_MAC) && defined(__aarch64__) #if defined(Q_OS_MAC) && defined(__aarch64__)
deviceList << "Metal"; deviceList << "Metal";
#else #else
@ -121,7 +121,7 @@ static QString getUiLanguage(const QString directory, const QString fileName)
static QStringList getUiLanguages(const QString &modelPath) 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 // 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 // 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. // to either the default which is the system locale or the one explicitly set by the user previously.
QLocale locale; QLocale locale;
const QString l = languageAndLocale(); const QString l = languageAndLocale();
if (l == "Default") if (l == "System Locale")
locale = QLocale::system(); locale = QLocale::system();
else else
locale = QLocale(l); locale = QLocale(l);

View File

@ -179,23 +179,41 @@ MySettingsTab {
Layout.maximumWidth: 200 Layout.maximumWidth: 200
Layout.fillWidth: false Layout.fillWidth: false
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
model: MySettings.uiLanguages model: ListModel {
Accessible.name: fontLabel.text Component.onCompleted: {
Accessible.description: fontLabel.helpText 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() { function updateModel() {
// 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); languageBox.currentIndex = languageBox.indexOfValue(MySettings.languageAndLocale);
} }
Component.onCompleted: { Component.onCompleted: {
languageBox.updateModel() languageBox.updateModel()
} }
onActivated: { 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 { MySettingsLabel {
id: deviceLabel id: deviceLabel
text: qsTr("Device") 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.row: 5
Layout.column: 0 Layout.column: 0
} }
@ -207,10 +225,23 @@ MySettingsTab {
Layout.maximumWidth: 400 Layout.maximumWidth: 400
Layout.fillWidth: false Layout.fillWidth: false
Layout.alignment: Qt.AlignRight 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.name: deviceLabel.text
Accessible.description: deviceLabel.helpText Accessible.description: deviceLabel.helpText
function updateModel() { function updateModel() {
// 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); deviceBox.currentIndex = deviceBox.indexOfValue(MySettings.device);
} }
Component.onCompleted: { Component.onCompleted: {
@ -223,6 +254,11 @@ MySettingsTab {
} }
} }
onActivated: { onActivated: {
// 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; MySettings.device = deviceBox.currentText;
} }
} }
@ -234,29 +270,54 @@ MySettingsTab {
Layout.column: 0 Layout.column: 0
} }
MyComboBox { MyComboBox {
id: comboBox id: defaultModelBox
Layout.row: 6 Layout.row: 6
Layout.column: 2 Layout.column: 2
Layout.minimumWidth: 400 Layout.minimumWidth: 400
Layout.maximumWidth: 400 Layout.maximumWidth: 400
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
model: ModelList.userDefaultModelList model: ListModel {
id: defaultModelBoxModel
Component.onCompleted: {
defaultModelBox.rebuildModel()
}
}
Accessible.name: defaultModelLabel.text Accessible.name: defaultModelLabel.text
Accessible.description: defaultModelLabel.helpText Accessible.description: defaultModelLabel.helpText
function updateModel() { function rebuildModel() {
comboBox.currentIndex = comboBox.indexOfValue(MySettings.userDefaultModel); 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: { function updateModel() {
comboBox.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 { Connections {
target: MySettings target: MySettings
function onUserDefaultModelChanged() { function onUserDefaultModelChanged() {
comboBox.updateModel() defaultModelBox.updateModel()
} }
} }
onActivated: { Connections {
MySettings.userDefaultModel = comboBox.currentText target: ModelList
function onSelectableModelListChanged() {
defaultModelBox.rebuildModel()
}
} }
} }
MySettingsLabel { MySettingsLabel {

View File

@ -97,11 +97,12 @@ void Server::start()
if (!MySettings::globalInstance()->serverChat()) if (!MySettings::globalInstance()->serverChat())
return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized); return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
const QList<ModelInfo> modelList = ModelList::globalInstance()->exportModelList(); const QList<ModelInfo> modelList = ModelList::globalInstance()->selectableModelList();
QJsonObject root; QJsonObject root;
root.insert("object", "list"); root.insert("object", "list");
QJsonArray data; QJsonArray data;
for (const ModelInfo &info : modelList) { for (const ModelInfo &info : modelList) {
Q_ASSERT(info.installed);
if (!info.installed) if (!info.installed)
continue; continue;
data.append(modelToJson(info)); data.append(modelToJson(info));
@ -116,9 +117,10 @@ void Server::start()
if (!MySettings::globalInstance()->serverChat()) if (!MySettings::globalInstance()->serverChat())
return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized); return QHttpServerResponse(QHttpServerResponder::StatusCode::Unauthorized);
const QList<ModelInfo> modelList = ModelList::globalInstance()->exportModelList(); const QList<ModelInfo> modelList = ModelList::globalInstance()->selectableModelList();
QJsonObject object; QJsonObject object;
for (const ModelInfo &info : modelList) { for (const ModelInfo &info : modelList) {
Q_ASSERT(info.installed);
if (!info.installed) if (!info.installed)
continue; continue;
@ -232,8 +234,9 @@ QHttpServerResponse Server::handleCompletionRequest(const QHttpServerRequest &re
const QString modelRequested = body["model"].toString(); const QString modelRequested = body["model"].toString();
ModelInfo modelInfo = ModelList::globalInstance()->defaultModelInfo(); ModelInfo modelInfo = ModelList::globalInstance()->defaultModelInfo();
const QList<ModelInfo> modelList = ModelList::globalInstance()->exportModelList(); const QList<ModelInfo> modelList = ModelList::globalInstance()->selectableModelList();
for (const ModelInfo &info : modelList) { for (const ModelInfo &info : modelList) {
Q_ASSERT(info.installed);
if (!info.installed) if (!info.installed)
continue; continue;
if (modelRequested == info.name() || modelRequested == info.filename()) { if (modelRequested == info.name() || modelRequested == info.filename()) {