mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-05-30 10:59:30 -04:00
feat: Add settings page for providers (#353)
This commit is contained in:
527
settings/ProviderDetailPane.cpp
Normal file
527
settings/ProviderDetailPane.cpp
Normal file
@@ -0,0 +1,527 @@
|
||||
// Copyright (C) 2024-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "ProviderDetailPane.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <solutions/terminal/terminalview.h>
|
||||
|
||||
#include "ProviderInstanceWriter.hpp"
|
||||
#include "ProvidersSettingsHelpers.hpp"
|
||||
#include "SectionBox.hpp"
|
||||
|
||||
namespace QodeAssist::Settings {
|
||||
|
||||
ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_nameLabel = new QLabel(this);
|
||||
QFont nf = m_nameLabel->font();
|
||||
nf.setBold(true);
|
||||
nf.setPixelSize(15);
|
||||
m_nameLabel->setFont(nf);
|
||||
|
||||
m_sourcePathLabel = new QLabel(this);
|
||||
m_sourcePathLabel->setFont(monospaceFont(11));
|
||||
QPalette spp = m_sourcePathLabel->palette();
|
||||
spp.setColor(QPalette::WindowText, spp.color(QPalette::Mid));
|
||||
m_sourcePathLabel->setPalette(spp);
|
||||
|
||||
m_editBtn = new QPushButton(tr("Edit…"), this);
|
||||
m_editBtn->setDefault(true);
|
||||
m_openInEditorBtn = new QPushButton(tr("Open in editor"), this);
|
||||
m_openInEditorBtn->setToolTip(
|
||||
tr("Open this provider's TOML file in Qt Creator. "
|
||||
"Bundled providers are read-only — duplicate first."));
|
||||
m_dupBtn = new QPushButton(tr("Duplicate…"), this);
|
||||
m_deleteBtn = new QPushButton(tr("Delete"), this);
|
||||
m_cancelBtn = new QPushButton(tr("Cancel"), this);
|
||||
m_saveBtn = new QPushButton(tr("Save"), this);
|
||||
m_saveBtn->setDefault(true);
|
||||
m_cancelBtn->hide();
|
||||
m_saveBtn->hide();
|
||||
|
||||
connect(m_editBtn, &QPushButton::clicked, this, [this] { setEditing(true); });
|
||||
connect(m_cancelBtn, &QPushButton::clicked, this, [this] {
|
||||
setEditing(false);
|
||||
populate(m_current, m_currentHasStoredKey);
|
||||
});
|
||||
connect(m_saveBtn, &QPushButton::clicked, this, [this] {
|
||||
emit saveRequested(collectEdits());
|
||||
});
|
||||
connect(m_openInEditorBtn, &QPushButton::clicked, this,
|
||||
[this] { emit openInEditorRequested(m_current.sourcePath); });
|
||||
connect(m_dupBtn, &QPushButton::clicked, this, [this] { emit duplicateRequested(); });
|
||||
connect(m_deleteBtn, &QPushButton::clicked, this, [this] { emit deleteRequested(); });
|
||||
|
||||
auto *btnBar = new QHBoxLayout;
|
||||
btnBar->setContentsMargins(0, 0, 0, 0);
|
||||
btnBar->setSpacing(4);
|
||||
btnBar->addWidget(m_editBtn);
|
||||
btnBar->addWidget(m_openInEditorBtn);
|
||||
btnBar->addWidget(m_dupBtn);
|
||||
btnBar->addWidget(m_deleteBtn);
|
||||
btnBar->addWidget(m_cancelBtn);
|
||||
btnBar->addWidget(m_saveBtn);
|
||||
|
||||
auto *titleRow = new QHBoxLayout;
|
||||
titleRow->setContentsMargins(0, 0, 0, 0);
|
||||
titleRow->setSpacing(8);
|
||||
titleRow->addWidget(m_nameLabel);
|
||||
titleRow->addStretch(1);
|
||||
|
||||
auto *headerLeft = new QVBoxLayout;
|
||||
headerLeft->setContentsMargins(0, 0, 0, 0);
|
||||
headerLeft->setSpacing(2);
|
||||
headerLeft->addLayout(titleRow);
|
||||
headerLeft->addWidget(m_sourcePathLabel);
|
||||
|
||||
auto *headerRow = new QHBoxLayout;
|
||||
headerRow->setContentsMargins(0, 0, 0, 0);
|
||||
headerRow->setSpacing(8);
|
||||
headerRow->addLayout(headerLeft, 1);
|
||||
headerRow->addLayout(btnBar);
|
||||
|
||||
auto *headerSep = new QFrame(this);
|
||||
headerSep->setFrameShape(QFrame::HLine);
|
||||
headerSep->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
m_descriptionLabel = new QLabel(this);
|
||||
m_descriptionLabel->setWordWrap(true);
|
||||
m_descriptionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
|
||||
auto *identitySection = new SectionBox(tr("Identity"), this);
|
||||
m_nameEdit = new QLineEdit(this);
|
||||
m_typeEdit = new QLineEdit(this);
|
||||
m_typeEdit->setReadOnly(true);
|
||||
m_descriptionEdit = new QPlainTextEdit(this);
|
||||
m_descriptionEdit->setMaximumHeight(60);
|
||||
m_descriptionEdit->setReadOnly(true);
|
||||
auto *identityGrid = new QGridLayout;
|
||||
identityGrid->setContentsMargins(0, 0, 0, 0);
|
||||
identityGrid->setHorizontalSpacing(8);
|
||||
identityGrid->setVerticalSpacing(4);
|
||||
int identityRow = 0;
|
||||
identityRow = addFormRow(identityGrid, identityRow, tr("Name:"),
|
||||
singleField(m_nameEdit));
|
||||
identityRow = addFormRow(identityGrid, identityRow, tr("Client API:"),
|
||||
singleField(m_typeEdit),
|
||||
tr("The client API this provider speaks. "
|
||||
"Cannot be changed after creation."));
|
||||
identityRow = addFormRow(identityGrid, identityRow, tr("Description:"),
|
||||
singleField(m_descriptionEdit));
|
||||
identitySection->bodyLayout()->addLayout(identityGrid);
|
||||
|
||||
auto *endpointSection = new SectionBox(tr("Endpoint"), this);
|
||||
m_urlEdit = new QLineEdit(this);
|
||||
m_urlEdit->setFont(monospaceFont(11));
|
||||
auto *endpointGrid = new QGridLayout;
|
||||
endpointGrid->setContentsMargins(0, 0, 0, 0);
|
||||
endpointGrid->setHorizontalSpacing(8);
|
||||
endpointGrid->setVerticalSpacing(4);
|
||||
int endpointRow = 0;
|
||||
endpointRow = addFormRow(endpointGrid, endpointRow, tr("URL:"),
|
||||
singleField(m_urlEdit),
|
||||
tr("Base URL. Agents append their endpoint path "
|
||||
"(e.g. /chat/completions) to this."));
|
||||
endpointSection->bodyLayout()->addLayout(endpointGrid);
|
||||
|
||||
m_samplePreview = new QLabel(this);
|
||||
m_samplePreview->setFont(monospaceFont(11));
|
||||
m_samplePreview->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
m_samplePreview->setWordWrap(true);
|
||||
m_samplePreview->setContentsMargins(6, 4, 6, 4);
|
||||
m_samplePreview->setAutoFillBackground(true);
|
||||
endpointSection->bodyLayout()->addWidget(m_samplePreview);
|
||||
|
||||
auto *credSection = new SectionBox(tr("Credentials"), this);
|
||||
m_apiKeyEdit = new QLineEdit(this);
|
||||
m_apiKeyEdit->setEchoMode(QLineEdit::Password);
|
||||
m_apiKeyEdit->setPlaceholderText(tr("Enter API key…"));
|
||||
m_revealKeyBtn = new QToolButton(this);
|
||||
m_revealKeyBtn->setText(QStringLiteral("👁"));
|
||||
m_revealKeyBtn->setCheckable(true);
|
||||
m_revealKeyBtn->setToolTip(tr("Show / hide API key"));
|
||||
connect(m_revealKeyBtn, &QToolButton::toggled, this, [this](bool on) {
|
||||
m_apiKeyEdit->setEchoMode(on ? QLineEdit::Normal : QLineEdit::Password);
|
||||
});
|
||||
m_apiKeySaveBtn = new QPushButton(tr("Save key"), this);
|
||||
m_apiKeySaveBtn->setEnabled(false);
|
||||
m_apiKeyClearBtn = new QPushButton(tr("Clear"), this);
|
||||
m_apiKeyClearBtn->setToolTip(tr("Erase the stored API key for this provider"));
|
||||
connect(m_apiKeyEdit, &QLineEdit::textChanged, this, [this](const QString &t) {
|
||||
m_apiKeySaveBtn->setEnabled(!t.isEmpty());
|
||||
});
|
||||
connect(m_apiKeyEdit, &QLineEdit::returnPressed, this, [this] {
|
||||
if (!m_apiKeyEdit->text().isEmpty())
|
||||
m_apiKeySaveBtn->click();
|
||||
});
|
||||
connect(m_apiKeySaveBtn, &QPushButton::clicked, this, [this] {
|
||||
const QString key = m_apiKeyEdit->text();
|
||||
if (key.isEmpty())
|
||||
return;
|
||||
emit apiKeySaveRequested(key);
|
||||
m_apiKeyEdit->clear();
|
||||
});
|
||||
connect(m_apiKeyClearBtn, &QPushButton::clicked, this,
|
||||
[this] { emit apiKeyClearRequested(); });
|
||||
m_keyHint = new QLabel(this);
|
||||
QFont khf = m_keyHint->font();
|
||||
khf.setPixelSize(11);
|
||||
m_keyHint->setFont(khf);
|
||||
m_keyHint->setWordWrap(true);
|
||||
QPalette khp = m_keyHint->palette();
|
||||
khp.setColor(QPalette::WindowText, khp.color(QPalette::Mid));
|
||||
m_keyHint->setPalette(khp);
|
||||
|
||||
auto *keyRow = new QHBoxLayout;
|
||||
keyRow->setContentsMargins(0, 0, 0, 0);
|
||||
keyRow->setSpacing(4);
|
||||
keyRow->addWidget(m_apiKeyEdit, 1);
|
||||
keyRow->addWidget(m_revealKeyBtn);
|
||||
keyRow->addWidget(m_apiKeySaveBtn);
|
||||
keyRow->addWidget(m_apiKeyClearBtn);
|
||||
|
||||
auto *credGrid = new QGridLayout;
|
||||
credGrid->setContentsMargins(0, 0, 0, 0);
|
||||
credGrid->setHorizontalSpacing(8);
|
||||
credGrid->setVerticalSpacing(4);
|
||||
int credRow = 0;
|
||||
credRow = addFormRow(credGrid, credRow, tr("API key:"), keyRow);
|
||||
credGrid->addWidget(m_keyHint, credRow, 1);
|
||||
credSection->bodyLayout()->addLayout(credGrid);
|
||||
|
||||
m_launchSection = new SectionBox(tr("Launch"), this);
|
||||
m_launchEmptyHint = new QLabel(this);
|
||||
m_launchEmptyHint->setWordWrap(true);
|
||||
QPalette lehp = m_launchEmptyHint->palette();
|
||||
lehp.setColor(QPalette::WindowText, lehp.color(QPalette::Mid));
|
||||
m_launchEmptyHint->setPalette(lehp);
|
||||
m_launchCmdLabel = new QLabel(this);
|
||||
m_launchCmdLabel->setFont(monospaceFont(11));
|
||||
m_launchCmdLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
m_launchCmdLabel->setWordWrap(true);
|
||||
m_launchStatusPill = new QLabel(tr("idle"), this);
|
||||
m_startBtn = new QPushButton(tr("Start"), this);
|
||||
m_stopBtn = new QPushButton(tr("Stop"), this);
|
||||
m_restartBtn = new QPushButton(tr("Restart"), this);
|
||||
connect(m_startBtn, &QPushButton::clicked, this,
|
||||
[this] { emit launchStartRequested(m_current.name); });
|
||||
connect(m_stopBtn, &QPushButton::clicked, this,
|
||||
[this] { emit launchStopRequested(m_current.name); });
|
||||
connect(m_restartBtn, &QPushButton::clicked, this,
|
||||
[this] { emit launchRestartRequested(m_current.name); });
|
||||
auto *launchBtnRow = new QHBoxLayout;
|
||||
launchBtnRow->setContentsMargins(0, 0, 0, 0);
|
||||
launchBtnRow->setSpacing(6);
|
||||
launchBtnRow->addWidget(m_launchStatusPill);
|
||||
launchBtnRow->addStretch(1);
|
||||
launchBtnRow->addWidget(m_startBtn);
|
||||
launchBtnRow->addWidget(m_stopBtn);
|
||||
launchBtnRow->addWidget(m_restartBtn);
|
||||
|
||||
m_launchTerminalToggle = new QToolButton(this);
|
||||
m_launchTerminalToggle->setText(tr("▸ Show launch terminal"));
|
||||
m_launchTerminalToggle->setCursor(Qt::PointingHandCursor);
|
||||
m_launchTerminalToggle->setAutoRaise(true);
|
||||
m_launchTerminalToggle->setCheckable(true);
|
||||
m_launchTerminal = new TerminalSolution::TerminalView(this);
|
||||
{
|
||||
QFont termFont(TerminalSolution::defaultFontFamily());
|
||||
const int sz = TerminalSolution::defaultFontSize();
|
||||
if (sz > 0)
|
||||
termFont.setPixelSize(sz);
|
||||
termFont.setStyleHint(QFont::Monospace);
|
||||
m_launchTerminal->setFont(termFont);
|
||||
applyTerminalPalette();
|
||||
}
|
||||
m_launchTerminal->setMinimumHeight(180);
|
||||
m_launchTerminal->setVisible(false);
|
||||
connect(m_launchTerminalToggle, &QToolButton::toggled, this, [this](bool on) {
|
||||
m_launchTerminal->setVisible(on);
|
||||
m_launchTerminalToggle->setText(
|
||||
on ? tr("▾ Hide launch terminal") : tr("▸ Show launch terminal"));
|
||||
});
|
||||
|
||||
m_launchSection->bodyLayout()->addWidget(m_launchEmptyHint);
|
||||
m_launchSection->bodyLayout()->addWidget(m_launchCmdLabel);
|
||||
m_launchSection->bodyLayout()->addLayout(launchBtnRow);
|
||||
m_launchSection->bodyLayout()->addWidget(m_launchTerminalToggle, 0, Qt::AlignLeft);
|
||||
m_launchSection->bodyLayout()->addWidget(m_launchTerminal);
|
||||
|
||||
m_rawToggle = new QToolButton(this);
|
||||
m_rawToggle->setText(tr("▸ Show raw TOML"));
|
||||
m_rawToggle->setCursor(Qt::PointingHandCursor);
|
||||
m_rawToggle->setAutoRaise(true);
|
||||
m_rawToggle->setCheckable(true);
|
||||
m_rawToml = new QPlainTextEdit(this);
|
||||
m_rawToml->setReadOnly(true);
|
||||
m_rawToml->setFont(monospaceFont(11));
|
||||
m_rawToml->setMinimumHeight(120);
|
||||
m_rawToml->setVisible(false);
|
||||
connect(m_rawToggle, &QToolButton::toggled, this, [this](bool on) {
|
||||
m_rawToml->setVisible(on);
|
||||
m_rawToggle->setText(on ? tr("▾ Hide raw TOML") : tr("▸ Show raw TOML"));
|
||||
});
|
||||
|
||||
auto *root = new QVBoxLayout(this);
|
||||
root->setContentsMargins(12, 12, 12, 12);
|
||||
root->setSpacing(10);
|
||||
root->addLayout(headerRow);
|
||||
root->addWidget(headerSep);
|
||||
root->addWidget(m_descriptionLabel);
|
||||
root->addWidget(identitySection);
|
||||
root->addWidget(endpointSection);
|
||||
root->addWidget(credSection);
|
||||
root->addWidget(m_launchSection);
|
||||
root->addWidget(m_rawToggle, 0, Qt::AlignLeft);
|
||||
root->addWidget(m_rawToml);
|
||||
root->addStretch(1);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void ProviderDetailPane::populate(const Providers::ProviderInstance &inst, bool hasStoredKey)
|
||||
{
|
||||
m_current = inst;
|
||||
m_currentHasStoredKey = hasStoredKey;
|
||||
const bool isUser = inst.isUserSource();
|
||||
const bool needsKey = !inst.apiKeyRef.isEmpty();
|
||||
|
||||
m_nameLabel->setText(inst.name);
|
||||
m_sourcePathLabel->setText(inst.sourcePath);
|
||||
|
||||
m_descriptionLabel->setText(
|
||||
inst.description.isEmpty() ? tr("No description provided.") : inst.description);
|
||||
|
||||
m_nameEdit->setText(inst.name);
|
||||
m_typeEdit->setText(inst.clientApi);
|
||||
m_descriptionEdit->setPlainText(inst.description);
|
||||
m_urlEdit->setText(inst.url);
|
||||
|
||||
m_apiKeyEdit->clear();
|
||||
m_apiKeyEdit->setEnabled(needsKey);
|
||||
m_apiKeySaveBtn->setEnabled(false);
|
||||
m_apiKeyClearBtn->setEnabled(needsKey && hasStoredKey);
|
||||
m_revealKeyBtn->setEnabled(needsKey);
|
||||
m_revealKeyBtn->setChecked(false);
|
||||
if (!needsKey) {
|
||||
m_apiKeyEdit->setPlaceholderText(tr("— not required (local provider)"));
|
||||
m_keyHint->setText(tr("This provider type does not use a key."));
|
||||
} else if (hasStoredKey) {
|
||||
m_apiKeyEdit->setPlaceholderText(tr("Stored — enter a new key to replace it."));
|
||||
m_keyHint->setText(tr("A key is stored. Type a new key and press Save key to "
|
||||
"replace it, or Clear to erase it."));
|
||||
} else {
|
||||
m_apiKeyEdit->setPlaceholderText(tr("Enter API key…"));
|
||||
m_keyHint->setText(tr("No key stored yet. Type a key and press Save key."));
|
||||
}
|
||||
|
||||
m_samplePreview->setText(
|
||||
QStringLiteral("# sample request line\nPOST %1/<agent endpoint>").arg(inst.url));
|
||||
applyPreviewPalette();
|
||||
|
||||
m_deleteBtn->setEnabled(isUser);
|
||||
m_dupBtn->setEnabled(true);
|
||||
m_editBtn->setVisible(isUser);
|
||||
m_openInEditorBtn->setEnabled(isUser);
|
||||
setEditing(false);
|
||||
|
||||
QString toml = QStringLiteral("# %1\n").arg(inst.sourcePath);
|
||||
toml += Providers::ProviderInstanceWriter::toToml(inst);
|
||||
m_rawToml->setPlainText(toml);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::clear()
|
||||
{
|
||||
m_current = {};
|
||||
m_nameLabel->setText(tr("Select a provider"));
|
||||
m_sourcePathLabel->clear();
|
||||
m_descriptionLabel->clear();
|
||||
m_nameEdit->clear();
|
||||
m_typeEdit->clear();
|
||||
m_descriptionEdit->clear();
|
||||
m_urlEdit->clear();
|
||||
m_apiKeyEdit->clear();
|
||||
m_apiKeyEdit->setEnabled(false);
|
||||
m_apiKeySaveBtn->setEnabled(false);
|
||||
m_apiKeyClearBtn->setEnabled(false);
|
||||
m_revealKeyBtn->setEnabled(false);
|
||||
m_samplePreview->clear();
|
||||
m_rawToml->clear();
|
||||
m_editBtn->setVisible(false);
|
||||
m_dupBtn->setEnabled(false);
|
||||
m_deleteBtn->setEnabled(false);
|
||||
m_openInEditorBtn->setEnabled(false);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::refreshKeyStatus(bool hasStoredKey)
|
||||
{
|
||||
m_currentHasStoredKey = hasStoredKey;
|
||||
const bool needsKey = !m_current.apiKeyRef.isEmpty();
|
||||
m_apiKeyClearBtn->setEnabled(needsKey && hasStoredKey);
|
||||
if (!needsKey)
|
||||
return;
|
||||
if (hasStoredKey) {
|
||||
m_apiKeyEdit->setPlaceholderText(tr("Stored — enter a new key to replace it."));
|
||||
m_keyHint->setText(tr("A key is stored. Type a new key and press Save key to "
|
||||
"replace it, or Clear to erase it."));
|
||||
} else {
|
||||
m_apiKeyEdit->setPlaceholderText(tr("Enter API key…"));
|
||||
m_keyHint->setText(tr("No key stored yet. Type a key and press Save key."));
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderDetailPane::setLaunchState(
|
||||
Providers::ProviderLauncher::State st, const QString &lastError)
|
||||
{
|
||||
const bool hasLaunch = !m_current.launch.isEmpty();
|
||||
m_launchSection->setVisible(true);
|
||||
m_launchEmptyHint->setVisible(!hasLaunch);
|
||||
m_launchCmdLabel->setVisible(hasLaunch);
|
||||
m_startBtn->setVisible(hasLaunch);
|
||||
m_stopBtn->setVisible(hasLaunch);
|
||||
m_restartBtn->setVisible(hasLaunch);
|
||||
m_launchStatusPill->setVisible(hasLaunch);
|
||||
m_launchTerminalToggle->setVisible(hasLaunch);
|
||||
|
||||
if (!hasLaunch) {
|
||||
m_launchEmptyHint->setText(tr(
|
||||
"No [launch] block. This provider is treated as external — "
|
||||
"the plugin will not spawn or supervise any process. "
|
||||
"Add a [launch] block to the TOML to have the plugin manage "
|
||||
"a local server here."));
|
||||
m_launchCmdLabel->clear();
|
||||
m_launchTerminal->clearContents();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString detachedNote = m_current.launch.detach
|
||||
? tr(" <span style='color:gray'>(detached — survives Qt Creator restart)</span>")
|
||||
: QString();
|
||||
m_launchCmdLabel->setText(
|
||||
QStringLiteral("<b>%1</b> %2%3")
|
||||
.arg(m_current.launch.command.toHtmlEscaped(),
|
||||
m_current.launch.args.join(QLatin1Char(' ')).toHtmlEscaped(),
|
||||
detachedNote));
|
||||
|
||||
QString statusText;
|
||||
switch (st) {
|
||||
case Providers::ProviderLauncher::Idle: statusText = tr("idle"); break;
|
||||
case Providers::ProviderLauncher::Starting: statusText = tr("starting…"); break;
|
||||
case Providers::ProviderLauncher::Probing: statusText = tr("probing…"); break;
|
||||
case Providers::ProviderLauncher::Ready: statusText = tr("ready"); break;
|
||||
case Providers::ProviderLauncher::Stopping: statusText = tr("stopping…"); break;
|
||||
case Providers::ProviderLauncher::Failed:
|
||||
statusText = lastError.isEmpty() ? tr("failed")
|
||||
: tr("failed — %1").arg(lastError);
|
||||
break;
|
||||
}
|
||||
m_launchStatusPill->setText(statusText);
|
||||
|
||||
const bool running = st == Providers::ProviderLauncher::Starting
|
||||
|| st == Providers::ProviderLauncher::Probing
|
||||
|| st == Providers::ProviderLauncher::Ready;
|
||||
m_startBtn->setEnabled(!running && st != Providers::ProviderLauncher::Stopping);
|
||||
m_stopBtn->setEnabled(running);
|
||||
m_restartBtn->setEnabled(running || st == Providers::ProviderLauncher::Failed);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::resetLaunchTerminal(const QByteArray &scrollback)
|
||||
{
|
||||
m_launchTerminal->clearContents();
|
||||
if (!scrollback.isEmpty())
|
||||
m_launchTerminal->writeToTerminal(scrollback, true);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::appendLaunchBytes(const QByteArray &chunk)
|
||||
{
|
||||
m_launchTerminal->writeToTerminal(chunk, true);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
if (event->type() == QEvent::PaletteChange || event->type() == QEvent::StyleChange) {
|
||||
applyPreviewPalette();
|
||||
applyTerminalPalette();
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderDetailPane::setEditing(bool on)
|
||||
{
|
||||
m_editing = on;
|
||||
m_nameEdit->setReadOnly(!on);
|
||||
m_descriptionEdit->setReadOnly(!on);
|
||||
m_urlEdit->setReadOnly(!on);
|
||||
m_editBtn->setVisible(!on && m_current.isUserSource());
|
||||
m_dupBtn->setVisible(!on);
|
||||
m_deleteBtn->setVisible(!on);
|
||||
m_cancelBtn->setVisible(on);
|
||||
m_saveBtn->setVisible(on);
|
||||
}
|
||||
|
||||
Providers::ProviderInstance ProviderDetailPane::collectEdits() const
|
||||
{
|
||||
Providers::ProviderInstance out = m_current;
|
||||
out.name = m_nameEdit->text().trimmed();
|
||||
out.description = m_descriptionEdit->toPlainText().trimmed();
|
||||
out.url = m_urlEdit->text().trimmed();
|
||||
return out;
|
||||
}
|
||||
|
||||
void ProviderDetailPane::applyPreviewPalette()
|
||||
{
|
||||
const bool dark = isDarkPalette(palette());
|
||||
const QString bg = dark ? QStringLiteral("#1f1f1f") : QStringLiteral("#f4f4f4");
|
||||
const QString bd = dark ? QStringLiteral("#3a3a3a") : QStringLiteral("#dcdcdc");
|
||||
m_samplePreview->setStyleSheet(QStringLiteral(
|
||||
"QLabel { background:%1; border:1px solid %2; }")
|
||||
.arg(bg, bd));
|
||||
}
|
||||
|
||||
void ProviderDetailPane::applyTerminalPalette()
|
||||
{
|
||||
if (!m_launchTerminal)
|
||||
return;
|
||||
const QPalette pal = palette();
|
||||
const bool dark = isDarkPalette(pal);
|
||||
const std::array<QColor, 16> ansi = dark
|
||||
? std::array<QColor, 16>{
|
||||
QColor("#000000"), QColor("#cd3131"), QColor("#0dbc79"),
|
||||
QColor("#e5e510"), QColor("#2472c8"), QColor("#bc3fbc"),
|
||||
QColor("#11a8cd"), QColor("#e5e5e5"),
|
||||
QColor("#666666"), QColor("#f14c4c"), QColor("#23d18b"),
|
||||
QColor("#f5f543"), QColor("#3b8eea"), QColor("#d670d6"),
|
||||
QColor("#29b8db"), QColor("#ffffff"),
|
||||
}
|
||||
: std::array<QColor, 16>{
|
||||
QColor("#000000"), QColor("#c91b00"), QColor("#00c200"),
|
||||
QColor("#c7c400"), QColor("#0037da"), QColor("#c930c7"),
|
||||
QColor("#00c5c7"), QColor("#c7c7c7"),
|
||||
QColor("#676767"), QColor("#ff6d67"), QColor("#5ff967"),
|
||||
QColor("#fefb67"), QColor("#6871ff"), QColor("#ff76ff"),
|
||||
QColor("#5ffdff"), QColor("#ffffff"),
|
||||
};
|
||||
std::array<QColor, 20> colors{};
|
||||
for (int i = 0; i < 16; ++i)
|
||||
colors[i] = ansi[i];
|
||||
colors[16] = pal.color(QPalette::Text);
|
||||
colors[17] = pal.color(QPalette::Base);
|
||||
colors[18] = pal.color(QPalette::Highlight);
|
||||
colors[19] = dark ? QColor("#5a5a40") : QColor("#fff59d");
|
||||
m_launchTerminal->setColors(colors);
|
||||
}
|
||||
|
||||
} // namespace QodeAssist::Settings
|
||||
Reference in New Issue
Block a user