diff --git a/CMakeLists.txt b/CMakeLists.txt index 70f7100..7e3f2b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) find_package(QtCreator REQUIRED COMPONENTS Core) -find_package(Qt6 COMPONENTS Core Gui Quick Widgets Network Test LinguistTools REQUIRED) +find_package(Qt6 COMPONENTS Core Gui Quick Widgets Network Svg Test LinguistTools REQUIRED) find_package(GTest) qt_standard_project_setup(I18N_TRANSLATED_LANGUAGES en) @@ -57,6 +57,7 @@ add_qtc_plugin(QodeAssist Qt::Quick Qt::Widgets Qt::Network + Qt::Svg QtCreator::ExtensionSystem QtCreator::Utils QtCreator::CPlusPlus diff --git a/qodeassist.cpp b/qodeassist.cpp index 1499ed3..a4395f6 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -57,6 +57,7 @@ #include "settings/ChatAssistantSettings.hpp" #include "settings/GeneralSettings.hpp" #include "settings/ProjectSettingsPanel.hpp" +#include "settings/QuickRefactorSettings.hpp" #include "settings/SettingsConstants.hpp" #include "templates/Templates.hpp" #include "widgets/CustomInstructionsManager.hpp" diff --git a/widgets/QuickRefactorDialog.cpp b/widgets/QuickRefactorDialog.cpp index 4c3bae4..851b2ad 100644 --- a/widgets/QuickRefactorDialog.cpp +++ b/widgets/QuickRefactorDialog.cpp @@ -22,6 +22,10 @@ #include "CustomInstructionsManager.hpp" #include "QodeAssisttr.h" +#include "settings/ConfigurationManager.hpp" +#include "settings/GeneralSettings.hpp" +#include "settings/QuickRefactorSettings.hpp" + #include #include #include @@ -30,12 +34,15 @@ #include #include #include +#include #include #include #include +#include #include #include #include +#include #include #include #include @@ -48,6 +55,43 @@ 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) : QDialog(parent) , m_lastInstructions(lastInstructions) @@ -75,6 +119,49 @@ void QuickRefactorDialog::setupUi() actionsLayout->addWidget(m_improveButton); 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(); + }); + mainLayout->addLayout(actionsLayout); QHBoxLayout *instructionsLayout = new QHBoxLayout(); @@ -149,6 +236,13 @@ void QuickRefactorDialog::setupUi() mainLayout->addWidget(m_textEdit); loadCustomCommands(); + loadAvailableConfigurations(); + + connect( + m_configComboBox, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &QuickRefactorDialog::onConfigurationChanged); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); @@ -476,4 +570,60 @@ void QuickRefactorDialog::onOpenInstructionsFolder() QDesktopServices::openUrl(url); } +QString QuickRefactorDialog::selectedConfiguration() const +{ + return m_selectedConfiguration; +} + +void QuickRefactorDialog::loadAvailableConfigurations() +{ + auto &manager = Settings::ConfigurationManager::instance(); + manager.loadConfigurations(Settings::ConfigurationType::QuickRefactor); + + QVector 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.qrEndpointMode.setValue( + settings.qrEndpointMode.indexForDisplay(config.endpointMode)); + settings.qrCustomEndpoint.setValue(config.customEndpoint); + + settings.writeSettings(); + } +} + } // namespace QodeAssist diff --git a/widgets/QuickRefactorDialog.hpp b/widgets/QuickRefactorDialog.hpp index df3f73f..5ad0dc4 100644 --- a/widgets/QuickRefactorDialog.hpp +++ b/widgets/QuickRefactorDialog.hpp @@ -46,6 +46,8 @@ public: Action selectedAction() const; + QString selectedConfiguration() const; + bool eventFilter(QObject *watched, QEvent *event) override; private slots: @@ -59,6 +61,8 @@ private slots: void onDeleteCustomCommand(); void onOpenInstructionsFolder(); void loadCustomCommands(); + void loadAvailableConfigurations(); + void onConfigurationChanged(int index); private: void setupUi(); @@ -73,11 +77,20 @@ private: QToolButton *m_editCommandButton; QToolButton *m_deleteCommandButton; QToolButton *m_openFolderButton; + QToolButton *m_toolsButton; + QToolButton *m_thinkingButton; QComboBox *m_commandsComboBox; + QComboBox *m_configComboBox; QLabel *m_instructionsLabel; Action m_selectedAction = Action::Custom; QString m_lastInstructions; + QString m_selectedConfiguration; + + QIcon m_toolsIconOn; + QIcon m_toolsIconOff; + QIcon m_thinkingIconOn; + QIcon m_thinkingIconOff; }; } // namespace QodeAssist