mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-07-12 06:11:14 -04:00
refactor: Improve UX
This commit is contained in:
@@ -36,6 +36,9 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
nf.setPixelSize(15);
|
||||
m_nameLabel->setFont(nf);
|
||||
|
||||
m_sourceBadge = new QLabel(this);
|
||||
m_sourceBadge->setVisible(false);
|
||||
|
||||
m_sourcePathLabel = new QLabel(this);
|
||||
m_sourcePathLabel->setFont(monospaceFont(11));
|
||||
QPalette spp = m_sourcePathLabel->palette();
|
||||
@@ -66,11 +69,10 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
setEditing(false);
|
||||
populate(m_current, m_currentHasStoredKey);
|
||||
});
|
||||
connect(m_saveBtn, &QPushButton::clicked, this, [this] {
|
||||
emit saveRequested(collectEdits());
|
||||
connect(m_saveBtn, &QPushButton::clicked, this, [this] { emit saveRequested(collectEdits()); });
|
||||
connect(m_openInEditorBtn, &QPushButton::clicked, this, [this] {
|
||||
emit openInEditorRequested(m_current.sourcePath);
|
||||
});
|
||||
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(); });
|
||||
|
||||
@@ -88,6 +90,7 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
titleRow->setContentsMargins(0, 0, 0, 0);
|
||||
titleRow->setSpacing(8);
|
||||
titleRow->addWidget(m_nameLabel);
|
||||
titleRow->addWidget(m_sourceBadge, 0, Qt::AlignVCenter);
|
||||
titleRow->addStretch(1);
|
||||
|
||||
auto *headerLeft = new QVBoxLayout;
|
||||
@@ -111,7 +114,7 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
m_descriptionLabel->setWordWrap(true);
|
||||
m_descriptionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
|
||||
auto *identitySection = new SectionBox(tr("Identity"), this);
|
||||
m_identitySection = new SectionBox(tr("Identity"), this);
|
||||
m_nameEdit = new QLineEdit(this);
|
||||
m_descriptionEdit = new QPlainTextEdit(this);
|
||||
m_descriptionEdit->setMaximumHeight(60);
|
||||
@@ -121,29 +124,12 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
identityGrid->setHorizontalSpacing(8);
|
||||
identityGrid->setVerticalSpacing(4);
|
||||
FormBuilder(identityGrid).row(tr("Name:"), m_nameEdit).row(tr("Description:"), m_descriptionEdit);
|
||||
identitySection->bodyLayout()->addLayout(identityGrid);
|
||||
m_identitySection->bodyLayout()->addLayout(identityGrid);
|
||||
m_identitySection->setVisible(false);
|
||||
|
||||
auto *endpointSection = new SectionBox(tr("Endpoint"), this);
|
||||
auto *configSection = new SectionBox(tr("Configuration"), 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);
|
||||
FormBuilder(endpointGrid).row(tr("URL:"), 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…"));
|
||||
@@ -182,8 +168,7 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
emit apiKeySaveRequested(key);
|
||||
m_apiKeyEdit->clear();
|
||||
});
|
||||
connect(m_apiKeyClearBtn, &QPushButton::clicked, this,
|
||||
[this] { emit apiKeyClearRequested(); });
|
||||
connect(m_apiKeyClearBtn, &QPushButton::clicked, this, [this] { emit apiKeyClearRequested(); });
|
||||
m_keyHint = makeHintLabel(QString{}, this);
|
||||
|
||||
auto *keyRow = new QHBoxLayout;
|
||||
@@ -194,15 +179,24 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
keyRow->addWidget(m_apiKeySaveBtn);
|
||||
keyRow->addWidget(m_apiKeyClearBtn);
|
||||
|
||||
auto *credGrid = new QGridLayout;
|
||||
credGrid->setContentsMargins(0, 0, 0, 0);
|
||||
credGrid->setHorizontalSpacing(8);
|
||||
credGrid->setVerticalSpacing(4);
|
||||
FormBuilder credForm(credGrid);
|
||||
credForm.row(tr("API key:"), keyRow);
|
||||
credGrid->addWidget(m_legacyKeyBtn, credForm.currentRow(), 1, Qt::AlignLeft);
|
||||
credGrid->addWidget(m_keyHint, credForm.currentRow() + 1, 1);
|
||||
credSection->bodyLayout()->addLayout(credGrid);
|
||||
auto *configGrid = new QGridLayout;
|
||||
configGrid->setContentsMargins(0, 0, 0, 0);
|
||||
configGrid->setHorizontalSpacing(8);
|
||||
configGrid->setVerticalSpacing(4);
|
||||
FormBuilder configForm(configGrid);
|
||||
configForm.row(tr("API key:"), keyRow);
|
||||
{
|
||||
int row = configForm.currentRow();
|
||||
configGrid->addWidget(m_legacyKeyBtn, row, 1, Qt::AlignLeft);
|
||||
configGrid->addWidget(m_keyHint, row + 1, 1);
|
||||
configForm = FormBuilder(configGrid, row + 2);
|
||||
}
|
||||
configForm.row(
|
||||
tr("URL:"),
|
||||
m_urlEdit,
|
||||
tr("Base URL. Agents append their endpoint path "
|
||||
"(e.g. /chat/completions) to this. Editable via Edit…"));
|
||||
configSection->bodyLayout()->addLayout(configGrid);
|
||||
|
||||
m_launchSection = new SectionBox(tr("Launch"), this);
|
||||
m_launchEmptyHint = new QLabel(this);
|
||||
@@ -218,12 +212,15 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
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); });
|
||||
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);
|
||||
@@ -283,9 +280,8 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
root->addLayout(headerRow);
|
||||
root->addWidget(headerSep);
|
||||
root->addWidget(m_descriptionLabel);
|
||||
root->addWidget(identitySection);
|
||||
root->addWidget(endpointSection);
|
||||
root->addWidget(credSection);
|
||||
root->addWidget(m_identitySection);
|
||||
root->addWidget(configSection);
|
||||
root->addWidget(m_launchSection);
|
||||
root->addWidget(m_rawToggle, 0, Qt::AlignLeft);
|
||||
root->addWidget(m_rawToml);
|
||||
@@ -302,6 +298,9 @@ void ProviderDetailPane::populate(const Providers::ProviderInstance &inst, bool
|
||||
const bool needsKey = !inst.apiKeyRef.isEmpty();
|
||||
|
||||
m_nameLabel->setText(inst.name);
|
||||
m_sourceBadge->setText(isUser ? tr("User") : tr("Bundled"));
|
||||
m_sourceBadge->setVisible(true);
|
||||
styleSourceBadge(m_sourceBadge, isUser);
|
||||
m_sourcePathLabel->setText(inst.sourcePath);
|
||||
|
||||
m_descriptionLabel->setText(
|
||||
@@ -323,8 +322,9 @@ void ProviderDetailPane::populate(const Providers::ProviderInstance &inst, bool
|
||||
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."));
|
||||
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."));
|
||||
@@ -341,10 +341,6 @@ void ProviderDetailPane::populate(const Providers::ProviderInstance &inst, bool
|
||||
m_legacyKeyBtn->setVisible(false);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -360,6 +356,7 @@ void ProviderDetailPane::clear()
|
||||
{
|
||||
m_current = {};
|
||||
m_nameLabel->setText(tr("Select a provider"));
|
||||
m_sourceBadge->setVisible(false);
|
||||
m_sourcePathLabel->clear();
|
||||
m_descriptionLabel->clear();
|
||||
m_nameEdit->clear();
|
||||
@@ -373,7 +370,6 @@ void ProviderDetailPane::clear()
|
||||
m_revealKeyBtn->setEnabled(false);
|
||||
m_legacyKeyValue.clear();
|
||||
m_legacyKeyBtn->setVisible(false);
|
||||
m_samplePreview->clear();
|
||||
m_rawToml->clear();
|
||||
m_editBtn->setVisible(false);
|
||||
m_dupBtn->setEnabled(false);
|
||||
@@ -390,8 +386,9 @@ void ProviderDetailPane::refreshKeyStatus(bool hasStoredKey)
|
||||
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."));
|
||||
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."));
|
||||
@@ -412,11 +409,11 @@ void ProviderDetailPane::setLaunchState(
|
||||
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_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;
|
||||
@@ -429,22 +426,31 @@ void ProviderDetailPane::setLaunchState(
|
||||
Utils::creatorColor(Utils::Theme::PanelTextColorMid).name(),
|
||||
tr("(detached — survives Qt Creator restart)"))
|
||||
: QString();
|
||||
m_launchCmdLabel->setText(
|
||||
QStringLiteral("<b>%1</b> %2%3")
|
||||
.arg(m_current.launch.command.toHtmlEscaped(),
|
||||
m_current.launch.args.join(QLatin1Char(' ')).toHtmlEscaped(),
|
||||
detachedNote));
|
||||
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::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);
|
||||
statusText = lastError.isEmpty() ? tr("failed") : tr("failed — %1").arg(lastError);
|
||||
break;
|
||||
}
|
||||
m_launchStatusPill->setText(statusText);
|
||||
@@ -473,8 +479,9 @@ void ProviderDetailPane::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
if (event->type() == QEvent::PaletteChange || event->type() == QEvent::StyleChange) {
|
||||
applyPreviewPalette();
|
||||
applyTerminalPalette();
|
||||
if (!m_current.name.isEmpty())
|
||||
styleSourceBadge(m_sourceBadge, m_current.isUserSource());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,6 +498,7 @@ void ProviderDetailPane::showRevealedKey(const QString &key)
|
||||
void ProviderDetailPane::setEditing(bool on)
|
||||
{
|
||||
m_editing = on;
|
||||
m_identitySection->setVisible(on);
|
||||
m_nameEdit->setReadOnly(!on);
|
||||
m_descriptionEdit->setReadOnly(!on);
|
||||
m_urlEdit->setReadOnly(!on);
|
||||
@@ -510,15 +518,6 @@ Providers::ProviderInstance ProviderDetailPane::collectEdits() const
|
||||
return out;
|
||||
}
|
||||
|
||||
void ProviderDetailPane::applyPreviewPalette()
|
||||
{
|
||||
m_samplePreview->setStyleSheet(
|
||||
QStringLiteral("QLabel { background:%1; border:1px solid %2; }")
|
||||
.arg(
|
||||
cssColor(Utils::creatorColor(Utils::Theme::BackgroundColorNormal)),
|
||||
cssColor(Utils::creatorColor(Utils::Theme::SplitterColor))));
|
||||
}
|
||||
|
||||
void ProviderDetailPane::applyTerminalPalette()
|
||||
{
|
||||
if (!m_launchTerminal)
|
||||
|
||||
Reference in New Issue
Block a user