mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-05-28 03:10:28 -04:00
352 lines
12 KiB
C++
352 lines
12 KiB
C++
/*
|
|
* Copyright (C) 2024 Petr Mironychev
|
|
*
|
|
* This file is part of QodeAssist.
|
|
*
|
|
* QodeAssist is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* QodeAssist is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "GeneralSettings.hpp"
|
|
|
|
#include <coreplugin/dialogs/ioptionspage.h>
|
|
#include <coreplugin/icore.h>
|
|
#include <utils/layoutbuilder.h>
|
|
#include <utils/utilsicons.h>
|
|
#include <QInputDialog>
|
|
#include <QMessageBox>
|
|
#include <QTimer>
|
|
#include <QtWidgets/qboxlayout.h>
|
|
#include <QtWidgets/qcompleter.h>
|
|
#include <QtWidgets/qgroupbox.h>
|
|
#include <QtWidgets/qradiobutton.h>
|
|
#include <QtWidgets/qstackedwidget.h>
|
|
|
|
#include "Logger.hpp"
|
|
#include "SettingsConstants.hpp"
|
|
#include "SettingsDialog.hpp"
|
|
#include "SettingsTr.hpp"
|
|
#include "SettingsUtils.hpp"
|
|
#include "UpdateDialog.hpp"
|
|
|
|
namespace QodeAssist::Settings {
|
|
|
|
GeneralSettings &generalSettings()
|
|
{
|
|
static GeneralSettings settings;
|
|
return settings;
|
|
}
|
|
|
|
GeneralSettings::GeneralSettings()
|
|
{
|
|
setAutoApply(false);
|
|
|
|
setDisplayName(TrConstants::GENERAL);
|
|
|
|
enableQodeAssist.setSettingsKey(Constants::ENABLE_QODE_ASSIST);
|
|
enableQodeAssist.setLabelText(TrConstants::ENABLE_QODE_ASSIST);
|
|
enableQodeAssist.setDefaultValue(true);
|
|
|
|
enableLogging.setSettingsKey(Constants::ENABLE_LOGGING);
|
|
enableLogging.setLabelText(TrConstants::ENABLE_LOG);
|
|
enableLogging.setDefaultValue(false);
|
|
|
|
enableCheckUpdate.setSettingsKey(Constants::ENABLE_CHECK_UPDATE);
|
|
enableCheckUpdate.setLabelText(TrConstants::ENABLE_CHECK_UPDATE_ON_START);
|
|
enableCheckUpdate.setDefaultValue(true);
|
|
|
|
resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS;
|
|
checkUpdate.m_buttonText = TrConstants::CHECK_UPDATE;
|
|
|
|
initStringAspect(ccProvider, Constants::CC_PROVIDER, TrConstants::PROVIDER, "Ollama");
|
|
ccProvider.setReadOnly(true);
|
|
ccSelectProvider.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(ccModel, Constants::CC_MODEL, TrConstants::MODEL, "qwen2.5-coder:7b");
|
|
ccModel.setHistoryCompleter(Constants::CC_MODEL_HISTORY);
|
|
ccSelectModel.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(ccTemplate, Constants::CC_TEMPLATE, TrConstants::TEMPLATE, "Ollama Auto FIM");
|
|
ccTemplate.setReadOnly(true);
|
|
ccSelectTemplate.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(ccUrl, Constants::CC_URL, TrConstants::URL, "http://localhost:11434");
|
|
ccUrl.setHistoryCompleter(Constants::CC_URL_HISTORY);
|
|
ccSetUrl.m_buttonText = TrConstants::SELECT;
|
|
|
|
ccStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay);
|
|
ccStatus.setLabelText(TrConstants::STATUS);
|
|
ccStatus.setDefaultValue("");
|
|
ccTest.m_buttonText = TrConstants::TEST;
|
|
|
|
initStringAspect(caProvider, Constants::CA_PROVIDER, TrConstants::PROVIDER, "Ollama");
|
|
caProvider.setReadOnly(true);
|
|
caSelectProvider.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(caModel, Constants::CA_MODEL, TrConstants::MODEL, "qwen2.5-coder:7b");
|
|
caModel.setHistoryCompleter(Constants::CA_MODEL_HISTORY);
|
|
caSelectModel.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(caTemplate, Constants::CA_TEMPLATE, TrConstants::TEMPLATE, "Ollama Auto Chat");
|
|
caTemplate.setReadOnly(true);
|
|
|
|
caSelectTemplate.m_buttonText = TrConstants::SELECT;
|
|
|
|
initStringAspect(caUrl, Constants::CA_URL, TrConstants::URL, "http://localhost:11434");
|
|
caUrl.setHistoryCompleter(Constants::CA_URL_HISTORY);
|
|
caSetUrl.m_buttonText = TrConstants::SELECT;
|
|
|
|
caStatus.setDisplayStyle(Utils::StringAspect::LabelDisplay);
|
|
caStatus.setLabelText(TrConstants::STATUS);
|
|
caStatus.setDefaultValue("");
|
|
caTest.m_buttonText = TrConstants::TEST;
|
|
|
|
readSettings();
|
|
|
|
Logger::instance().setLoggingEnabled(enableLogging());
|
|
|
|
setupConnections();
|
|
|
|
setLayouter([this]() {
|
|
using namespace Layouting;
|
|
|
|
auto ccGrid = Grid{};
|
|
ccGrid.addRow({ccProvider, ccSelectProvider});
|
|
ccGrid.addRow({ccUrl, ccSetUrl});
|
|
ccGrid.addRow({ccModel, ccSelectModel});
|
|
ccGrid.addRow({ccTemplate, ccSelectTemplate});
|
|
|
|
auto caGrid = Grid{};
|
|
caGrid.addRow({caProvider, caSelectProvider});
|
|
caGrid.addRow({caUrl, caSetUrl});
|
|
caGrid.addRow({caModel, caSelectModel});
|
|
caGrid.addRow({caTemplate, caSelectTemplate});
|
|
|
|
auto ccGroup = Group{title(TrConstants::CODE_COMPLETION), ccGrid};
|
|
auto caGroup = Group{title(TrConstants::CHAT_ASSISTANT), caGrid};
|
|
|
|
auto rootLayout = Column{
|
|
Row{enableQodeAssist, Stretch{1}, Row{checkUpdate, resetToDefaults}},
|
|
Row{enableLogging, Stretch{1}},
|
|
Row{enableCheckUpdate, Stretch{1}},
|
|
Space{8},
|
|
ccGroup,
|
|
Space{8},
|
|
caGroup,
|
|
Stretch{1}};
|
|
|
|
return rootLayout;
|
|
});
|
|
}
|
|
|
|
void GeneralSettings::showSelectionDialog(const QStringList &data,
|
|
Utils::StringAspect &aspect,
|
|
const QString &title,
|
|
const QString &text)
|
|
{
|
|
if (data.isEmpty())
|
|
return;
|
|
|
|
bool ok;
|
|
QInputDialog dialog(Core::ICore::dialogParent());
|
|
dialog.setWindowTitle(title);
|
|
dialog.setLabelText(text);
|
|
dialog.setComboBoxItems(data);
|
|
dialog.setComboBoxEditable(false);
|
|
dialog.setFixedSize(400, 150);
|
|
|
|
if (dialog.exec() == QDialog::Accepted) {
|
|
QString result = dialog.textValue();
|
|
if (!result.isEmpty()) {
|
|
aspect.setValue(result);
|
|
writeSettings();
|
|
}
|
|
}
|
|
}
|
|
|
|
void GeneralSettings::showModelsNotFoundDialog(Utils::StringAspect &aspect)
|
|
{
|
|
SettingsDialog dialog(TrConstants::CONNECTION_ERROR);
|
|
dialog.addLabel(TrConstants::NO_MODELS_FOUND);
|
|
dialog.addLabel(TrConstants::CHECK_CONNECTION);
|
|
dialog.addSpacing();
|
|
|
|
ButtonAspect *providerButton = nullptr;
|
|
ButtonAspect *urlButton = nullptr;
|
|
|
|
if (&aspect == &ccModel) {
|
|
providerButton = &ccSelectProvider;
|
|
urlButton = &ccSetUrl;
|
|
} else if (&aspect == &caModel) {
|
|
providerButton = &caSelectProvider;
|
|
urlButton = &caSetUrl;
|
|
}
|
|
|
|
if (providerButton && urlButton) {
|
|
auto selectProviderBtn = new QPushButton(TrConstants::SELECT_PROVIDER);
|
|
auto selectUrlBtn = new QPushButton(TrConstants::SELECT_URL);
|
|
auto enterManuallyBtn = new QPushButton(TrConstants::ENTER_MODEL_MANUALLY);
|
|
|
|
connect(selectProviderBtn, &QPushButton::clicked, &dialog, [this, providerButton, &dialog]() {
|
|
dialog.close();
|
|
emit providerButton->clicked();
|
|
});
|
|
|
|
connect(selectUrlBtn, &QPushButton::clicked, &dialog, [this, urlButton, &dialog]() {
|
|
dialog.close();
|
|
emit urlButton->clicked();
|
|
});
|
|
|
|
connect(enterManuallyBtn, &QPushButton::clicked, &dialog, [this, &aspect, &dialog]() {
|
|
dialog.close();
|
|
showModelsNotSupportedDialog(aspect);
|
|
});
|
|
|
|
dialog.buttonLayout()->addWidget(selectProviderBtn);
|
|
dialog.buttonLayout()->addWidget(selectUrlBtn);
|
|
dialog.buttonLayout()->addWidget(enterManuallyBtn);
|
|
}
|
|
|
|
auto closeBtn = new QPushButton(TrConstants::CLOSE);
|
|
connect(closeBtn, &QPushButton::clicked, &dialog, &QDialog::close);
|
|
dialog.buttonLayout()->addWidget(closeBtn);
|
|
|
|
dialog.exec();
|
|
}
|
|
|
|
void GeneralSettings::showModelsNotSupportedDialog(Utils::StringAspect &aspect)
|
|
{
|
|
SettingsDialog dialog(TrConstants::MODEL_SELECTION);
|
|
dialog.addLabel(TrConstants::MODEL_LISTING_NOT_SUPPORTED_INFO);
|
|
dialog.addSpacing();
|
|
|
|
QString key = QString("CompleterHistory/")
|
|
.append(
|
|
(&aspect == &ccModel) ? Constants::CC_MODEL_HISTORY
|
|
: Constants::CA_MODEL_HISTORY);
|
|
QStringList historyList = qtcSettings()->value(Utils::Key(key.toLocal8Bit())).toStringList();
|
|
|
|
auto modelList = dialog.addComboBox(historyList, aspect.value());
|
|
dialog.addSpacing();
|
|
|
|
auto okButton = new QPushButton(TrConstants::OK);
|
|
connect(okButton, &QPushButton::clicked, &dialog, [this, &aspect, modelList, &dialog]() {
|
|
QString value = modelList->currentText().trimmed();
|
|
if (!value.isEmpty()) {
|
|
aspect.setValue(value);
|
|
writeSettings();
|
|
dialog.accept();
|
|
}
|
|
});
|
|
|
|
auto cancelButton = new QPushButton(TrConstants::CANCEL);
|
|
connect(cancelButton, &QPushButton::clicked, &dialog, &QDialog::reject);
|
|
|
|
dialog.buttonLayout()->addWidget(cancelButton);
|
|
dialog.buttonLayout()->addWidget(okButton);
|
|
|
|
modelList->setFocus();
|
|
dialog.exec();
|
|
}
|
|
|
|
void GeneralSettings::showUrlSelectionDialog(
|
|
Utils::StringAspect &aspect, const QStringList &predefinedUrls)
|
|
{
|
|
SettingsDialog dialog(TrConstants::URL_SELECTION);
|
|
dialog.addLabel(TrConstants::URL_SELECTION_INFO);
|
|
dialog.addSpacing();
|
|
|
|
QStringList allUrls = predefinedUrls;
|
|
QString key
|
|
= QString("CompleterHistory/")
|
|
.append((&aspect == &ccUrl) ? Constants::CC_URL_HISTORY : Constants::CA_URL_HISTORY);
|
|
QStringList historyList = qtcSettings()->value(Utils::Key(key.toLocal8Bit())).toStringList();
|
|
allUrls.append(historyList);
|
|
allUrls.removeDuplicates();
|
|
|
|
auto urlList = dialog.addComboBox(allUrls, aspect.value());
|
|
dialog.addSpacing();
|
|
|
|
auto okButton = new QPushButton(TrConstants::OK);
|
|
connect(okButton, &QPushButton::clicked, &dialog, [this, &aspect, urlList, &dialog]() {
|
|
QString value = urlList->currentText().trimmed();
|
|
if (!value.isEmpty()) {
|
|
aspect.setValue(value);
|
|
writeSettings();
|
|
dialog.accept();
|
|
}
|
|
});
|
|
|
|
auto cancelButton = new QPushButton(TrConstants::CANCEL);
|
|
connect(cancelButton, &QPushButton::clicked, &dialog, &QDialog::reject);
|
|
|
|
dialog.buttonLayout()->addWidget(cancelButton);
|
|
dialog.buttonLayout()->addWidget(okButton);
|
|
|
|
urlList->setFocus();
|
|
dialog.exec();
|
|
}
|
|
|
|
void GeneralSettings::setupConnections()
|
|
{
|
|
connect(&enableLogging, &Utils::BoolAspect::volatileValueChanged, this, [this]() {
|
|
Logger::instance().setLoggingEnabled(enableLogging.volatileValue());
|
|
});
|
|
connect(&resetToDefaults, &ButtonAspect::clicked, this, &GeneralSettings::resetPageToDefaults);
|
|
connect(&checkUpdate, &ButtonAspect::clicked, this, [this]() {
|
|
QodeAssist::UpdateDialog::checkForUpdatesAndShow(Core::ICore::dialogParent());
|
|
});
|
|
}
|
|
|
|
void GeneralSettings::resetPageToDefaults()
|
|
{
|
|
QMessageBox::StandardButton reply;
|
|
reply = QMessageBox::question(Core::ICore::dialogParent(),
|
|
TrConstants::RESET_SETTINGS,
|
|
TrConstants::CONFIRMATION,
|
|
QMessageBox::Yes | QMessageBox::No);
|
|
|
|
if (reply == QMessageBox::Yes) {
|
|
resetAspect(enableQodeAssist);
|
|
resetAspect(enableLogging);
|
|
resetAspect(ccProvider);
|
|
resetAspect(ccModel);
|
|
resetAspect(ccTemplate);
|
|
resetAspect(ccUrl);
|
|
resetAspect(caProvider);
|
|
resetAspect(caModel);
|
|
resetAspect(caTemplate);
|
|
resetAspect(caUrl);
|
|
resetAspect(enableCheckUpdate);
|
|
writeSettings();
|
|
}
|
|
}
|
|
|
|
class GeneralSettingsPage : public Core::IOptionsPage
|
|
{
|
|
public:
|
|
GeneralSettingsPage()
|
|
{
|
|
setId(Constants::QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID);
|
|
setDisplayName(TrConstants::GENERAL);
|
|
setCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_CATEGORY);
|
|
setDisplayCategory(Constants::QODE_ASSIST_GENERAL_OPTIONS_DISPLAY_CATEGORY);
|
|
setCategoryIconPath(":/resources/images/qoderassist-icon.png");
|
|
setSettingsProvider([] { return &generalSettings(); });
|
|
}
|
|
};
|
|
|
|
const GeneralSettingsPage generalSettingsPage;
|
|
|
|
} // namespace QodeAssist::Settings
|