Skip to content

Commit

Permalink
#3026 add: AI model selector in main menu
Browse files Browse the repository at this point in the history
  • Loading branch information
pbek committed May 23, 2024
1 parent bbef099 commit b6080a1
Show file tree
Hide file tree
Showing 8 changed files with 515 additions and 461 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# QOwnNotes Changelog

## 24.5.8
- You can now also select an AI model to use in the *Edit* main menu, instead of
only in the AI toolbar (for [#3026](https://github.com/pbek/QOwnNotes/issues/3026))

## 24.5.7
- There now is a new scripting command `script.inputDialogGetMultiLineText` to open an
input dialog with a multi-line text edit
Expand Down
849 changes: 422 additions & 427 deletions src/languages/QOwnNotes_en.ts

Large diffs are not rendered by default.

82 changes: 60 additions & 22 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,6 @@ void MainWindow::initToolbars() {
_encryptionToolbar->setObjectName(QStringLiteral("encryptionToolbar"));
addToolBar(_encryptionToolbar);

_aiBackendGroup = new QActionGroup(ui->menuAI_backend);
_aiModelGroup = new QActionGroup(ui->menuAI_model);

_aiToolbar = new QToolBar(tr("AI toolbar"), this);
Expand Down Expand Up @@ -2465,10 +2464,6 @@ void MainWindow::readSettings() {
}

loadNoteBookmarks();

// TODO: Enable AI menu, when done
ui->menuAI_backend->setEnabled(false);
ui->menuAI_model->setEnabled(false);
buildAiToolbarAndActions();
}

Expand Down Expand Up @@ -10335,6 +10330,7 @@ void MainWindow::onAiBackendComboBoxCurrentIndexChanged(int index) {

if (OpenAiService::instance()->setBackendId(backendId)) {
generateAiModelComboBox();
aiModelMainMenuSetCurrentItem();
}
}

Expand All @@ -10346,8 +10342,8 @@ void MainWindow::generateAiBackendComboBox() {
_aiBackendComboBox->clear();
auto backendNames = OpenAiService::instance()->getBackendNames();

for (const auto& key : backendNames.keys()) {
const QString&name = backendNames.value(key);
for (const auto &key : backendNames.keys()) {
const QString &name = backendNames.value(key);
_aiBackendComboBox->addItem(name, key);
}

Expand All @@ -10357,21 +10353,48 @@ void MainWindow::generateAiBackendComboBox() {
}

/**
* Puts items into the AI backend main menu group
* TODO: Implement MainWindow::generateAiBackendMainMenuGroup
* Puts items into the AI model main menu
*/
void MainWindow::generateAiBackendMainMenuGroup() {
// _aiBackendGroup->clear();
auto backendNames = OpenAiService::instance()->getBackendNames();
void MainWindow::generateAiModelMainMenu() {
QMap<QString, QString> backendNames = OpenAiService::instance()->getBackendNames();
_aiModelGroup->setExclusive(true);

for (const auto &backendId : backendNames.keys()) {
const QString &backendName = backendNames.value(backendId);

for (const auto& key : backendNames.keys()) {
const QString&name = backendNames.value(key);
// _aiBackendGroup->addItem(name, key);
// Create a submenu for the backend models
auto *modelSubMenu = new QMenu(backendName, ui->menuAI_model);

// Retrieve models for the current backend
QStringList models = OpenAiService::instance()->getModelsForBackend(backendId);

// Add each model as an action to the submenu
for (const QString &modelId : models) {
auto *modelAction = new QAction(modelId, modelSubMenu);
modelAction->setData(QStringList() << backendId << modelId);
modelSubMenu->addAction(modelAction);
modelAction->setActionGroup(_aiModelGroup);
modelAction->setCheckable(true);
}

// Add the submenu to the main menu
ui->menuAI_model->addMenu(modelSubMenu);
}

// Utils::Gui::setComboBoxIndexByUserData(_aiBackendComboBox,
// OpenAiService::instance()->getBackendId());
// _aiBackendComboBox->blockSignals(false);
connect(_aiModelGroup, &QActionGroup::triggered, this, &MainWindow::onAiModelGroupChanged);
}

void MainWindow::aiModelMainMenuSetCurrentItem() {
auto currentBackendId = OpenAiService::instance()->getBackendId();
auto currentModelId = OpenAiService::instance()->getModelId();
auto action = Utils::Gui::findActionByData(ui->menuAI_model,
QStringList() << currentBackendId << currentModelId);

if (action) {
_aiModelGroup->blockSignals(true);
action->setChecked(true);
_aiModelGroup->blockSignals(false);
}
}

/**
Expand All @@ -10382,6 +10405,21 @@ void MainWindow::onAiModelComboBoxCurrentIndexChanged(int index) {

const QString modelId = _aiModelComboBox->currentData().toString();

if (OpenAiService::instance()->setModelId(modelId)) {
generateAiModelComboBox();
aiModelMainMenuSetCurrentItem();
}
}

void MainWindow::onAiModelGroupChanged(QAction *action) {
const auto data = action->data().toStringList();
const auto &backendId = data[0];
const auto &modelId = data[1];

if (OpenAiService::instance()->setBackendId(backendId)) {
generateAiBackendComboBox();
}

if (OpenAiService::instance()->setModelId(modelId)) {
generateAiModelComboBox();
}
Expand Down Expand Up @@ -11565,7 +11603,7 @@ void MainWindow::loadSpellingBackends() {
settings.value(QStringLiteral("spellCheckBackend"), QStringLiteral("Hunspell")).toString();

_spellBackendGroup->setExclusive(true);
connect(_spellBackendGroup, &QActionGroup::triggered, this, &MainWindow::onBackendChanged);
connect(_spellBackendGroup, &QActionGroup::triggered, this, &MainWindow::onSpellBackendChanged);

QAction *hs = ui->menuSpelling_backend->addAction(QStringLiteral("Hunspell"));
hs->setCheckable(true);
Expand All @@ -11583,7 +11621,7 @@ void MainWindow::loadSpellingBackends() {
}
}

void MainWindow::onBackendChanged(QAction *action) {
void MainWindow::onSpellBackendChanged(QAction *action) {
QString backend = action->data().toString();
QSettings settings;
settings.setValue(QStringLiteral("spellCheckBackend"), backend);
Expand Down Expand Up @@ -11949,8 +11987,8 @@ void MainWindow::buildAiToolbarAndActions() {
aiModelWidgetAction->setText(tr("AI model selector"));
_aiToolbar->addAction(aiModelWidgetAction);


// _aiBackendGroup
generateAiModelMainMenu();
aiModelMainMenuSetCurrentItem();
}

void MainWindow::on_actionEnable_AI_toggled(bool arg1) {
Expand Down
8 changes: 5 additions & 3 deletions src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@ class MainWindow : public QMainWindow {

void onAiModelComboBoxCurrentIndexChanged(int index);

void onAiModelGroupChanged(QAction *action);

void on_actionRemove_current_workspace_triggered();

void on_actionRename_current_workspace_triggered();
Expand Down Expand Up @@ -652,7 +654,7 @@ class MainWindow : public QMainWindow {

void onLanguageChanged(QAction *action);

void onBackendChanged(QAction *action);
void onSpellBackendChanged(QAction *action);

void on_actionManage_dictionaries_triggered();

Expand Down Expand Up @@ -833,7 +835,6 @@ class MainWindow : public QMainWindow {
WebAppClientService *_webAppClientService;
QActionGroup *_languageGroup;
QActionGroup *_spellBackendGroup;
QActionGroup *_aiBackendGroup;
QActionGroup *_aiModelGroup;
bool _brokenTagNoteLinksRemoved = false;

Expand Down Expand Up @@ -1129,5 +1130,6 @@ class MainWindow : public QMainWindow {
void buildAiToolbarAndActions();
void generateAiBackendComboBox();
void generateAiModelComboBox();
void generateAiBackendMainMenuGroup();
void generateAiModelMainMenu();
void aiModelMainMenuSetCurrentItem();
};
6 changes: 0 additions & 6 deletions src/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1119,11 +1119,6 @@ li.checked::marker { content: &quot;\2612&quot;; }
<string>Spelling backend</string>
</property>
</widget>
<widget class="QMenu" name="menuAI_backend">
<property name="title">
<string>AI backend</string>
</property>
</widget>
<widget class="QMenu" name="menuAI_model">
<property name="title">
<string>AI model</string>
Expand Down Expand Up @@ -1152,7 +1147,6 @@ li.checked::marker { content: &quot;\2612&quot;; }
<addaction name="actionManage_dictionaries"/>
<addaction name="separator"/>
<addaction name="actionEnable_AI"/>
<addaction name="menuAI_backend"/>
<addaction name="menuAI_model"/>
</widget>
<widget class="QMenu" name="menuTodo">
Expand Down
4 changes: 1 addition & 3 deletions src/services/openaiservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ QStringList OpenAiService::getModelsForCurrentBackend() {
return getModelsForBackend(getBackendId());
}

QMap<QString, QString> OpenAiService::getBackendNames() {
return _backendNames;
}
QMap<QString, QString> OpenAiService::getBackendNames() { return _backendNames; }

QString OpenAiService::getApiBaseUrlForCurrentBackend() {
auto backendId = getBackendId();
Expand Down
21 changes: 21 additions & 0 deletions src/utils/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1228,3 +1228,24 @@ void Utils::Gui::fixDarkModeIcons(QWidget *widget) {
}
}
}

QAction *Utils::Gui::findActionByData(QMenu *menu, const QVariant &data) {
// Iterate through all actions in the menu
for (QAction *action : menu->actions()) {
// Check if the action's data matches the desired data
if (action->data() == data) {
return action;
}

// Check if the action is a submenu
if (QMenu *subMenu = action->menu()) {
// Recursively search in the submenu
QAction *foundAction = findActionByData(subMenu, data);
if (foundAction) {
return foundAction;
}
}
}
// Return nullptr if no matching action is found
return nullptr;
}
2 changes: 2 additions & 0 deletions src/utils/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <QFontDialog>
#include <QMessageBox>
#include <QtWidgets/QMenu>

class QTreeWidgetItem;
class QTreeWidget;
Expand Down Expand Up @@ -153,5 +154,6 @@ void handleTreeWidgetItemTagColor(QTreeWidgetItem *item, const Tag &tag);
void handleTreeWidgetItemTagColor(QTreeWidgetItem *item, int tag);
bool enableDockWidgetQuestion(QDockWidget *dockWidget);
void fixDarkModeIcons(QWidget *widget);
QAction *findActionByData(QMenu *menu, const QVariant &data);
} // namespace Gui
} // namespace Utils

0 comments on commit b6080a1

Please sign in to comment.