mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-06-30 01:59:11 -04:00
refactor: Move to agent architecture
This commit is contained in:
@@ -4,10 +4,14 @@
|
||||
|
||||
#include "AgentDetailPane.hpp"
|
||||
|
||||
#include "AgentModelDialog.hpp"
|
||||
#include "SectionBox.hpp"
|
||||
#include "SettingsTheme.hpp"
|
||||
#include "SettingsUiBuilders.hpp"
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <AgentFactory.hpp>
|
||||
#include <ProviderInstance.hpp>
|
||||
#include <ProviderInstanceFactory.hpp>
|
||||
|
||||
@@ -21,6 +25,7 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QScopedValueRollback>
|
||||
@@ -79,18 +84,24 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
m_path->setFont(monospaceFont(11));
|
||||
m_path->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
QPalette pp = m_path->palette();
|
||||
pp.setColor(QPalette::WindowText, pp.color(QPalette::Mid));
|
||||
pp.setColor(QPalette::WindowText, Utils::creatorColor(Utils::Theme::PanelTextColorMid));
|
||||
m_path->setPalette(pp);
|
||||
|
||||
m_openBtn = new QPushButton(tr("Open in editor"), this);
|
||||
m_dupBtn = new QPushButton(tr("Duplicate…"), this);
|
||||
m_deleteBtn = new QPushButton(tr("Delete"), this);
|
||||
connect(m_openBtn, &QPushButton::clicked, this,
|
||||
[this] { if (m_current) emit openInEditorRequested(*m_current); });
|
||||
connect(m_dupBtn, &QPushButton::clicked, this,
|
||||
[this] { if (m_current) emit customizeRequested(*m_current); });
|
||||
connect(m_deleteBtn, &QPushButton::clicked, this,
|
||||
[this] { if (m_current) emit deleteRequested(*m_current); });
|
||||
connect(m_openBtn, &QPushButton::clicked, this, [this] {
|
||||
if (m_current)
|
||||
emit openInEditorRequested(*m_current);
|
||||
});
|
||||
connect(m_dupBtn, &QPushButton::clicked, this, [this] {
|
||||
if (m_current)
|
||||
emit customizeRequested(*m_current);
|
||||
});
|
||||
connect(m_deleteBtn, &QPushButton::clicked, this, [this] {
|
||||
if (m_current)
|
||||
emit deleteRequested(*m_current);
|
||||
});
|
||||
|
||||
auto *actions = new QHBoxLayout;
|
||||
actions->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -152,50 +163,80 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
idForm = FormBuilder(idGrid, row + 1);
|
||||
}
|
||||
idForm.row(tr("Description:"), m_descriptionEdit);
|
||||
idForm.row(tr("Tags:"), m_tagsValue,
|
||||
tr("Comma-separated. Free-form — used to filter and "
|
||||
"group the agent list."));
|
||||
idForm.row(
|
||||
tr("Tags:"),
|
||||
m_tagsValue,
|
||||
tr("Comma-separated. Free-form — used to filter and "
|
||||
"group the agent list."));
|
||||
identity->bodyLayout()->addLayout(idGrid);
|
||||
|
||||
auto *roleSection = new SectionBox(tr("System role"), this);
|
||||
auto *roleHint = makeHintLabel(
|
||||
tr("Prepended to every request as the system message."));
|
||||
m_roleText = new QPlainTextEdit(this);
|
||||
m_roleText->setReadOnly(true);
|
||||
m_roleText->setMinimumHeight(120);
|
||||
roleSection->bodyLayout()->addWidget(roleHint);
|
||||
roleSection->bodyLayout()->addWidget(m_roleText);
|
||||
|
||||
auto *contextSection = new SectionBox(tr("Context"), this);
|
||||
auto *contextHint = makeHintLabel(
|
||||
tr("Jinja2 template rendered with ContextManager bindings into the "
|
||||
"agent.context system-prompt layer. Empty = no context block."));
|
||||
m_contextText = new QPlainTextEdit(this);
|
||||
m_contextText->setReadOnly(true);
|
||||
m_contextText->setFont(monospaceFont(11));
|
||||
m_contextText->setMinimumHeight(120);
|
||||
contextSection->bodyLayout()->addWidget(contextHint);
|
||||
contextSection->bodyLayout()->addWidget(m_contextText);
|
||||
|
||||
auto *connection = new SectionBox(tr("Connection"), this);
|
||||
m_providerCombo = new QComboBox(this);
|
||||
m_providerCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_providerCombo->setEnabled(false);
|
||||
connect(m_providerCombo, &QComboBox::activated, this, [this](int index) {
|
||||
onChangeProvider(index);
|
||||
});
|
||||
|
||||
m_providerResetBtn = new QPushButton(tr("Reset"), this);
|
||||
m_providerResetBtn->setToolTip(
|
||||
tr("Remove the provider override and restore the agent's default"));
|
||||
m_providerResetBtn->setVisible(false);
|
||||
connect(m_providerResetBtn, &QPushButton::clicked, this, [this] { onResetProvider(); });
|
||||
|
||||
auto *providerHolder = new QWidget(this);
|
||||
auto *providerRow = new QHBoxLayout(providerHolder);
|
||||
providerRow->setContentsMargins(0, 0, 0, 0);
|
||||
providerRow->setSpacing(6);
|
||||
providerRow->addWidget(m_providerCombo, 1);
|
||||
providerRow->addWidget(m_providerResetBtn);
|
||||
|
||||
m_endpointValue = makeReadOnlyLine(true);
|
||||
|
||||
m_modelValue = makeReadOnlyLine(true);
|
||||
m_modelValue->setPlaceholderText(tr("(set a model)"));
|
||||
|
||||
m_modelChangeBtn = new QPushButton(tr("Change…"), this);
|
||||
m_modelChangeBtn->setToolTip(tr("Pick a model from the provider or type one"));
|
||||
m_modelChangeBtn->setEnabled(false);
|
||||
connect(m_modelChangeBtn, &QPushButton::clicked, this, [this] { onChangeModel(); });
|
||||
|
||||
m_modelResetBtn = new QPushButton(tr("Reset"), this);
|
||||
m_modelResetBtn->setToolTip(tr("Remove the model override and restore the agent's default"));
|
||||
m_modelResetBtn->setVisible(false);
|
||||
connect(m_modelResetBtn, &QPushButton::clicked, this, [this] { onResetModel(); });
|
||||
|
||||
auto *modelHolder = new QWidget(this);
|
||||
auto *modelRow = new QHBoxLayout(modelHolder);
|
||||
modelRow->setContentsMargins(0, 0, 0, 0);
|
||||
modelRow->setSpacing(6);
|
||||
modelRow->addWidget(m_modelValue, 1);
|
||||
modelRow->addWidget(m_modelChangeBtn);
|
||||
modelRow->addWidget(m_modelResetBtn);
|
||||
|
||||
auto *connGrid = new QGridLayout;
|
||||
connGrid->setContentsMargins(0, 0, 0, 0);
|
||||
connGrid->setHorizontalSpacing(8);
|
||||
connGrid->setVerticalSpacing(4);
|
||||
FormBuilder(connGrid)
|
||||
.row(tr("Provider:"), m_providerCombo,
|
||||
tr("The provider instance this agent uses. URL is "
|
||||
"inherited from the instance."))
|
||||
.row(tr("Endpoint:"), m_endpointValue,
|
||||
tr("Appended to the provider's URL. Blank uses the "
|
||||
"provider default."))
|
||||
.row(tr("Model:"), m_modelValue);
|
||||
.row(
|
||||
tr("Provider:"),
|
||||
providerHolder,
|
||||
tr("The provider instance this agent uses. URL is "
|
||||
"inherited from the instance. Switching it is saved as a "
|
||||
"per-agent override; Reset restores the agent's default."))
|
||||
.row(
|
||||
tr("Endpoint:"),
|
||||
m_endpointValue,
|
||||
tr("Appended to the provider's URL. Blank uses the "
|
||||
"provider default."))
|
||||
.row(
|
||||
tr("Model:"),
|
||||
modelHolder,
|
||||
tr("Model sent to the provider. Click Change… to pick from the "
|
||||
"provider's available models or type one. The choice is saved "
|
||||
"as a per-agent override in settings; Reset restores the "
|
||||
"agent's default."));
|
||||
connection->bodyLayout()->addLayout(connGrid);
|
||||
|
||||
m_effectiveUrl = new QLabel(this);
|
||||
@@ -215,34 +256,13 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
matchGrid->setContentsMargins(0, 0, 0, 0);
|
||||
matchGrid->setHorizontalSpacing(8);
|
||||
matchGrid->setVerticalSpacing(4);
|
||||
FormBuilder(matchGrid).row(tr("File patterns:"), m_filePatternsValue,
|
||||
tr("Globs, comma-separated. Empty matches every file."));
|
||||
FormBuilder(matchGrid).row(
|
||||
tr("File patterns:"),
|
||||
m_filePatternsValue,
|
||||
tr("Globs, comma-separated. Empty matches every file."));
|
||||
match->bodyLayout()->addWidget(matchHint);
|
||||
match->bodyLayout()->addLayout(matchGrid);
|
||||
|
||||
auto *templ = new SectionBox(tr("Template"), this);
|
||||
auto *templHint = makeHintLabel(
|
||||
tr("Jinja2 template (via inja) rendered to the request body. "
|
||||
"Built-in context: ctx.prefix, ctx.suffix, ctx.history, "
|
||||
"ctx.system_prompt, agent.model."));
|
||||
m_messageFormat = new QPlainTextEdit(this);
|
||||
m_messageFormat->setReadOnly(true);
|
||||
m_messageFormat->setFont(monospaceFont(11));
|
||||
m_messageFormat->setMinimumHeight(140);
|
||||
|
||||
templ->bodyLayout()->addWidget(templHint);
|
||||
auto *mfLabel = new QLabel(tr("message_format:"), this);
|
||||
templ->bodyLayout()->addWidget(mfLabel);
|
||||
templ->bodyLayout()->addWidget(m_messageFormat);
|
||||
|
||||
m_diagnostics = new SectionBox(tr("Load errors"), this);
|
||||
m_diagnosticsView = new QPlainTextEdit(this);
|
||||
m_diagnosticsView->setReadOnly(true);
|
||||
m_diagnosticsView->setMaximumHeight(110);
|
||||
m_diagnosticsView->setFont(monospaceFont(11));
|
||||
m_diagnostics->bodyLayout()->addWidget(m_diagnosticsView);
|
||||
m_diagnostics->setVisible(false);
|
||||
|
||||
m_rawToggle = new QToolButton(this);
|
||||
m_rawToggle->setText(tr("▸ Show raw TOML"));
|
||||
m_rawToggle->setCursor(Qt::PointingHandCursor);
|
||||
@@ -267,10 +287,6 @@ AgentDetailPane::AgentDetailPane(QWidget *parent)
|
||||
root->addWidget(identity);
|
||||
root->addWidget(connection);
|
||||
root->addWidget(match);
|
||||
root->addWidget(templ);
|
||||
root->addWidget(roleSection);
|
||||
root->addWidget(contextSection);
|
||||
root->addWidget(m_diagnostics);
|
||||
root->addWidget(m_rawToggle, 0, Qt::AlignLeft);
|
||||
root->addWidget(m_rawToml);
|
||||
root->addStretch(1);
|
||||
@@ -286,6 +302,11 @@ void AgentDetailPane::setInstanceFactory(Providers::ProviderInstanceFactory *fac
|
||||
populateProviderCombo();
|
||||
}
|
||||
|
||||
void AgentDetailPane::setAgentFactory(AgentFactory *factory)
|
||||
{
|
||||
m_agentFactory = factory;
|
||||
}
|
||||
|
||||
void AgentDetailPane::populateProviderCombo()
|
||||
{
|
||||
if (m_providerComboPopulated)
|
||||
@@ -294,13 +315,105 @@ void AgentDetailPane::populateProviderCombo()
|
||||
m_providerComboHasSentinel = false;
|
||||
if (m_instanceFactory) {
|
||||
for (const auto &inst : m_instanceFactory->instances()) {
|
||||
m_providerCombo->addItem(
|
||||
QStringLiteral("%1 (%2)").arg(inst.name, inst.clientApi), inst.name);
|
||||
m_providerCombo
|
||||
->addItem(QStringLiteral("%1 (%2)").arg(inst.name, inst.clientApi), inst.name);
|
||||
}
|
||||
}
|
||||
m_providerComboPopulated = true;
|
||||
}
|
||||
|
||||
void AgentDetailPane::onChangeModel()
|
||||
{
|
||||
if (!m_agentFactory || !m_current)
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
AgentModelDialog dialog(m_agentFactory, name, m_current->model, this);
|
||||
if (dialog.exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
const QString model = dialog.selectedModel();
|
||||
if (model == m_current->model)
|
||||
return;
|
||||
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentModelOverride(name, model, &err)) {
|
||||
QMessageBox::warning(this, tr("Set model"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::onResetModel()
|
||||
{
|
||||
if (!m_agentFactory || !m_current)
|
||||
return;
|
||||
if (m_agentFactory->agentModelOverride(m_current->name).isEmpty())
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentModelOverride(name, QString(), &err)) {
|
||||
QMessageBox::warning(this, tr("Reset model"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::onChangeProvider(int index)
|
||||
{
|
||||
if (!m_agentFactory || !m_current || index < 0)
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
const QString selected = m_providerCombo->itemData(index).toString();
|
||||
if (selected.isEmpty() || selected == m_current->providerInstance)
|
||||
return;
|
||||
|
||||
const auto answer = QMessageBox::warning(
|
||||
this,
|
||||
tr("Change provider"),
|
||||
tr("Changing the agent's default provider may make it behave incorrectly — "
|
||||
"the agent template is tuned for its original provider.\n\n"
|
||||
"Switch '%1' to provider '%2'?")
|
||||
.arg(name, selected),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No);
|
||||
if (answer != QMessageBox::Yes) {
|
||||
const int cur = m_providerCombo->findData(m_current->providerInstance);
|
||||
if (cur >= 0)
|
||||
m_providerCombo->setCurrentIndex(cur);
|
||||
return;
|
||||
}
|
||||
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentProviderOverride(name, selected, &err)) {
|
||||
QMessageBox::warning(this, tr("Change provider"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::onResetProvider()
|
||||
{
|
||||
if (!m_agentFactory || !m_current)
|
||||
return;
|
||||
if (m_agentFactory->agentProviderOverride(m_current->name).isEmpty())
|
||||
return;
|
||||
|
||||
const QString name = m_current->name;
|
||||
QString err;
|
||||
if (!m_agentFactory->setAgentProviderOverride(name, QString(), &err)) {
|
||||
QMessageBox::warning(this, tr("Reset provider"), err);
|
||||
return;
|
||||
}
|
||||
if (const AgentConfig *cfg = m_agentFactory->configByName(name))
|
||||
setAgent(*cfg);
|
||||
}
|
||||
|
||||
void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
{
|
||||
m_currentStorage = cfg;
|
||||
@@ -309,9 +422,8 @@ void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
|
||||
m_name->setText(cfg.name);
|
||||
m_path->setText(cfg.sourcePath);
|
||||
m_description->setText(cfg.description.isEmpty()
|
||||
? tr("No description provided.")
|
||||
: cfg.description);
|
||||
m_description->setText(
|
||||
cfg.description.isEmpty() ? tr("No description provided.") : cfg.description);
|
||||
|
||||
m_nameValue->setText(cfg.name);
|
||||
if (cfg.extendsName.isEmpty()) {
|
||||
@@ -342,36 +454,41 @@ void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
m_providerCombo->setCurrentIndex(idx);
|
||||
} else if (!cfg.providerInstance.isEmpty()) {
|
||||
m_providerCombo->insertItem(
|
||||
0, tr("%1 (missing — not in provider library)")
|
||||
.arg(cfg.providerInstance),
|
||||
0,
|
||||
tr("%1 (missing — not in provider library)").arg(cfg.providerInstance),
|
||||
cfg.providerInstance);
|
||||
m_providerCombo->setCurrentIndex(0);
|
||||
m_providerComboHasSentinel = true;
|
||||
}
|
||||
|
||||
m_providerCombo->setEnabled(m_agentFactory != nullptr);
|
||||
const bool hasProviderOverride = m_agentFactory
|
||||
&& !m_agentFactory->agentProviderOverride(cfg.name).isEmpty();
|
||||
m_providerResetBtn->setVisible(hasProviderOverride);
|
||||
m_providerCombo->setToolTip(
|
||||
hasProviderOverride
|
||||
? tr("Overridden in settings. Reset to use the agent's default provider.")
|
||||
: QString());
|
||||
|
||||
m_endpointValue->setText(cfg.endpoint);
|
||||
m_endpointValue->setPlaceholderText(tr("(provider default)"));
|
||||
m_modelValue->setText(cfg.model);
|
||||
m_modelChangeBtn->setEnabled(m_agentFactory != nullptr);
|
||||
const bool hasModelOverride = m_agentFactory
|
||||
&& !m_agentFactory->agentModelOverride(cfg.name).isEmpty();
|
||||
m_modelResetBtn->setVisible(hasModelOverride);
|
||||
m_modelValue->setToolTip(
|
||||
hasModelOverride ? tr("Overridden in settings. Reset to use the agent's default model.")
|
||||
: QString());
|
||||
|
||||
const QString eff = resolvedUrl + cfg.endpoint;
|
||||
m_effectiveUrl->setText(
|
||||
eff.isEmpty()
|
||||
? tr("# effective request line\n(unknown — provider instance not found)")
|
||||
: QStringLiteral("# %1\nPOST %2")
|
||||
.arg(tr("effective request line"), eff));
|
||||
|
||||
m_roleText->setPlainText(
|
||||
cfg.role.isEmpty() ? tr("(no system role set)") : cfg.role);
|
||||
m_contextText->setPlainText(
|
||||
cfg.context.isEmpty() ? tr("(no context block)") : cfg.context);
|
||||
eff.isEmpty() ? tr("# effective request line\n(unknown — provider instance not found)")
|
||||
: QStringLiteral("# %1\nPOST %2").arg(tr("effective request line"), eff));
|
||||
|
||||
m_filePatternsValue->setText(cfg.match.filePatterns.join(QStringLiteral(", ")));
|
||||
m_filePatternsValue->setPlaceholderText(tr("(matches every file)"));
|
||||
|
||||
m_messageFormat->setPlainText(
|
||||
cfg.messageFormat.isEmpty() ? tr("(inherited from parent / none)")
|
||||
: cfg.messageFormat);
|
||||
|
||||
const FileReadResult raw = readFileTextCapped(cfg.sourcePath, kRawTomlMaxBytes);
|
||||
switch (raw.status) {
|
||||
case FileReadStatus::Ok:
|
||||
@@ -391,12 +508,12 @@ void AgentDetailPane::setAgent(const AgentConfig &cfg)
|
||||
}
|
||||
|
||||
m_openBtn->setEnabled(user);
|
||||
m_openBtn->setToolTip(user ? QString()
|
||||
: tr("Bundled agents are read-only — "
|
||||
"duplicate to edit."));
|
||||
m_openBtn->setToolTip(
|
||||
user ? QString()
|
||||
: tr("Bundled agents are read-only — "
|
||||
"duplicate to edit."));
|
||||
m_deleteBtn->setEnabled(user);
|
||||
m_deleteBtn->setToolTip(user ? QString()
|
||||
: tr("Bundled agents cannot be deleted."));
|
||||
m_deleteBtn->setToolTip(user ? QString() : tr("Bundled agents cannot be deleted."));
|
||||
m_dupBtn->setEnabled(true);
|
||||
applyCodePalette();
|
||||
}
|
||||
@@ -418,30 +535,20 @@ void AgentDetailPane::clear()
|
||||
m_providerComboHasSentinel = false;
|
||||
}
|
||||
m_providerCombo->setCurrentIndex(-1);
|
||||
m_providerCombo->setEnabled(false);
|
||||
m_providerResetBtn->setVisible(false);
|
||||
m_endpointValue->clear();
|
||||
m_modelValue->clear();
|
||||
m_modelChangeBtn->setEnabled(false);
|
||||
m_modelResetBtn->setVisible(false);
|
||||
m_effectiveUrl->clear();
|
||||
m_roleText->clear();
|
||||
m_contextText->clear();
|
||||
m_filePatternsValue->clear();
|
||||
m_messageFormat->clear();
|
||||
m_rawToml->clear();
|
||||
m_openBtn->setEnabled(false);
|
||||
m_dupBtn->setEnabled(false);
|
||||
m_deleteBtn->setEnabled(false);
|
||||
}
|
||||
|
||||
void AgentDetailPane::setLoadDiagnostics(const QStringList &errors, const QStringList &warnings)
|
||||
{
|
||||
QStringList lines;
|
||||
for (const QString &e : errors)
|
||||
lines << tr("error: %1").arg(e);
|
||||
for (const QString &w : warnings)
|
||||
lines << tr("warning: %1").arg(w);
|
||||
m_diagnostics->setVisible(!lines.isEmpty());
|
||||
m_diagnosticsView->setPlainText(lines.join(QLatin1Char('\n')));
|
||||
}
|
||||
|
||||
void AgentDetailPane::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
@@ -463,14 +570,14 @@ QLineEdit *AgentDetailPane::makeReadOnlyLine(bool mono)
|
||||
void AgentDetailPane::applyCodePalette()
|
||||
{
|
||||
QScopedValueRollback<bool> guard(m_inApplyPalette, true);
|
||||
const Theme theme = themeFor(palette());
|
||||
const QColor codeBg = Utils::creatorColor(Utils::Theme::BackgroundColorNormal);
|
||||
QPalette p = m_effectiveUrl->palette();
|
||||
p.setColor(QPalette::Window, QColor(theme.codeBg));
|
||||
p.setColor(QPalette::WindowText, palette().color(QPalette::Text));
|
||||
p.setColor(QPalette::Window, codeBg);
|
||||
p.setColor(QPalette::WindowText, Utils::creatorColor(Utils::Theme::TextColorNormal));
|
||||
m_effectiveUrl->setPalette(p);
|
||||
m_effectiveUrl->setStyleSheet(QStringLiteral(
|
||||
"QLabel { background:%1; border:1px solid %2; }")
|
||||
.arg(theme.codeBg, theme.rowSeparator));
|
||||
m_effectiveUrl->setStyleSheet(
|
||||
QStringLiteral("QLabel { background:%1; border:1px solid %2; }")
|
||||
.arg(cssColor(codeBg), cssColor(Utils::creatorColor(Utils::Theme::SplitterColor))));
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Settings
|
||||
|
||||
Reference in New Issue
Block a user