mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-02-17 12:33:05 -05:00
feat: Add predefined templates
This commit is contained in:
26
README.md
26
README.md
@ -125,16 +125,30 @@ For more information, visit the [QodeAssistUpdater repository](https://github.co
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
QodeAssist supports multiple LLM providers. Choose your preferred provider and follow the configuration guide:
|
### Quick Setup (Recommended for Beginners)
|
||||||
|
|
||||||
### Supported Providers
|
The Quick Setup feature provides one-click configuration for popular cloud AI models. Get started in 3 easy steps:
|
||||||
|
|
||||||
|
1. **Open QodeAssist Settings**
|
||||||
|
2. **Select a Preset** - Choose from the Quick Setup dropdown:
|
||||||
|
- **Anthropic Claude** (Sonnet 4.5, Haiku 4.5, Opus 4.5)
|
||||||
|
- **OpenAI** (gpt-5.2-codex)
|
||||||
|
- **Mistral AI** (Codestral 2501)
|
||||||
|
- **Google AI** (Gemini 2.5 Flash)
|
||||||
|
3. **Configure API Key** - Click "Configure API Key" button and enter your API key in Provider Settings
|
||||||
|
|
||||||
|
All settings (provider, model, template, URL) are configured automatically. Just add your API key and you're ready to go!
|
||||||
|
|
||||||
|
### Manual Provider Configuration
|
||||||
|
|
||||||
|
For advanced users or local models, choose your preferred provider and follow the detailed configuration guide:
|
||||||
|
|
||||||
- **[Ollama](docs/ollama-configuration.md)** - Local LLM provider
|
- **[Ollama](docs/ollama-configuration.md)** - Local LLM provider
|
||||||
- **[llama.cpp](docs/llamacpp-configuration.md)** - Local LLM server
|
- **[llama.cpp](docs/llamacpp-configuration.md)** - Local LLM server
|
||||||
- **[Anthropic Claude](docs/claude-configuration.md)** - Сloud provider
|
- **[Anthropic Claude](docs/claude-configuration.md)** - Cloud provider (manual setup)
|
||||||
- **[OpenAI](docs/openai-configuration.md)** - Сloud provider (includes Responses API support)
|
- **[OpenAI](docs/openai-configuration.md)** - Cloud provider (includes Responses API support)
|
||||||
- **[Mistral AI](docs/mistral-configuration.md)** - Сloud provider
|
- **[Mistral AI](docs/mistral-configuration.md)** - Cloud provider
|
||||||
- **[Google AI](docs/google-ai-configuration.md)** - Сloud provider
|
- **[Google AI](docs/google-ai-configuration.md)** - Cloud provider
|
||||||
- **LM Studio** - Local LLM provider
|
- **LM Studio** - Local LLM provider
|
||||||
- **OpenAI-compatible** - Custom providers (OpenRouter, etc.)
|
- **OpenAI-compatible** - Custom providers (OpenRouter, etc.)
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,93 @@ ConfigurationManager &ConfigurationManager::instance()
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<AIConfiguration> ConfigurationManager::getPredefinedConfigurations(
|
||||||
|
ConfigurationType type)
|
||||||
|
{
|
||||||
|
QVector<AIConfiguration> presets;
|
||||||
|
|
||||||
|
AIConfiguration claudeOpus;
|
||||||
|
claudeOpus.id = "preset_claude_opus";
|
||||||
|
claudeOpus.name = "Claude Opus 4.5";
|
||||||
|
claudeOpus.provider = "Claude";
|
||||||
|
claudeOpus.model = "claude-opus-4-5-20251101";
|
||||||
|
claudeOpus.url = "https://api.anthropic.com";
|
||||||
|
claudeOpus.endpointMode = "Auto";
|
||||||
|
claudeOpus.customEndpoint = "";
|
||||||
|
claudeOpus.templateName = "Claude";
|
||||||
|
claudeOpus.type = type;
|
||||||
|
claudeOpus.isPredefined = true;
|
||||||
|
|
||||||
|
AIConfiguration claudeSonnet;
|
||||||
|
claudeSonnet.id = "preset_claude_sonnet";
|
||||||
|
claudeSonnet.name = "Claude Sonnet 4.5";
|
||||||
|
claudeSonnet.provider = "Claude";
|
||||||
|
claudeSonnet.model = "claude-sonnet-4-5-20250929";
|
||||||
|
claudeSonnet.url = "https://api.anthropic.com";
|
||||||
|
claudeSonnet.endpointMode = "Auto";
|
||||||
|
claudeSonnet.customEndpoint = "";
|
||||||
|
claudeSonnet.templateName = "Claude";
|
||||||
|
claudeSonnet.type = type;
|
||||||
|
claudeSonnet.isPredefined = true;
|
||||||
|
|
||||||
|
AIConfiguration claudeHaiku;
|
||||||
|
claudeHaiku.id = "preset_claude_haiku";
|
||||||
|
claudeHaiku.name = "Claude Haiku 4.5";
|
||||||
|
claudeHaiku.provider = "Claude";
|
||||||
|
claudeHaiku.model = "claude-haiku-4-5-20251001";
|
||||||
|
claudeHaiku.url = "https://api.anthropic.com";
|
||||||
|
claudeHaiku.endpointMode = "Auto";
|
||||||
|
claudeHaiku.customEndpoint = "";
|
||||||
|
claudeHaiku.templateName = "Claude";
|
||||||
|
claudeHaiku.type = type;
|
||||||
|
claudeHaiku.isPredefined = true;
|
||||||
|
|
||||||
|
AIConfiguration mistralCodestral;
|
||||||
|
mistralCodestral.id = "preset_mistral_codestral";
|
||||||
|
mistralCodestral.name = "Mistral Codestral";
|
||||||
|
mistralCodestral.provider = "Mistral AI";
|
||||||
|
mistralCodestral.model = "codestral-2501";
|
||||||
|
mistralCodestral.url = "https://api.mistral.ai";
|
||||||
|
mistralCodestral.endpointMode = "Auto";
|
||||||
|
mistralCodestral.customEndpoint = "";
|
||||||
|
mistralCodestral.templateName = type == ConfigurationType::CodeCompletion ? "Mistral AI FIM" : "Mistral AI Chat";
|
||||||
|
mistralCodestral.type = type;
|
||||||
|
mistralCodestral.isPredefined = true;
|
||||||
|
|
||||||
|
AIConfiguration geminiFlash;
|
||||||
|
geminiFlash.id = "preset_gemini_flash";
|
||||||
|
geminiFlash.name = "Gemini 2.5 Flash";
|
||||||
|
geminiFlash.provider = "Google AI";
|
||||||
|
geminiFlash.model = "gemini-2.5-flash";
|
||||||
|
geminiFlash.url = "https://generativelanguage.googleapis.com/v1beta";
|
||||||
|
geminiFlash.endpointMode = "Auto";
|
||||||
|
geminiFlash.customEndpoint = "";
|
||||||
|
geminiFlash.templateName = "Google AI";
|
||||||
|
geminiFlash.type = type;
|
||||||
|
geminiFlash.isPredefined = true;
|
||||||
|
|
||||||
|
AIConfiguration gpt52codex;
|
||||||
|
gpt52codex.id = "preset_gpt52codex";
|
||||||
|
gpt52codex.name = "gpt-5.2-codex";
|
||||||
|
gpt52codex.provider = "OpenAI Responses";
|
||||||
|
gpt52codex.model = "gpt-5.2-codex";
|
||||||
|
gpt52codex.url = "https://api.openai.com";
|
||||||
|
gpt52codex.endpointMode = "Auto";
|
||||||
|
gpt52codex.customEndpoint = "";
|
||||||
|
gpt52codex.templateName = "OpenAI Responses";
|
||||||
|
gpt52codex.type = type;
|
||||||
|
gpt52codex.isPredefined = true;
|
||||||
|
|
||||||
|
presets.append(claudeSonnet);
|
||||||
|
presets.append(claudeHaiku);
|
||||||
|
presets.append(claudeOpus);
|
||||||
|
presets.append(gpt52codex);
|
||||||
|
presets.append(mistralCodestral);
|
||||||
|
presets.append(geminiFlash);
|
||||||
|
|
||||||
|
return presets;
|
||||||
|
}
|
||||||
|
|
||||||
QString ConfigurationManager::configurationTypeToString(ConfigurationType type) const
|
QString ConfigurationManager::configurationTypeToString(ConfigurationType type) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -94,6 +181,9 @@ bool ConfigurationManager::loadConfigurations(ConfigurationType type)
|
|||||||
|
|
||||||
configs->clear();
|
configs->clear();
|
||||||
|
|
||||||
|
QVector<AIConfiguration> predefinedConfigs = getPredefinedConfigurations(type);
|
||||||
|
configs->append(predefinedConfigs);
|
||||||
|
|
||||||
if (!ensureDirectoryExists(type)) {
|
if (!ensureDirectoryExists(type)) {
|
||||||
LOG_MESSAGE("Failed to create configuration directory");
|
LOG_MESSAGE("Failed to create configuration directory");
|
||||||
return false;
|
return false;
|
||||||
@ -131,6 +221,7 @@ bool ConfigurationManager::loadConfigurations(ConfigurationType type)
|
|||||||
config.customEndpoint = obj["customEndpoint"].toString();
|
config.customEndpoint = obj["customEndpoint"].toString();
|
||||||
config.type = type;
|
config.type = type;
|
||||||
config.formatVersion = obj.value("formatVersion").toInt(1);
|
config.formatVersion = obj.value("formatVersion").toInt(1);
|
||||||
|
config.isPredefined = false;
|
||||||
|
|
||||||
if (config.id.isEmpty() || config.name.isEmpty()) {
|
if (config.id.isEmpty() || config.name.isEmpty()) {
|
||||||
LOG_MESSAGE(QString("Invalid configuration data in file: %1").arg(fileInfo.fileName()));
|
LOG_MESSAGE(QString("Invalid configuration data in file: %1").arg(fileInfo.fileName()));
|
||||||
@ -185,6 +276,12 @@ bool ConfigurationManager::saveConfiguration(const AIConfiguration &config)
|
|||||||
|
|
||||||
bool ConfigurationManager::deleteConfiguration(const QString &id, ConfigurationType type)
|
bool ConfigurationManager::deleteConfiguration(const QString &id, ConfigurationType type)
|
||||||
{
|
{
|
||||||
|
AIConfiguration config = getConfigurationById(id, type);
|
||||||
|
if (config.isPredefined) {
|
||||||
|
LOG_MESSAGE(QString("Cannot delete predefined configuration: %1").arg(id));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QDir dir(getConfigurationDirectory(type));
|
QDir dir(getConfigurationDirectory(type));
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << QString("*_%1.json").arg(id);
|
filters << QString("*_%1.json").arg(id);
|
||||||
|
|||||||
@ -41,6 +41,7 @@ struct AIConfiguration
|
|||||||
QString customEndpoint;
|
QString customEndpoint;
|
||||||
ConfigurationType type;
|
ConfigurationType type;
|
||||||
int formatVersion = CONFIGURATION_FORMAT_VERSION;
|
int formatVersion = CONFIGURATION_FORMAT_VERSION;
|
||||||
|
bool isPredefined = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConfigurationManager : public QObject
|
class ConfigurationManager : public QObject
|
||||||
@ -58,6 +59,8 @@ public:
|
|||||||
AIConfiguration getConfigurationById(const QString &id, ConfigurationType type) const;
|
AIConfiguration getConfigurationById(const QString &id, ConfigurationType type) const;
|
||||||
|
|
||||||
QString getConfigurationDirectory(ConfigurationType type) const;
|
QString getConfigurationDirectory(ConfigurationType type) const;
|
||||||
|
|
||||||
|
static QVector<AIConfiguration> getPredefinedConfigurations(ConfigurationType type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void configurationsChanged(ConfigurationType type);
|
void configurationsChanged(ConfigurationType type);
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <utils/layoutbuilder.h>
|
#include <utils/layoutbuilder.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
@ -88,6 +89,27 @@ GeneralSettings::GeneralSettings()
|
|||||||
|
|
||||||
resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS;
|
resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS;
|
||||||
checkUpdate.m_buttonText = TrConstants::CHECK_UPDATE;
|
checkUpdate.m_buttonText = TrConstants::CHECK_UPDATE;
|
||||||
|
|
||||||
|
ccPresetConfig.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox);
|
||||||
|
ccPresetConfig.setLabelText(Tr::tr("Quick Setup"));
|
||||||
|
loadPresetConfigurations(ccPresetConfig, ConfigurationType::CodeCompletion);
|
||||||
|
|
||||||
|
ccConfigureApiKey.m_buttonText = Tr::tr("Configure API Key");
|
||||||
|
ccConfigureApiKey.m_tooltip = Tr::tr("Open Provider Settings to configure API keys");
|
||||||
|
|
||||||
|
caPresetConfig.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox);
|
||||||
|
caPresetConfig.setLabelText(Tr::tr("Quick Setup"));
|
||||||
|
loadPresetConfigurations(caPresetConfig, ConfigurationType::Chat);
|
||||||
|
|
||||||
|
caConfigureApiKey.m_buttonText = Tr::tr("Configure API Key");
|
||||||
|
caConfigureApiKey.m_tooltip = Tr::tr("Open Provider Settings to configure API keys");
|
||||||
|
|
||||||
|
qrPresetConfig.setDisplayStyle(Utils::SelectionAspect::DisplayStyle::ComboBox);
|
||||||
|
qrPresetConfig.setLabelText(Tr::tr("Quick Setup"));
|
||||||
|
loadPresetConfigurations(qrPresetConfig, ConfigurationType::QuickRefactor);
|
||||||
|
|
||||||
|
qrConfigureApiKey.m_buttonText = Tr::tr("Configure API Key");
|
||||||
|
qrConfigureApiKey.m_tooltip = Tr::tr("Open Provider Settings to configure API keys");
|
||||||
|
|
||||||
initStringAspect(ccProvider, Constants::CC_PROVIDER, TrConstants::PROVIDER, "Ollama");
|
initStringAspect(ccProvider, Constants::CC_PROVIDER, TrConstants::PROVIDER, "Ollama");
|
||||||
ccProvider.setReadOnly(true);
|
ccProvider.setReadOnly(true);
|
||||||
@ -127,6 +149,7 @@ GeneralSettings::GeneralSettings()
|
|||||||
|
|
||||||
ccSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
ccSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
||||||
ccLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
ccLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
||||||
|
ccLoadConfig.m_tooltip = Tr::tr("Load configuration (includes predefined cloud models)");
|
||||||
ccOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
ccOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
||||||
ccOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
ccOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
||||||
ccOpenConfigFolder.m_isCompact = true;
|
ccOpenConfigFolder.m_isCompact = true;
|
||||||
@ -218,6 +241,7 @@ GeneralSettings::GeneralSettings()
|
|||||||
|
|
||||||
caSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
caSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
||||||
caLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
caLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
||||||
|
caLoadConfig.m_tooltip = Tr::tr("Load configuration (includes predefined cloud models)");
|
||||||
caOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
caOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
||||||
caOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
caOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
||||||
caOpenConfigFolder.m_isCompact = true;
|
caOpenConfigFolder.m_isCompact = true;
|
||||||
@ -262,6 +286,7 @@ GeneralSettings::GeneralSettings()
|
|||||||
|
|
||||||
qrSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
qrSaveConfig.m_buttonText = TrConstants::SAVE_CONFIG;
|
||||||
qrLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
qrLoadConfig.m_buttonText = TrConstants::LOAD_CONFIG;
|
||||||
|
qrLoadConfig.m_tooltip = Tr::tr("Load configuration (includes predefined cloud models)");
|
||||||
qrOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
qrOpenConfigFolder.m_buttonText = TrConstants::OPEN_CONFIG_FOLDER;
|
||||||
qrOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
qrOpenConfigFolder.m_icon = Utils::Icons::OPENFILE.icon();
|
||||||
qrOpenConfigFolder.m_isCompact = true;
|
qrOpenConfigFolder.m_isCompact = true;
|
||||||
@ -325,17 +350,24 @@ GeneralSettings::GeneralSettings()
|
|||||||
title(TrConstants::CODE_COMPLETION),
|
title(TrConstants::CODE_COMPLETION),
|
||||||
Column{
|
Column{
|
||||||
Row{ccSaveConfig, ccLoadConfig, ccOpenConfigFolder, Stretch{1}},
|
Row{ccSaveConfig, ccLoadConfig, ccOpenConfigFolder, Stretch{1}},
|
||||||
|
Row{ccPresetConfig, ccConfigureApiKey, Stretch{1}},
|
||||||
ccGrid,
|
ccGrid,
|
||||||
Row{specifyPreset1, preset1Language, Stretch{1}},
|
Row{specifyPreset1, preset1Language, Stretch{1}},
|
||||||
ccPreset1Grid}};
|
ccPreset1Grid}};
|
||||||
|
|
||||||
auto caGroup = Group{
|
auto caGroup = Group{
|
||||||
title(TrConstants::CHAT_ASSISTANT),
|
title(TrConstants::CHAT_ASSISTANT),
|
||||||
Column{Row{caSaveConfig, caLoadConfig, caOpenConfigFolder, Stretch{1}}, caGrid}};
|
Column{
|
||||||
|
Row{caSaveConfig, caLoadConfig, caOpenConfigFolder, Stretch{1}},
|
||||||
|
Row{caPresetConfig, caConfigureApiKey, Stretch{1}},
|
||||||
|
caGrid}};
|
||||||
|
|
||||||
auto qrGroup = Group{
|
auto qrGroup = Group{
|
||||||
title(TrConstants::QUICK_REFACTOR),
|
title(TrConstants::QUICK_REFACTOR),
|
||||||
Column{Row{qrSaveConfig, qrLoadConfig, qrOpenConfigFolder, Stretch{1}}, qrGrid}};
|
Column{
|
||||||
|
Row{qrSaveConfig, qrLoadConfig, qrOpenConfigFolder, Stretch{1}},
|
||||||
|
Row{qrPresetConfig, qrConfigureApiKey, Stretch{1}},
|
||||||
|
qrGrid}};
|
||||||
|
|
||||||
auto rootLayout = Column{
|
auto rootLayout = Column{
|
||||||
Row{enableQodeAssist, Stretch{1}, Row{checkUpdate, resetToDefaults}},
|
Row{enableQodeAssist, Stretch{1}, Row{checkUpdate, resetToDefaults}},
|
||||||
@ -570,6 +602,33 @@ void GeneralSettings::setupConnections()
|
|||||||
connect(&checkUpdate, &ButtonAspect::clicked, this, [this]() {
|
connect(&checkUpdate, &ButtonAspect::clicked, this, [this]() {
|
||||||
QodeAssist::UpdateDialog::checkForUpdatesAndShow(Core::ICore::dialogParent());
|
QodeAssist::UpdateDialog::checkForUpdatesAndShow(Core::ICore::dialogParent());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(&ccPresetConfig, &Utils::SelectionAspect::volatileValueChanged, this, [this]() {
|
||||||
|
applyPresetConfiguration(ccPresetConfig.volatileValue(), ConfigurationType::CodeCompletion);
|
||||||
|
ccPresetConfig.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&ccConfigureApiKey, &ButtonAspect::clicked, this, []() {
|
||||||
|
Core::ICore::showOptionsDialog(Constants::QODE_ASSIST_PROVIDER_SETTINGS_PAGE_ID);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&caPresetConfig, &Utils::SelectionAspect::volatileValueChanged, this, [this]() {
|
||||||
|
applyPresetConfiguration(caPresetConfig.volatileValue(), ConfigurationType::Chat);
|
||||||
|
caPresetConfig.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&caConfigureApiKey, &ButtonAspect::clicked, this, []() {
|
||||||
|
Core::ICore::showOptionsDialog(Constants::QODE_ASSIST_PROVIDER_SETTINGS_PAGE_ID);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&qrPresetConfig, &Utils::SelectionAspect::volatileValueChanged, this, [this]() {
|
||||||
|
applyPresetConfiguration(qrPresetConfig.volatileValue(), ConfigurationType::QuickRefactor);
|
||||||
|
qrPresetConfig.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&qrConfigureApiKey, &ButtonAspect::clicked, this, []() {
|
||||||
|
Core::ICore::showOptionsDialog(Constants::QODE_ASSIST_PROVIDER_SETTINGS_PAGE_ID);
|
||||||
|
});
|
||||||
|
|
||||||
connect(&specifyPreset1, &Utils::BoolAspect::volatileValueChanged, this, [this]() {
|
connect(&specifyPreset1, &Utils::BoolAspect::volatileValueChanged, this, [this]() {
|
||||||
updatePreset1Visiblity(specifyPreset1.volatileValue());
|
updatePreset1Visiblity(specifyPreset1.volatileValue());
|
||||||
@ -776,11 +835,33 @@ void GeneralSettings::onLoadConfiguration(const QString &prefix)
|
|||||||
|
|
||||||
SettingsDialog dialog(TrConstants::LOAD_CONFIGURATION);
|
SettingsDialog dialog(TrConstants::LOAD_CONFIGURATION);
|
||||||
dialog.addLabel(TrConstants::SELECT_CONFIGURATION);
|
dialog.addLabel(TrConstants::SELECT_CONFIGURATION);
|
||||||
|
|
||||||
|
int predefinedCount = 0;
|
||||||
|
for (const AIConfiguration &config : configs) {
|
||||||
|
if (config.isPredefined) {
|
||||||
|
predefinedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (predefinedCount > 0) {
|
||||||
|
auto *hintLabel = dialog.addLabel(
|
||||||
|
Tr::tr("[Preset] configurations are predefined cloud models ready to use."));
|
||||||
|
QFont hintFont = hintLabel->font();
|
||||||
|
hintFont.setItalic(true);
|
||||||
|
hintFont.setPointSize(hintFont.pointSize() - 1);
|
||||||
|
hintLabel->setFont(hintFont);
|
||||||
|
hintLabel->setStyleSheet("color: gray;");
|
||||||
|
}
|
||||||
|
|
||||||
dialog.addSpacing();
|
dialog.addSpacing();
|
||||||
|
|
||||||
QStringList configNames;
|
QStringList configNames;
|
||||||
for (const AIConfiguration &config : configs) {
|
for (const AIConfiguration &config : configs) {
|
||||||
configNames.append(config.name);
|
QString displayName = config.name;
|
||||||
|
if (config.isPredefined) {
|
||||||
|
displayName = QString("[Preset] %1").arg(config.name);
|
||||||
|
}
|
||||||
|
configNames.append(displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto configList = dialog.addComboBox(configNames, QString());
|
auto configList = dialog.addComboBox(configNames, QString());
|
||||||
@ -790,9 +871,31 @@ void GeneralSettings::onLoadConfiguration(const QString &prefix)
|
|||||||
auto *okButton = new QPushButton(TrConstants::OK);
|
auto *okButton = new QPushButton(TrConstants::OK);
|
||||||
auto *cancelButton = new QPushButton(TrConstants::CANCEL);
|
auto *cancelButton = new QPushButton(TrConstants::CANCEL);
|
||||||
|
|
||||||
|
auto updateDeleteButtonState = [&]() {
|
||||||
|
int currentIndex = configList->currentIndex();
|
||||||
|
if (currentIndex >= 0 && currentIndex < configs.size()) {
|
||||||
|
deleteButton->setEnabled(!configs[currentIndex].isPredefined);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
connect(configList,
|
||||||
|
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||||
|
updateDeleteButtonState);
|
||||||
|
|
||||||
|
updateDeleteButtonState();
|
||||||
|
|
||||||
connect(deleteButton, &QPushButton::clicked, &dialog, [&]() {
|
connect(deleteButton, &QPushButton::clicked, &dialog, [&]() {
|
||||||
int currentIndex = configList->currentIndex();
|
int currentIndex = configList->currentIndex();
|
||||||
if (currentIndex >= 0 && currentIndex < configs.size()) {
|
if (currentIndex >= 0 && currentIndex < configs.size()) {
|
||||||
|
const AIConfiguration &configToDelete = configs[currentIndex];
|
||||||
|
if (configToDelete.isPredefined) {
|
||||||
|
QMessageBox::information(
|
||||||
|
&dialog,
|
||||||
|
TrConstants::DELETE_CONFIGURATION,
|
||||||
|
Tr::tr("Predefined configurations cannot be deleted."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QMessageBox::StandardButton reply = QMessageBox::question(
|
QMessageBox::StandardButton reply = QMessageBox::question(
|
||||||
&dialog,
|
&dialog,
|
||||||
TrConstants::DELETE_CONFIGURATION,
|
TrConstants::DELETE_CONFIGURATION,
|
||||||
@ -800,7 +903,6 @@ void GeneralSettings::onLoadConfiguration(const QString &prefix)
|
|||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes) {
|
if (reply == QMessageBox::Yes) {
|
||||||
const AIConfiguration &configToDelete = configs[currentIndex];
|
|
||||||
if (manager.deleteConfiguration(configToDelete.id, type)) {
|
if (manager.deleteConfiguration(configToDelete.id, type)) {
|
||||||
dialog.accept();
|
dialog.accept();
|
||||||
onLoadConfiguration(prefix);
|
onLoadConfiguration(prefix);
|
||||||
@ -860,6 +962,73 @@ void GeneralSettings::onLoadConfiguration(const QString &prefix)
|
|||||||
dialog.exec();
|
dialog.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeneralSettings::loadPresetConfigurations(Utils::SelectionAspect &aspect,
|
||||||
|
ConfigurationType type)
|
||||||
|
{
|
||||||
|
QVector<AIConfiguration> presets = ConfigurationManager::getPredefinedConfigurations(type);
|
||||||
|
|
||||||
|
if (type == ConfigurationType::CodeCompletion) {
|
||||||
|
m_ccPresets = presets;
|
||||||
|
} else if (type == ConfigurationType::Chat) {
|
||||||
|
m_caPresets = presets;
|
||||||
|
} else if (type == ConfigurationType::QuickRefactor) {
|
||||||
|
m_qrPresets = presets;
|
||||||
|
}
|
||||||
|
|
||||||
|
aspect.addOption(Tr::tr("-- Select Preset --"));
|
||||||
|
for (const AIConfiguration &config : presets) {
|
||||||
|
aspect.addOption(config.name);
|
||||||
|
}
|
||||||
|
aspect.setDefaultValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneralSettings::applyPresetConfiguration(int index, ConfigurationType type)
|
||||||
|
{
|
||||||
|
if (index <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<AIConfiguration> *presets = nullptr;
|
||||||
|
if (type == ConfigurationType::CodeCompletion) {
|
||||||
|
presets = &m_ccPresets;
|
||||||
|
} else if (type == ConfigurationType::Chat) {
|
||||||
|
presets = &m_caPresets;
|
||||||
|
} else if (type == ConfigurationType::QuickRefactor) {
|
||||||
|
presets = &m_qrPresets;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!presets || index - 1 >= presets->size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AIConfiguration &config = presets->at(index - 1);
|
||||||
|
|
||||||
|
if (type == ConfigurationType::CodeCompletion) {
|
||||||
|
ccProvider.setValue(config.provider);
|
||||||
|
ccModel.setValue(config.model);
|
||||||
|
ccTemplate.setValue(config.templateName);
|
||||||
|
ccUrl.setValue(config.url);
|
||||||
|
ccEndpointMode.setValue(ccEndpointMode.indexForDisplay(config.endpointMode));
|
||||||
|
ccCustomEndpoint.setValue(config.customEndpoint);
|
||||||
|
} else if (type == ConfigurationType::Chat) {
|
||||||
|
caProvider.setValue(config.provider);
|
||||||
|
caModel.setValue(config.model);
|
||||||
|
caTemplate.setValue(config.templateName);
|
||||||
|
caUrl.setValue(config.url);
|
||||||
|
caEndpointMode.setValue(caEndpointMode.indexForDisplay(config.endpointMode));
|
||||||
|
caCustomEndpoint.setValue(config.customEndpoint);
|
||||||
|
} else if (type == ConfigurationType::QuickRefactor) {
|
||||||
|
qrProvider.setValue(config.provider);
|
||||||
|
qrModel.setValue(config.model);
|
||||||
|
qrTemplate.setValue(config.templateName);
|
||||||
|
qrUrl.setValue(config.url);
|
||||||
|
qrEndpointMode.setValue(qrEndpointMode.indexForDisplay(config.endpointMode));
|
||||||
|
qrCustomEndpoint.setValue(config.customEndpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
class GeneralSettingsPage : public Core::IOptionsPage
|
class GeneralSettingsPage : public Core::IOptionsPage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "ButtonAspect.hpp"
|
#include "ButtonAspect.hpp"
|
||||||
|
#include "ConfigurationManager.hpp"
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
class DetailsWidget;
|
class DetailsWidget;
|
||||||
@ -46,6 +47,9 @@ public:
|
|||||||
ButtonAspect resetToDefaults{this};
|
ButtonAspect resetToDefaults{this};
|
||||||
|
|
||||||
// code completion setttings
|
// code completion setttings
|
||||||
|
Utils::SelectionAspect ccPresetConfig{this};
|
||||||
|
ButtonAspect ccConfigureApiKey{this};
|
||||||
|
|
||||||
Utils::StringAspect ccProvider{this};
|
Utils::StringAspect ccProvider{this};
|
||||||
ButtonAspect ccSelectProvider{this};
|
ButtonAspect ccSelectProvider{this};
|
||||||
|
|
||||||
@ -91,6 +95,9 @@ public:
|
|||||||
ButtonAspect ccPreset1SelectTemplate{this};
|
ButtonAspect ccPreset1SelectTemplate{this};
|
||||||
|
|
||||||
// chat assistant settings
|
// chat assistant settings
|
||||||
|
Utils::SelectionAspect caPresetConfig{this};
|
||||||
|
ButtonAspect caConfigureApiKey{this};
|
||||||
|
|
||||||
Utils::StringAspect caProvider{this};
|
Utils::StringAspect caProvider{this};
|
||||||
ButtonAspect caSelectProvider{this};
|
ButtonAspect caSelectProvider{this};
|
||||||
|
|
||||||
@ -116,6 +123,9 @@ public:
|
|||||||
ButtonAspect caOpenConfigFolder{this};
|
ButtonAspect caOpenConfigFolder{this};
|
||||||
|
|
||||||
// quick refactor settings
|
// quick refactor settings
|
||||||
|
Utils::SelectionAspect qrPresetConfig{this};
|
||||||
|
ButtonAspect qrConfigureApiKey{this};
|
||||||
|
|
||||||
Utils::StringAspect qrProvider{this};
|
Utils::StringAspect qrProvider{this};
|
||||||
ButtonAspect qrSelectProvider{this};
|
ButtonAspect qrSelectProvider{this};
|
||||||
|
|
||||||
@ -162,10 +172,17 @@ public:
|
|||||||
|
|
||||||
void onSaveConfiguration(const QString &prefix);
|
void onSaveConfiguration(const QString &prefix);
|
||||||
void onLoadConfiguration(const QString &prefix);
|
void onLoadConfiguration(const QString &prefix);
|
||||||
|
|
||||||
|
void loadPresetConfigurations(Utils::SelectionAspect &aspect, ConfigurationType type);
|
||||||
|
void applyPresetConfiguration(int index, ConfigurationType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupConnections();
|
void setupConnections();
|
||||||
void resetPageToDefaults();
|
void resetPageToDefaults();
|
||||||
|
|
||||||
|
QVector<AIConfiguration> m_ccPresets;
|
||||||
|
QVector<AIConfiguration> m_caPresets;
|
||||||
|
QVector<AIConfiguration> m_qrPresets;
|
||||||
};
|
};
|
||||||
|
|
||||||
GeneralSettings &generalSettings();
|
GeneralSettings &generalSettings();
|
||||||
|
|||||||
Reference in New Issue
Block a user