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:
@@ -21,8 +21,6 @@ public:
|
||||
|
||||
void hideError();
|
||||
|
||||
bool isErrorVisible() const { return !m_errorWidget.isNull(); }
|
||||
|
||||
protected:
|
||||
void identifyMatch(
|
||||
TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report) override;
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#include "CompletionHintHandler.hpp"
|
||||
#include "CompletionHintWidget.hpp"
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
CompletionHintHandler::CompletionHintHandler() = default;
|
||||
|
||||
CompletionHintHandler::~CompletionHintHandler()
|
||||
{
|
||||
hideHint();
|
||||
}
|
||||
|
||||
void CompletionHintHandler::showHint(TextEditor::TextEditorWidget *widget, QPoint position, int fontSize)
|
||||
{
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_hintWidget) {
|
||||
m_hintWidget = new CompletionHintWidget(widget, fontSize);
|
||||
}
|
||||
|
||||
m_hintWidget->move(position);
|
||||
m_hintWidget->show();
|
||||
m_hintWidget->raise();
|
||||
}
|
||||
|
||||
void CompletionHintHandler::hideHint()
|
||||
{
|
||||
if (m_hintWidget) {
|
||||
m_hintWidget->deleteLater();
|
||||
m_hintWidget = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool CompletionHintHandler::isHintVisible() const
|
||||
{
|
||||
return !m_hintWidget.isNull() && m_hintWidget->isVisible();
|
||||
}
|
||||
|
||||
void CompletionHintHandler::updateHintPosition(TextEditor::TextEditorWidget *widget, QPoint position)
|
||||
{
|
||||
if (!widget || !m_hintWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_hintWidget->move(position);
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPointer>
|
||||
#include <functional>
|
||||
|
||||
namespace TextEditor {
|
||||
class TextEditorWidget;
|
||||
}
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class CompletionHintWidget;
|
||||
|
||||
class CompletionHintHandler
|
||||
{
|
||||
public:
|
||||
CompletionHintHandler();
|
||||
~CompletionHintHandler();
|
||||
|
||||
void showHint(TextEditor::TextEditorWidget *widget, QPoint position, int fontSize);
|
||||
void hideHint();
|
||||
bool isHintVisible() const;
|
||||
void updateHintPosition(TextEditor::TextEditorWidget *widget, QPoint position);
|
||||
|
||||
private:
|
||||
QPointer<CompletionHintWidget> m_hintWidget;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#include "CompletionHintWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
CompletionHintWidget::CompletionHintWidget(QWidget *parent, int fontSize)
|
||||
: QWidget(parent)
|
||||
, m_isHovered(false)
|
||||
{
|
||||
m_accentColor = Utils::creatorTheme()->color(Utils::Theme::TextColorNormal);
|
||||
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
int triangleSize = qMax(6, fontSize / 2);
|
||||
setFixedSize(triangleSize, triangleSize);
|
||||
}
|
||||
|
||||
void CompletionHintWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QColor triangleColor = m_accentColor;
|
||||
triangleColor.setAlpha(m_isHovered ? 255 : 200);
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(triangleColor);
|
||||
|
||||
QPolygonF triangle;
|
||||
int w = width();
|
||||
int h = height();
|
||||
|
||||
triangle << QPointF(0, 0)
|
||||
<< QPointF(0, h)
|
||||
<< QPointF(w, h / 2.0);
|
||||
|
||||
painter.drawPolygon(triangle);
|
||||
}
|
||||
|
||||
void CompletionHintWidget::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_isHovered = true;
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
update();
|
||||
}
|
||||
|
||||
void CompletionHintWidget::leaveEvent(QEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_isHovered = false;
|
||||
setCursor(Qt::ArrowCursor);
|
||||
update();
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class CompletionHintWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CompletionHintWidget(QWidget *parent = nullptr, int fontSize = 12);
|
||||
~CompletionHintWidget() override = default;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
QColor m_accentColor;
|
||||
bool m_isHovered;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
void showProgress(TextEditor::TextEditorWidget *widget);
|
||||
void hideProgress();
|
||||
void setCancelCallback(std::function<void()> callback);
|
||||
bool isProgressVisible() const { return !m_progressWidget.isNull(); }
|
||||
|
||||
protected:
|
||||
void identifyMatch(
|
||||
|
||||
@@ -63,47 +63,6 @@ public:
|
||||
|
||||
return contextLines.join('\n');
|
||||
}
|
||||
|
||||
static QString extractLineContext(QTextDocument *doc, int position, bool before)
|
||||
{
|
||||
QTextCursor cursor(doc);
|
||||
cursor.setPosition(position);
|
||||
|
||||
if (before) {
|
||||
int posInBlock = cursor.positionInBlock();
|
||||
cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, posInBlock);
|
||||
return cursor.selectedText();
|
||||
} else {
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
return cursor.selectedText();
|
||||
}
|
||||
}
|
||||
|
||||
static QStringList extractSurroundingLines(QTextDocument *doc, int position, int linesBefore, int linesAfter)
|
||||
{
|
||||
QTextCursor cursor(doc);
|
||||
cursor.setPosition(position);
|
||||
QTextBlock currentBlock = cursor.block();
|
||||
|
||||
QStringList result;
|
||||
|
||||
QTextBlock blockBefore = currentBlock.previous();
|
||||
QStringList beforeLines;
|
||||
for (int i = 0; i < linesBefore && blockBefore.isValid(); ++i) {
|
||||
beforeLines.prepend(blockBefore.text());
|
||||
blockBefore = blockBefore.previous();
|
||||
}
|
||||
result.append(beforeLines);
|
||||
|
||||
QTextBlock blockAfter = currentBlock.next();
|
||||
for (int i = 0; i < linesAfter && blockAfter.isValid(); ++i) {
|
||||
result.append(blockAfter.text());
|
||||
blockAfter = blockAfter.next();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#include "EditorChatButton.hpp"
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
EditorChatButton::EditorChatButton(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_textColor = Utils::creatorTheme()->color(Utils::Theme::TextColorNormal);
|
||||
m_backgroundColor = Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal);
|
||||
|
||||
m_logoPixmap = QPixmap(":/resources/images/qoderassist-icon.png");
|
||||
|
||||
if (!m_logoPixmap.isNull()) {
|
||||
QImage image = m_logoPixmap.toImage();
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
for (int y = 0; y < image.height(); ++y) {
|
||||
for (int x = 0; x < image.width(); ++x) {
|
||||
QColor pixelColor = QColor::fromRgba(image.pixel(x, y));
|
||||
|
||||
int brightness = (pixelColor.red() + pixelColor.green() + pixelColor.blue()) / 3;
|
||||
|
||||
if (brightness > 200) {
|
||||
pixelColor.setAlpha(0);
|
||||
image.setPixelColor(x, y, pixelColor);
|
||||
} else if (pixelColor.alpha() > 0) {
|
||||
int alpha = pixelColor.alpha();
|
||||
pixelColor = m_textColor;
|
||||
pixelColor.setAlpha(alpha);
|
||||
image.setPixelColor(x, y, pixelColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_logoPixmap = QPixmap::fromImage(image);
|
||||
m_logoPixmap = m_logoPixmap.scaled(24, 24, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
setFixedSize(40, 40);
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
setToolTip(tr("Open QodeAssist Chat"));
|
||||
}
|
||||
|
||||
EditorChatButton::~EditorChatButton() = default;
|
||||
|
||||
void EditorChatButton::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QColor bgColor = m_backgroundColor;
|
||||
if (m_isPressed) {
|
||||
bgColor = bgColor.darker(120);
|
||||
} else if (m_isHovered) {
|
||||
bgColor = bgColor.lighter(110);
|
||||
}
|
||||
painter.fillRect(rect(), bgColor);
|
||||
|
||||
QRect buttonRect = rect().adjusted(4, 4, -4, -4);
|
||||
painter.setPen(Qt::NoPen);
|
||||
QColor buttonBgColor
|
||||
= m_isPressed ? Utils::creatorTheme()->color(Utils::Theme::BackgroundColorHover).darker(110)
|
||||
: Utils::creatorTheme()->color(Utils::Theme::BackgroundColorHover);
|
||||
|
||||
if (m_isHovered) {
|
||||
buttonBgColor = buttonBgColor.lighter(110);
|
||||
}
|
||||
painter.setBrush(buttonBgColor);
|
||||
painter.drawEllipse(buttonRect);
|
||||
|
||||
if (!m_logoPixmap.isNull()) {
|
||||
QRect logoRect(
|
||||
(width() - m_logoPixmap.width()) / 2,
|
||||
(height() - m_logoPixmap.height()) / 2,
|
||||
m_logoPixmap.width(),
|
||||
m_logoPixmap.height());
|
||||
painter.drawPixmap(logoRect, m_logoPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorChatButton::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
m_isPressed = true;
|
||||
update();
|
||||
}
|
||||
QWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void EditorChatButton::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && m_isPressed) {
|
||||
m_isPressed = false;
|
||||
update();
|
||||
if (rect().contains(event->pos())) {
|
||||
emit clicked();
|
||||
}
|
||||
}
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void EditorChatButton::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
m_isHovered = true;
|
||||
update();
|
||||
QWidget::enterEvent(event);
|
||||
}
|
||||
|
||||
void EditorChatButton::leaveEvent(QEvent *event)
|
||||
{
|
||||
m_isHovered = false;
|
||||
m_isPressed = false;
|
||||
update();
|
||||
QWidget::leaveEvent(event);
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class EditorChatButton : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EditorChatButton(QWidget *parent = nullptr);
|
||||
~EditorChatButton() override;
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void enterEvent(QEnterEvent *event) override;
|
||||
void leaveEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
QPixmap m_logoPixmap;
|
||||
QColor m_textColor;
|
||||
QColor m_backgroundColor;
|
||||
bool m_isPressed = false;
|
||||
bool m_isHovered = false;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#include "EditorChatButtonHandler.hpp"
|
||||
#include "EditorChatButton.hpp"
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <utils/tooltip/tooltip.h>
|
||||
#include <QPoint>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
EditorChatButtonHandler::~EditorChatButtonHandler()
|
||||
{
|
||||
delete m_chatButton;
|
||||
}
|
||||
|
||||
void EditorChatButtonHandler::showButton(TextEditor::TextEditorWidget *widget)
|
||||
{
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
m_widget = widget;
|
||||
|
||||
identifyMatch(widget, widget->textCursor().position(), [this](auto priority) {
|
||||
if (priority != Priority_None && m_widget) {
|
||||
const QTextCursor cursor = m_widget->textCursor();
|
||||
const QRect selectionRect = m_widget->cursorRect(cursor);
|
||||
m_cursorPosition = m_widget->viewport()->mapToGlobal(selectionRect.topLeft())
|
||||
- Utils::ToolTip::offsetFromPosition();
|
||||
operateTooltip(m_widget, m_cursorPosition);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EditorChatButtonHandler::hideButton()
|
||||
{
|
||||
Utils::ToolTip::hide();
|
||||
}
|
||||
|
||||
void EditorChatButtonHandler::identifyMatch(
|
||||
TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report)
|
||||
{
|
||||
if (!editorWidget) {
|
||||
report(Priority_None);
|
||||
return;
|
||||
}
|
||||
|
||||
report(Priority_Tooltip);
|
||||
}
|
||||
|
||||
void EditorChatButtonHandler::operateTooltip(
|
||||
TextEditor::TextEditorWidget *editorWidget, const QPoint &point)
|
||||
{
|
||||
if (!editorWidget)
|
||||
return;
|
||||
|
||||
if (!Utils::ToolTip::isVisible()) {
|
||||
m_chatButton = new EditorChatButton(editorWidget);
|
||||
m_buttonHeight = m_chatButton->height();
|
||||
|
||||
QPoint showPoint = point;
|
||||
showPoint.ry() -= m_buttonHeight;
|
||||
|
||||
Utils::ToolTip::show(showPoint, m_chatButton, editorWidget);
|
||||
} else {
|
||||
QPoint showPoint = point;
|
||||
showPoint.ry() -= m_buttonHeight;
|
||||
Utils::ToolTip::move(showPoint);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright (C) 2025-2026 Petr Mironychev
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Additional attribution terms under GPLv3 §7(b) apply — see LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "widgets/EditorChatButton.hpp"
|
||||
#include <texteditor/basehoverhandler.h>
|
||||
#include <QPointer>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class EditorChatButtonHandler : public TextEditor::BaseHoverHandler
|
||||
{
|
||||
public:
|
||||
explicit EditorChatButtonHandler() = default;
|
||||
~EditorChatButtonHandler() override;
|
||||
|
||||
void showButton(TextEditor::TextEditorWidget *widget);
|
||||
void hideButton();
|
||||
|
||||
signals:
|
||||
void chatButtonClicked(TextEditor::TextEditorWidget *widget);
|
||||
|
||||
protected:
|
||||
void identifyMatch(
|
||||
TextEditor::TextEditorWidget *editorWidget, int pos, ReportPriority report) override;
|
||||
void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override;
|
||||
|
||||
private:
|
||||
QPointer<TextEditor::TextEditorWidget> m_widget;
|
||||
QPoint m_cursorPosition;
|
||||
EditorChatButton *m_chatButton = nullptr;
|
||||
int m_buttonHeight = 0;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
@@ -47,16 +47,6 @@ ErrorWidget::~ErrorWidget()
|
||||
}
|
||||
}
|
||||
|
||||
void ErrorWidget::setErrorMessage(const QString &message)
|
||||
{
|
||||
m_errorMessage = message;
|
||||
QFont smallFont = font();
|
||||
smallFont.setPointSize(qMax(8, smallFont.pointSize() - 2));
|
||||
setFont(smallFont);
|
||||
setFixedSize(calculateSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void ErrorWidget::setupColors()
|
||||
{
|
||||
m_textColor = Utils::creatorTheme()->color(Utils::Theme::TextColorNormal);
|
||||
|
||||
@@ -19,10 +19,6 @@ public:
|
||||
explicit ErrorWidget(const QString &errorMessage, QWidget *parent = nullptr, int autoHideMs = 5000);
|
||||
~ErrorWidget();
|
||||
|
||||
void setErrorMessage(const QString &message);
|
||||
|
||||
QString errorMessage() const { return m_errorMessage; }
|
||||
|
||||
signals:
|
||||
void dismissed();
|
||||
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
#include "CustomInstructionsManager.hpp"
|
||||
#include "QodeAssisttr.h"
|
||||
|
||||
#include "settings/ConfigurationManager.hpp"
|
||||
#include "settings/GeneralSettings.hpp"
|
||||
#include "settings/QuickRefactorSettings.hpp"
|
||||
#include "settings/SettingsConstants.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
@@ -42,46 +40,11 @@
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
static QIcon createThemedIcon(const QString &svgPath, const QColor &color)
|
||||
{
|
||||
QSvgRenderer renderer(svgPath);
|
||||
if (!renderer.isValid()) {
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
QSize iconSize(16, 16);
|
||||
QPixmap pixmap(iconSize);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
renderer.render(&painter);
|
||||
painter.end();
|
||||
|
||||
QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
uchar *bits = image.bits();
|
||||
const int bytesPerPixel = 4;
|
||||
const int totalBytes = image.width() * image.height() * bytesPerPixel;
|
||||
|
||||
const int newR = color.red();
|
||||
const int newG = color.green();
|
||||
const int newB = color.blue();
|
||||
|
||||
for (int i = 0; i < totalBytes; i += bytesPerPixel) {
|
||||
int alpha = bits[i + 3];
|
||||
if (alpha > 0) {
|
||||
bits[i] = newB;
|
||||
bits[i + 1] = newG;
|
||||
bits[i + 2] = newR;
|
||||
}
|
||||
}
|
||||
|
||||
return QIcon(QPixmap::fromImage(image));
|
||||
}
|
||||
|
||||
QuickRefactorDialog::QuickRefactorDialog(QWidget *parent, const QString &lastInstructions)
|
||||
QuickRefactorDialog::QuickRefactorDialog(
|
||||
QWidget *parent, const QString &lastInstructions, bool refactorAgentAvailable)
|
||||
: QDialog(parent)
|
||||
, m_lastInstructions(lastInstructions)
|
||||
, m_refactorAgentAvailable(refactorAgentAvailable)
|
||||
{
|
||||
setWindowTitle(Tr::tr("Quick Refactor"));
|
||||
setupUi();
|
||||
@@ -113,48 +76,6 @@ void QuickRefactorDialog::setupUi()
|
||||
actionsLayout->addWidget(m_alternativeButton);
|
||||
actionsLayout->addStretch();
|
||||
|
||||
m_configComboBox = new QComboBox(this);
|
||||
m_configComboBox->setMinimumWidth(200);
|
||||
m_configComboBox->setToolTip(Tr::tr("Switch AI configuration"));
|
||||
actionsLayout->addWidget(m_configComboBox);
|
||||
|
||||
Utils::Theme *theme = Utils::creatorTheme();
|
||||
QColor iconColor = theme ? theme->color(Utils::Theme::TextColorNormal) : QColor(Qt::white);
|
||||
|
||||
m_toolsIconOn = createThemedIcon(":/qt/qml/ChatView/icons/tools-icon-on.svg", iconColor);
|
||||
m_toolsIconOff = createThemedIcon(":/qt/qml/ChatView/icons/tools-icon-off.svg", iconColor);
|
||||
|
||||
m_toolsButton = new QToolButton(this);
|
||||
m_toolsButton->setCheckable(true);
|
||||
m_toolsButton->setChecked(Settings::quickRefactorSettings().useTools());
|
||||
m_toolsButton->setIcon(m_toolsButton->isChecked() ? m_toolsIconOn : m_toolsIconOff);
|
||||
m_toolsButton->setToolTip(Tr::tr("Enable/Disable AI Tools"));
|
||||
m_toolsButton->setIconSize(QSize(16, 16));
|
||||
actionsLayout->addWidget(m_toolsButton);
|
||||
|
||||
connect(m_toolsButton, &QToolButton::toggled, this, [this](bool checked) {
|
||||
m_toolsButton->setIcon(checked ? m_toolsIconOn : m_toolsIconOff);
|
||||
Settings::quickRefactorSettings().useTools.setValue(checked);
|
||||
Settings::quickRefactorSettings().writeSettings();
|
||||
});
|
||||
|
||||
m_thinkingIconOn = createThemedIcon(":/qt/qml/ChatView/icons/thinking-icon-on.svg", iconColor);
|
||||
m_thinkingIconOff = createThemedIcon(":/qt/qml/ChatView/icons/thinking-icon-off.svg", iconColor);
|
||||
|
||||
m_thinkingButton = new QToolButton(this);
|
||||
m_thinkingButton->setCheckable(true);
|
||||
m_thinkingButton->setChecked(Settings::quickRefactorSettings().useThinking());
|
||||
m_thinkingButton->setIcon(m_thinkingButton->isChecked() ? m_thinkingIconOn : m_thinkingIconOff);
|
||||
m_thinkingButton->setToolTip(Tr::tr("Enable/Disable Thinking Mode"));
|
||||
m_thinkingButton->setIconSize(QSize(16, 16));
|
||||
actionsLayout->addWidget(m_thinkingButton);
|
||||
|
||||
connect(m_thinkingButton, &QToolButton::toggled, this, [this](bool checked) {
|
||||
m_thinkingButton->setIcon(checked ? m_thinkingIconOn : m_thinkingIconOff);
|
||||
Settings::quickRefactorSettings().useThinking.setValue(checked);
|
||||
Settings::quickRefactorSettings().writeSettings();
|
||||
});
|
||||
|
||||
m_settingsButton = new QToolButton(this);
|
||||
m_settingsButton->setIcon(Utils::Icons::SETTINGS_TOOLBAR.icon());
|
||||
m_settingsButton->setToolTip(Tr::tr("Open Quick Refactor Settings"));
|
||||
@@ -244,23 +165,36 @@ void QuickRefactorDialog::setupUi()
|
||||
&QuickRefactorDialog::onOpenInstructionsFolder);
|
||||
|
||||
loadCustomCommands();
|
||||
loadAvailableConfigurations();
|
||||
|
||||
connect(
|
||||
m_configComboBox,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this,
|
||||
&QuickRefactorDialog::onConfigurationChanged);
|
||||
|
||||
QDialogButtonBox *buttonBox
|
||||
= new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QuickRefactorDialog::validateAndAccept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
|
||||
QPushButton *cancelButton = buttonBox->button(QDialogButtonBox::Cancel);
|
||||
|
||||
|
||||
if (!m_refactorAgentAvailable) {
|
||||
if (okButton) {
|
||||
okButton->setEnabled(false);
|
||||
okButton->setToolTip(Tr::tr("Assign a Quick Refactor agent in the Pipelines settings"));
|
||||
}
|
||||
|
||||
QLabel *agentHint = new QLabel(
|
||||
Tr::tr("No Quick Refactor agent is set. "
|
||||
"<a href=\"pipelines\">Assign one in the Pipelines settings</a>."),
|
||||
this);
|
||||
agentHint->setWordWrap(true);
|
||||
agentHint->setTextInteractionFlags(
|
||||
Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
|
||||
connect(agentHint, &QLabel::linkActivated, this, [] {
|
||||
Settings::showSettings(Constants::QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID);
|
||||
});
|
||||
mainLayout->addWidget(agentHint);
|
||||
}
|
||||
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
if (okButton) {
|
||||
okButton->installEventFilter(this);
|
||||
}
|
||||
@@ -308,16 +242,6 @@ QString QuickRefactorDialog::instructions() const
|
||||
return m_instructionEdit->toPlainText().trimmed();
|
||||
}
|
||||
|
||||
void QuickRefactorDialog::setInstructions(const QString &instructions)
|
||||
{
|
||||
m_instructionEdit->setPlainText(instructions);
|
||||
}
|
||||
|
||||
QuickRefactorDialog::Action QuickRefactorDialog::selectedAction() const
|
||||
{
|
||||
return m_selectedAction;
|
||||
}
|
||||
|
||||
void QuickRefactorDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
QDialog::keyPressEvent(event);
|
||||
@@ -355,7 +279,6 @@ void QuickRefactorDialog::useLastInstructions()
|
||||
if (!m_lastInstructions.isEmpty()) {
|
||||
m_commandsComboBox->setCurrentIndex(0);
|
||||
m_instructionEdit->setPlainText(m_lastInstructions);
|
||||
m_selectedAction = Action::RepeatLast;
|
||||
}
|
||||
accept();
|
||||
}
|
||||
@@ -367,7 +290,6 @@ void QuickRefactorDialog::useImproveCodeTemplate()
|
||||
Tr::tr(
|
||||
"Improve the selected code by enhancing readability, efficiency, and maintainability. "
|
||||
"Follow best practices for C++/Qt and fix any potential issues."));
|
||||
m_selectedAction = Action::ImproveCode;
|
||||
accept();
|
||||
}
|
||||
|
||||
@@ -379,7 +301,6 @@ void QuickRefactorDialog::useAlternativeSolutionTemplate()
|
||||
"Suggest an alternative implementation approach for the selected code. "
|
||||
"Provide a different solution that might be cleaner, more efficient, "
|
||||
"or uses different Qt/C++ patterns or idioms."));
|
||||
m_selectedAction = Action::AlternativeSolution;
|
||||
accept();
|
||||
}
|
||||
|
||||
@@ -577,60 +498,6 @@ void QuickRefactorDialog::onOpenSettings()
|
||||
Settings::showSettings(Constants::QODE_ASSIST_QUICK_REFACTOR_SETTINGS_PAGE_ID);
|
||||
}
|
||||
|
||||
QString QuickRefactorDialog::selectedConfiguration() const
|
||||
{
|
||||
return m_selectedConfiguration;
|
||||
}
|
||||
|
||||
void QuickRefactorDialog::loadAvailableConfigurations()
|
||||
{
|
||||
auto &manager = Settings::ConfigurationManager::instance();
|
||||
manager.loadConfigurations(Settings::ConfigurationType::QuickRefactor);
|
||||
|
||||
QVector<Settings::AIConfiguration> configs = manager.configurations(
|
||||
Settings::ConfigurationType::QuickRefactor);
|
||||
|
||||
m_configComboBox->clear();
|
||||
m_configComboBox->addItem(Tr::tr("Current"), QString());
|
||||
|
||||
for (const Settings::AIConfiguration &config : configs) {
|
||||
m_configComboBox->addItem(config.name, config.id);
|
||||
}
|
||||
|
||||
auto &settings = Settings::generalSettings();
|
||||
QString currentProvider = settings.qrProvider.value();
|
||||
QString currentModel = settings.qrModel.value();
|
||||
QString currentConfigText = QString("%1/%2").arg(currentProvider, currentModel);
|
||||
m_configComboBox->setItemText(0, Tr::tr("Current (%1)").arg(currentConfigText));
|
||||
}
|
||||
|
||||
void QuickRefactorDialog::onConfigurationChanged(int index)
|
||||
{
|
||||
if (index == 0) {
|
||||
m_selectedConfiguration.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
QString configId = m_configComboBox->itemData(index).toString();
|
||||
m_selectedConfiguration = m_configComboBox->itemText(index);
|
||||
|
||||
auto &manager = Settings::ConfigurationManager::instance();
|
||||
Settings::AIConfiguration config
|
||||
= manager.getConfigurationById(configId, Settings::ConfigurationType::QuickRefactor);
|
||||
|
||||
if (!config.id.isEmpty()) {
|
||||
auto &settings = Settings::generalSettings();
|
||||
|
||||
settings.qrProvider.setValue(config.provider);
|
||||
settings.qrModel.setValue(config.model);
|
||||
settings.qrTemplate.setValue(config.templateName);
|
||||
settings.qrUrl.setValue(config.url);
|
||||
settings.qrCustomEndpoint.setValue(config.customEndpoint);
|
||||
|
||||
settings.writeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void QuickRefactorDialog::validateAndAccept()
|
||||
{
|
||||
QString instruction = m_instructionEdit->toPlainText().trimmed();
|
||||
|
||||
@@ -22,18 +22,13 @@ class QuickRefactorDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class Action { Custom, RepeatLast, ImproveCode, AlternativeSolution };
|
||||
|
||||
explicit QuickRefactorDialog(
|
||||
QWidget *parent = nullptr, const QString &lastInstructions = QString());
|
||||
QWidget *parent = nullptr,
|
||||
const QString &lastInstructions = QString(),
|
||||
bool refactorAgentAvailable = true);
|
||||
~QuickRefactorDialog() override = default;
|
||||
|
||||
QString instructions() const;
|
||||
void setInstructions(const QString &instructions);
|
||||
|
||||
Action selectedAction() const;
|
||||
|
||||
QString selectedConfiguration() const;
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
@@ -50,8 +45,6 @@ private slots:
|
||||
void onOpenInstructionsFolder();
|
||||
void onOpenSettings();
|
||||
void loadCustomCommands();
|
||||
void loadAvailableConfigurations();
|
||||
void onConfigurationChanged(int index);
|
||||
void validateAndAccept();
|
||||
|
||||
private:
|
||||
@@ -68,19 +61,10 @@ private:
|
||||
QToolButton *m_deleteCommandButton;
|
||||
QToolButton *m_openFolderButton;
|
||||
QToolButton *m_settingsButton;
|
||||
QToolButton *m_toolsButton;
|
||||
QToolButton *m_thinkingButton;
|
||||
QComboBox *m_commandsComboBox;
|
||||
QComboBox *m_configComboBox;
|
||||
|
||||
Action m_selectedAction = Action::Custom;
|
||||
QString m_lastInstructions;
|
||||
QString m_selectedConfiguration;
|
||||
|
||||
QIcon m_toolsIconOn;
|
||||
QIcon m_toolsIconOff;
|
||||
QIcon m_thinkingIconOn;
|
||||
QIcon m_thinkingIconOff;
|
||||
bool m_refactorAgentAvailable = true;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
||||
|
||||
@@ -382,11 +382,6 @@ void RefactorWidget::dimContextLines(const QString &contextBefore, const QString
|
||||
}
|
||||
}
|
||||
|
||||
QString RefactorWidget::getRefactoredText() const
|
||||
{
|
||||
return m_applyText;
|
||||
}
|
||||
|
||||
void RefactorWidget::setRange(const Utils::Text::Range &range)
|
||||
{
|
||||
m_range = range;
|
||||
|
||||
@@ -58,9 +58,7 @@ public:
|
||||
void setApplyText(const QString &text) { m_applyText = text; }
|
||||
void setRange(const Utils::Text::Range &range);
|
||||
void setEditorWidth(int width);
|
||||
|
||||
QString getRefactoredText() const;
|
||||
|
||||
|
||||
void setApplyCallback(std::function<void(const QString &)> callback);
|
||||
void setDeclineCallback(std::function<void()> callback);
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ public:
|
||||
const QString &contextAfter);
|
||||
|
||||
void hideRefactorWidget();
|
||||
|
||||
bool isWidgetVisible() const { return !m_refactorWidget.isNull(); }
|
||||
|
||||
void setApplyCallback(std::function<void(const QString &)> callback);
|
||||
void setDeclineCallback(std::function<void()> callback);
|
||||
|
||||
Reference in New Issue
Block a user