diff --git a/ChatView/CMakeLists.txt b/ChatView/CMakeLists.txt index da55f52..28459b6 100644 --- a/ChatView/CMakeLists.txt +++ b/ChatView/CMakeLists.txt @@ -25,6 +25,14 @@ qt_add_qml_module(QodeAssistChatView icons/close-light.svg icons/link-file-light.svg icons/link-file-dark.svg + icons/load-chat-dark.svg + icons/save-chat-dark.svg + icons/clean-icon-dark.svg + icons/file-in-system.svg + icons/window-lock.svg + icons/window-unlock.svg + icons/chat-icon.svg + icons/chat-pause-icon.svg SOURCES ChatWidget.hpp ChatWidget.cpp ChatModel.hpp ChatModel.cpp @@ -33,6 +41,7 @@ qt_add_qml_module(QodeAssistChatView MessagePart.hpp ChatUtils.h ChatUtils.cpp ChatSerializer.hpp ChatSerializer.cpp + ChatView.hpp ChatView.cpp ) target_link_libraries(QodeAssistChatView diff --git a/ChatView/ChatRootView.cpp b/ChatView/ChatRootView.cpp index fc81c1d..be9668d 100644 --- a/ChatView/ChatRootView.cpp +++ b/ChatView/ChatRootView.cpp @@ -66,6 +66,10 @@ ChatRootView::ChatRootView(QQuickItem *parent) this, &ChatRootView::autosave); + connect(m_clientInterface, &ClientInterface::messageReceivedCompletely, this, [this]() { + this->setRequestProgressStatus(false); + }); + connect( m_clientInterface, &ClientInterface::messageReceivedCompletely, @@ -156,6 +160,7 @@ void ChatRootView::sendMessage(const QString &message) m_clientInterface->sendMessage(message, m_attachmentFiles, m_linkedFiles); clearAttachmentFiles(); + setRequestProgressStatus(true); } void ChatRootView::copyToClipboard(const QString &text) @@ -166,6 +171,7 @@ void ChatRootView::copyToClipboard(const QString &text) void ChatRootView::cancelRequest() { m_clientInterface->cancelRequest(); + setRequestProgressStatus(false); } void ChatRootView::clearAttachmentFiles() @@ -602,4 +608,17 @@ int ChatRootView::textFormat() const return Settings::chatAssistantSettings().textFormat(); } +bool ChatRootView::isRequestInProgress() const +{ + return m_isRequestInProgress; +} + +void ChatRootView::setRequestProgressStatus(bool state) +{ + if (m_isRequestInProgress == state) + return; + m_isRequestInProgress = state; + emit isRequestInProgressChanged(); +} + } // namespace QodeAssist::Chat diff --git a/ChatView/ChatRootView.hpp b/ChatView/ChatRootView.hpp index cd0afe2..865dd60 100644 --- a/ChatView/ChatRootView.hpp +++ b/ChatView/ChatRootView.hpp @@ -43,6 +43,8 @@ class ChatRootView : public QQuickItem Q_PROPERTY(int codeFontSize READ codeFontSize NOTIFY codeFontSizeChanged FINAL) Q_PROPERTY(int textFontSize READ textFontSize NOTIFY textFontSizeChanged FINAL) Q_PROPERTY(int textFormat READ textFormat NOTIFY textFormatChanged FINAL) + Q_PROPERTY( + bool isRequestInProgress READ isRequestInProgress NOTIFY isRequestInProgressChanged FINAL) QML_ELEMENT @@ -92,6 +94,9 @@ public: int textFontSize() const; int textFormat() const; + bool isRequestInProgress() const; + void setRequestProgressStatus(bool state); + public slots: void sendMessage(const QString &message); void copyToClipboard(const QString &text); @@ -112,6 +117,8 @@ signals: void codeFontSizeChanged(); void textFontSizeChanged(); void textFormatChanged(); + void chatRequestStarted(); + void isRequestInProgressChanged(); private: QString getChatsHistoryDir() const; @@ -128,6 +135,7 @@ private: int m_inputTokensCount{0}; bool m_isSyncOpenFiles; QList m_currentEditors; + bool m_isRequestInProgress; }; } // namespace QodeAssist::Chat diff --git a/ChatView/ChatView.cpp b/ChatView/ChatView.cpp new file mode 100644 index 0000000..848022f --- /dev/null +++ b/ChatView/ChatView.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024-2025 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#include "ChatView.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace { +constexpr Qt::WindowFlags baseFlags = Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint + | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint; +} + +namespace QodeAssist::Chat { + +ChatView::ChatView() + : m_isPin(false) +{ + setTitle("QodeAssist Chat"); + engine()->rootContext()->setContextProperty("_chatview", this); + setSource(QUrl("qrc:/qt/qml/ChatView/qml/RootItem.qml")); + setResizeMode(QQuickView::SizeRootObjectToView); + setMinimumSize({400, 300}); + setFlags(baseFlags); + + if (auto action = Core::ActionManager::command("QodeAssist.CloseChatView")) { + m_closeShortcut = new QShortcut(action->keySequence(), this); + connect(m_closeShortcut, &QShortcut::activated, this, &QQuickView::close); + + connect(action, &Core::Command::keySequenceChanged, this, [action, this]() { + if (m_closeShortcut) { + m_closeShortcut->setKey(action->keySequence()); + } + }); + } + + restoreSettings(); +} + +void ChatView::closeEvent(QCloseEvent *event) +{ + saveSettings(); + event->accept(); +} + +void ChatView::saveSettings() +{ + QSettings settings; + settings.setValue("QodeAssist/ChatView/geometry", geometry()); + settings.setValue("QodeAssist/ChatView/pinned", m_isPin); +} + +void ChatView::restoreSettings() +{ + QSettings settings; + const QRect savedGeometry + = settings.value("QodeAssist/ChatView/geometry", QRect(100, 100, 800, 600)).toRect(); + setGeometry(savedGeometry); + + const bool pinned = settings.value("QodeAssist/ChatView/pinned", false).toBool(); + setIsPin(pinned); +} + +bool ChatView::isPin() const +{ + return m_isPin; +} + +void ChatView::setIsPin(bool newIsPin) +{ + if (m_isPin == newIsPin) + return; + m_isPin = newIsPin; + + if (m_isPin) { + setFlags(baseFlags | Qt::WindowStaysOnTopHint); + } else { + setFlags(baseFlags); + } + + emit isPinChanged(); +} + +} // namespace QodeAssist::Chat diff --git a/ChatView/ChatView.hpp b/ChatView/ChatView.hpp new file mode 100644 index 0000000..ec3a1fe --- /dev/null +++ b/ChatView/ChatView.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024-2025 Petr Mironychev + * + * This file is part of QodeAssist. + * + * QodeAssist is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QodeAssist is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QodeAssist. If not, see . + */ + +#pragma once + +#include +#include + +namespace QodeAssist::Chat { + +class ChatView : public QQuickView +{ + Q_OBJECT + Q_PROPERTY(bool isPin READ isPin WRITE setIsPin NOTIFY isPinChanged FINAL) +public: + ChatView(); + + bool isPin() const; + void setIsPin(bool newIsPin); + +signals: + void isPinChanged(); + +protected: + void closeEvent(QCloseEvent *event) override; + +private: + void saveSettings(); + void restoreSettings(); + + bool m_isPin; + QShortcut *m_closeShortcut; +}; + +} // namespace QodeAssist::Chat diff --git a/ChatView/icons/chat-icon.svg b/ChatView/icons/chat-icon.svg new file mode 100644 index 0000000..1bda6a2 --- /dev/null +++ b/ChatView/icons/chat-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/ChatView/icons/chat-pause-icon.svg b/ChatView/icons/chat-pause-icon.svg new file mode 100644 index 0000000..2ef9b1c --- /dev/null +++ b/ChatView/icons/chat-pause-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/ChatView/icons/clean-icon-dark.svg b/ChatView/icons/clean-icon-dark.svg new file mode 100644 index 0000000..95eaa61 --- /dev/null +++ b/ChatView/icons/clean-icon-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ChatView/icons/file-in-system.svg b/ChatView/icons/file-in-system.svg new file mode 100644 index 0000000..06a9fee --- /dev/null +++ b/ChatView/icons/file-in-system.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/ChatView/icons/load-chat-dark.svg b/ChatView/icons/load-chat-dark.svg new file mode 100644 index 0000000..bf3b413 --- /dev/null +++ b/ChatView/icons/load-chat-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ChatView/icons/save-chat-dark.svg b/ChatView/icons/save-chat-dark.svg new file mode 100644 index 0000000..857ad2f --- /dev/null +++ b/ChatView/icons/save-chat-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ChatView/icons/window-lock.svg b/ChatView/icons/window-lock.svg new file mode 100644 index 0000000..603994d --- /dev/null +++ b/ChatView/icons/window-lock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ChatView/icons/window-unlock.svg b/ChatView/icons/window-unlock.svg new file mode 100644 index 0000000..6f7a59e --- /dev/null +++ b/ChatView/icons/window-unlock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ChatView/qml/Badge.qml b/ChatView/qml/Badge.qml index 1cd2f4f..247e4ca 100644 --- a/ChatView/qml/Badge.qml +++ b/ChatView/qml/Badge.qml @@ -23,6 +23,7 @@ Rectangle { id: root property alias text: badgeText.text + property alias hovered: mouse.hovered implicitWidth: badgeText.implicitWidth + root.radius implicitHeight: badgeText.implicitHeight + 6 @@ -37,4 +38,10 @@ Rectangle { anchors.centerIn: parent color: palette.buttonText } + + HoverHandler { + id: mouse + + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } } diff --git a/ChatView/qml/RootItem.qml b/ChatView/qml/RootItem.qml index dcf0ad3..69a6f5f 100644 --- a/ChatView/qml/RootItem.qml +++ b/ChatView/qml/RootItem.qml @@ -70,12 +70,17 @@ ChatRootView { loadButton.onClicked: root.showLoadDialog() clearButton.onClicked: root.clearChat() tokensBadge { - text: qsTr("tokens:%1/%2").arg(root.inputTokensCount).arg(root.chatModel.tokensThreshold) + text: qsTr("%1/%2").arg(root.inputTokensCount).arg(root.chatModel.tokensThreshold) } recentPath { text: qsTr("Latest chat file name: %1").arg(root.chatFileName.length > 0 ? root.chatFileName : "Unsaved") } openChatHistory.onClicked: root.openChatHistoryFolder() + pinButton { + visible: typeof _chatview !== 'undefined' + checked: typeof _chatview !== 'undefined' ? _chatview.isPin : false + onCheckedChanged: _chatview.isPin = topBar.pinButton.checked + } } ListView { @@ -203,8 +208,9 @@ ChatRootView { Layout.preferredWidth: parent.width Layout.preferredHeight: 40 - sendButton.onClicked: root.sendChatMessage() - stopButton.onClicked: root.cancelRequest() + sendButton.onClicked: !root.isRequestInProgress ? root.sendChatMessage() + : root.cancelRequest() + isRequestInProgress: root.isRequestInProgress syncOpenFiles { checked: root.isSyncOpenFiles onCheckedChanged: root.setIsSyncOpenFiles(bottomBar.syncOpenFiles.checked) @@ -229,4 +235,8 @@ ChatRootView { messageInput.text = "" scrollToBottom() } + + Component.onCompleted: { + messageInput.forceActiveFocus() + } } diff --git a/ChatView/qml/parts/BottomBar.qml b/ChatView/qml/parts/BottomBar.qml index 016e04a..dc74141 100644 --- a/ChatView/qml/parts/BottomBar.qml +++ b/ChatView/qml/parts/BottomBar.qml @@ -26,11 +26,12 @@ Rectangle { id: root property alias sendButton: sendButtonId - property alias stopButton: stopButtonId property alias syncOpenFiles: syncOpenFilesId property alias attachFiles: attachFilesId property alias linkFiles: linkFilesId + property bool isRequestInProgress: false + color: palette.window.hslLightness > 0.5 ? Qt.darker(palette.window, 1.1) : Qt.lighter(palette.window, 1.1) @@ -51,13 +52,16 @@ Rectangle { QoAButton { id: sendButtonId - text: qsTr("Send") - } - - QoAButton { - id: stopButtonId - - text: qsTr("Stop") + icon { + source: !root.isRequestInProgress ? "qrc:/qt/qml/ChatView/icons/chat-icon.svg" + : "qrc:/qt/qml/ChatView/icons/chat-pause-icon.svg" + height: 15 + width: 15 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: !root.isRequestInProgress ? qsTr("Send message to LLM") + : qsTr("Stop") } QoAButton { @@ -68,7 +72,9 @@ Rectangle { height: 15 width: 8 } - text: qsTr("Attach files") + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Attach file to message") } QoAButton { @@ -79,7 +85,9 @@ Rectangle { height: 15 width: 8 } - text: qsTr("Link files") + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Link file to context") } CheckBox { diff --git a/ChatView/qml/parts/TopBar.qml b/ChatView/qml/parts/TopBar.qml index d57aee5..7aad2ff 100644 --- a/ChatView/qml/parts/TopBar.qml +++ b/ChatView/qml/parts/TopBar.qml @@ -19,6 +19,7 @@ import QtQuick import QtQuick.Layouts +import QtQuick.Controls import ChatView Rectangle { @@ -30,6 +31,7 @@ Rectangle { property alias tokensBadge: tokensBadgeId property alias recentPath: recentPathId property alias openChatHistory: openChatHistoryId + property alias pinButton: pinButtonId color: palette.window.hslLightness > 0.5 ? Qt.darker(palette.window, 1.1) : @@ -46,22 +48,61 @@ Rectangle { spacing: 10 + QoAButton { + id: pinButtonId + + checkable: true + + icon { + source: checked ? "qrc:/qt/qml/ChatView/icons/window-lock.svg" + : "qrc:/qt/qml/ChatView/icons/window-unlock.svg" + color: palette.window.hslLightness > 0.5 ? "#000000" : "#FFFFFF" + height: 15 + width: 15 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: checked ? qsTr("Unpin chat window") + : qsTr("Pin chat window to the top") + } + QoAButton { id: saveButtonId - text: qsTr("Save") + icon { + source: "qrc:/qt/qml/ChatView/icons/save-chat-dark.svg" + height: 15 + width: 8 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Save chat to *.json file") } QoAButton { id: loadButtonId - text: qsTr("Load") + icon { + source: "qrc:/qt/qml/ChatView/icons/load-chat-dark.svg" + height: 15 + width: 8 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Load chat from *.json file") } QoAButton { id: clearButtonId - text: qsTr("Clear") + icon { + source: "qrc:/qt/qml/ChatView/icons/clean-icon-dark.svg" + height: 15 + width: 8 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Clean chat") } Text { @@ -74,7 +115,14 @@ Rectangle { QoAButton { id: openChatHistoryId - text: qsTr("Show in system") + icon { + source: "qrc:/qt/qml/ChatView/icons/file-in-system.svg" + height: 15 + width: 15 + } + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Show in system") } Item { @@ -83,6 +131,10 @@ Rectangle { Badge { id: tokensBadgeId + + ToolTip.visible: hovered + ToolTip.delay: 250 + ToolTip.text: qsTr("Current amount tokens in chat and LLM limit threshold") } } } diff --git a/QodeAssistClient.hpp b/QodeAssistClient.hpp index fb2fde0..e812d22 100644 --- a/QodeAssistClient.hpp +++ b/QodeAssistClient.hpp @@ -24,6 +24,8 @@ #pragma once +#include + #include "LLMClientInterface.hpp" #include "LSPCompletion.hpp" #include "QuickRefactorHandler.hpp" @@ -37,6 +39,7 @@ namespace QodeAssist { class QodeAssistClient : public LanguageClient::Client { + Q_OBJECT public: explicit QodeAssistClient(LLMClientInterface *clientInterface); ~QodeAssistClient() override; diff --git a/UpdateStatusWidget.cpp b/UpdateStatusWidget.cpp index f81c0cc..53a628b 100644 --- a/UpdateStatusWidget.cpp +++ b/UpdateStatusWidget.cpp @@ -33,6 +33,9 @@ UpdateStatusWidget::UpdateStatusWidget(QWidget *parent) m_actionButton = new QToolButton(this); m_actionButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_chatButton = new QToolButton(this); + m_chatButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_versionLabel = new QLabel(this); m_versionLabel->setVisible(false); @@ -41,6 +44,7 @@ UpdateStatusWidget::UpdateStatusWidget(QWidget *parent) m_updateButton->setStyleSheet("QPushButton { padding: 2px 8px; }"); layout->addWidget(m_actionButton); + layout->addWidget(m_chatButton); layout->addWidget(m_versionLabel); layout->addWidget(m_updateButton); } @@ -64,6 +68,11 @@ void UpdateStatusWidget::hideUpdateInfo() m_updateButton->setVisible(false); } +void UpdateStatusWidget::setChatButtonAction(QAction *action) +{ + m_chatButton->setDefaultAction(action); +} + QPushButton *UpdateStatusWidget::updateButton() const { return m_updateButton; diff --git a/UpdateStatusWidget.hpp b/UpdateStatusWidget.hpp index 915cce0..69833fb 100644 --- a/UpdateStatusWidget.hpp +++ b/UpdateStatusWidget.hpp @@ -36,11 +36,13 @@ public: void setDefaultAction(QAction *action); void showUpdateAvailable(const QString &version); void hideUpdateInfo(); + void setChatButtonAction(QAction *action); QPushButton *updateButton() const; private: QToolButton *m_actionButton; + QToolButton *m_chatButton; QLabel *m_versionLabel; QPushButton *m_updateButton; }; diff --git a/qodeassist.cpp b/qodeassist.cpp index 38f0ff0..5d8a40b 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -42,6 +42,7 @@ #include #include +#include #include "ConfigurationManager.hpp" #include "QodeAssistClient.hpp" #include "UpdateStatusWidget.hpp" @@ -53,17 +54,18 @@ #include "llmcore/ProvidersManager.hpp" #include "logger/RequestPerformanceLogger.hpp" #include "providers/Providers.hpp" +#include "settings/ChatAssistantSettings.hpp" #include "settings/GeneralSettings.hpp" #include "settings/ProjectSettingsPanel.hpp" #include "settings/SettingsConstants.hpp" #include "templates/Templates.hpp" #include "widgets/QuickRefactorDialog.hpp" +#include #include #include #include #include #include -#include using namespace Utils; using namespace Core; @@ -86,8 +88,12 @@ public: ~QodeAssistPlugin() final { delete m_qodeAssistClient; - delete m_chatOutputPane; - delete m_navigationPanel; + if (m_chatOutputPane) { + delete m_chatOutputPane; + } + if (m_navigationPanel) { + delete m_navigationPanel; + } } void loadTranslations() @@ -148,8 +154,10 @@ public: UpdateDialog::checkForUpdatesAndShow(Core::ICore::mainWindow()); }); - if (Settings::generalSettings().enableChat()) { + if (Settings::chatAssistantSettings().enableChatInBottomToolBar()) { m_chatOutputPane = new Chat::ChatOutputPane(this); + } + if (Settings::chatAssistantSettings().enableChatInNavigationPanel()) { m_navigationPanel = new Chat::NavigationPanel(); } @@ -186,6 +194,34 @@ public: } }); + ActionBuilder showChatViewAction(this, "QodeAssist.ShowChatView"); + const QKeySequence showChatViewShortcut = QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_W); + showChatViewAction.setDefaultKeySequence(showChatViewShortcut); + showChatViewAction.setToolTip(Tr::tr("Show QodeAssist Chat")); + showChatViewAction.setText(Tr::tr("Show QodeAssist Chat")); + showChatViewAction.setIcon(QCODEASSIST_ICON.icon()); + showChatViewAction.addOnTriggered(this, [this] { + if (!m_chatView->isVisible()) { + m_chatView->show(); + } + + m_chatView->raise(); + m_chatView->requestActivate(); + }); + m_statusWidget->setChatButtonAction(showChatViewAction.contextAction()); + + ActionBuilder closeChatViewAction(this, "QodeAssist.CloseChatView"); + const QKeySequence closeChatViewShortcut = QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_S); + closeChatViewAction.setDefaultKeySequence(closeChatViewShortcut); + closeChatViewAction.setToolTip(Tr::tr("Close QodeAssist Chat")); + closeChatViewAction.setText(Tr::tr("Close QodeAssist Chat")); + closeChatViewAction.setIcon(QCODEASSIST_ICON.icon()); + closeChatViewAction.addOnTriggered(this, [this] { + if (m_chatView->isVisible()) { + m_chatView->close(); + } + }); + Core::ActionContainer *editorContextMenu = Core::ActionManager::actionContainer( TextEditor::Constants::M_STANDARDCONTEXTMENU); if (editorContextMenu) { @@ -193,10 +229,14 @@ public: editorContextMenu ->addAction(quickRefactorAction.command(), Core::Constants::G_DEFAULT_THREE); editorContextMenu->addAction(requestAction.command(), Core::Constants::G_DEFAULT_THREE); + editorContextMenu->addAction(showChatViewAction.command(), + Core::Constants::G_DEFAULT_THREE); + editorContextMenu->addAction(closeChatViewAction.command(), + Core::Constants::G_DEFAULT_THREE); } } - void extensionsInitialized() final {} + void extensionsInitialized() final { m_chatView.reset(new Chat::ChatView()); } void restartClient() { @@ -256,6 +296,7 @@ private: QPointer m_updater; UpdateStatusWidget *m_statusWidget{nullptr}; QString m_lastRefactorInstructions; + QScopedPointer m_chatView; }; } // namespace QodeAssist::Internal diff --git a/settings/ChatAssistantSettings.cpp b/settings/ChatAssistantSettings.cpp index 0b893a3..c07ec75 100644 --- a/settings/ChatAssistantSettings.cpp +++ b/settings/ChatAssistantSettings.cpp @@ -64,6 +64,14 @@ ChatAssistantSettings::ChatAssistantSettings() autosave.setDefaultValue(true); autosave.setLabelText(Tr::tr("Enable autosave when message received")); + enableChatInBottomToolBar.setSettingsKey(Constants::CA_ENABLE_CHAT_IN_BOTTOM_TOOLBAR); + enableChatInBottomToolBar.setLabelText(Tr::tr("Enable chat in bottom toolbar")); + enableChatInBottomToolBar.setDefaultValue(false); + + enableChatInNavigationPanel.setSettingsKey(Constants::CA_ENABLE_CHAT_IN_NAVIGATION_PANEL); + enableChatInNavigationPanel.setLabelText(Tr::tr("Enable chat in navigation panel")); + enableChatInNavigationPanel.setDefaultValue(false); + // General Parameters Settings temperature.setSettingsKey(Constants::CA_TEMPERATURE); temperature.setLabelText(Tr::tr("Temperature:")); @@ -226,29 +234,32 @@ ChatAssistantSettings::ChatAssistantSettings() chatViewSettingsGrid.addRow({codeFontFamily, codeFontSize}); chatViewSettingsGrid.addRow({textFormat}); - return Column{ - Row{Stretch{1}, resetToDefaults}, - Space{8}, - Group{ - title(Tr::tr("Chat Settings")), - Column{Row{chatTokensThreshold, Stretch{1}}, linkOpenFiles, stream, autosave}}, - Space{8}, - Group{ - title(Tr::tr("General Parameters")), - Row{genGrid, Stretch{1}}, - }, - Space{8}, - Group{title(Tr::tr("Advanced Parameters")), Column{Row{advancedGrid, Stretch{1}}}}, - Space{8}, - Group{ - title(Tr::tr("Context Settings")), - Column{ - Row{useSystemPrompt, Stretch{1}}, - systemPrompt, - }}, - Group{title(Tr::tr("Ollama Settings")), Column{Row{ollamaGrid, Stretch{1}}}}, - Group{title(Tr::tr("Chat Settings")), Row{chatViewSettingsGrid, Stretch{1}}}, - Stretch{1}}; + return Column{Row{Stretch{1}, resetToDefaults}, + Space{8}, + Group{title(Tr::tr("Chat Settings")), + Column{Row{chatTokensThreshold, Stretch{1}}, + linkOpenFiles, + stream, + autosave, + enableChatInBottomToolBar, + enableChatInNavigationPanel}}, + Space{8}, + Group{ + title(Tr::tr("General Parameters")), + Row{genGrid, Stretch{1}}, + }, + Space{8}, + Group{title(Tr::tr("Advanced Parameters")), + Column{Row{advancedGrid, Stretch{1}}}}, + Space{8}, + Group{title(Tr::tr("Context Settings")), + Column{ + Row{useSystemPrompt, Stretch{1}}, + systemPrompt, + }}, + Group{title(Tr::tr("Ollama Settings")), Column{Row{ollamaGrid, Stretch{1}}}}, + Group{title(Tr::tr("Chat Settings")), Row{chatViewSettingsGrid, Stretch{1}}}, + Stretch{1}}; }); } diff --git a/settings/ChatAssistantSettings.hpp b/settings/ChatAssistantSettings.hpp index cfb9062..c34412b 100644 --- a/settings/ChatAssistantSettings.hpp +++ b/settings/ChatAssistantSettings.hpp @@ -37,6 +37,8 @@ public: Utils::BoolAspect linkOpenFiles{this}; Utils::BoolAspect stream{this}; Utils::BoolAspect autosave{this}; + Utils::BoolAspect enableChatInBottomToolBar{this}; + Utils::BoolAspect enableChatInNavigationPanel{this}; // General Parameters Settings Utils::DoubleAspect temperature{this}; diff --git a/settings/GeneralSettings.cpp b/settings/GeneralSettings.cpp index 44bd35a..f577203 100644 --- a/settings/GeneralSettings.cpp +++ b/settings/GeneralSettings.cpp @@ -79,10 +79,6 @@ GeneralSettings::GeneralSettings() enableCheckUpdate.setLabelText(TrConstants::ENABLE_CHECK_UPDATE_ON_START); enableCheckUpdate.setDefaultValue(true); - enableChat.setSettingsKey(Constants::ENABLE_CHAT); - enableChat.setLabelText(TrConstants::ENABLE_CHAT); - enableChat.setDefaultValue(true); - resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS; checkUpdate.m_buttonText = TrConstants::CHECK_UPDATE; @@ -258,7 +254,6 @@ GeneralSettings::GeneralSettings() Row{enableQodeAssist, Stretch{1}, Row{checkUpdate, resetToDefaults}}, Row{enableLogging, Stretch{1}}, Row{enableCheckUpdate, Stretch{1}}, - Row{enableChat, Stretch{1}}, Space{8}, ccGroup, Space{8}, diff --git a/settings/GeneralSettings.hpp b/settings/GeneralSettings.hpp index f1d80a9..ebf848b 100644 --- a/settings/GeneralSettings.hpp +++ b/settings/GeneralSettings.hpp @@ -36,7 +36,6 @@ public: Utils::BoolAspect enableQodeAssist{this}; Utils::BoolAspect enableLogging{this}; Utils::BoolAspect enableCheckUpdate{this}; - Utils::BoolAspect enableChat{this}; ButtonAspect checkUpdate{this}; ButtonAspect resetToDefaults{this}; diff --git a/settings/SettingsConstants.hpp b/settings/SettingsConstants.hpp index 19ecb3e..ae6b714 100644 --- a/settings/SettingsConstants.hpp +++ b/settings/SettingsConstants.hpp @@ -68,7 +68,6 @@ const char CC_SHOW_PROGRESS_WIDGET[] = "QodeAssist.ccShowProgressWidget"; const char CC_USE_OPEN_FILES_CONTEXT[] = "QodeAssist.ccUseOpenFilesContext"; const char ENABLE_LOGGING[] = "QodeAssist.enableLogging"; const char ENABLE_CHECK_UPDATE[] = "QodeAssist.enableCheckUpdate"; -const char ENABLE_CHAT[] = "QodeAssist.enableChat"; const char PROVIDER_PATHS[] = "QodeAssist.providerPaths"; const char СС_START_SUGGESTION_TIMER[] = "QodeAssist.startSuggestionTimer"; @@ -85,6 +84,9 @@ const char CA_STREAM[] = "QodeAssist.caStream"; const char CA_AUTOSAVE[] = "QodeAssist.caAutosave"; const char CC_CUSTOM_LANGUAGES[] = "QodeAssist.ccCustomLanguages"; +const char CA_ENABLE_CHAT_IN_BOTTOM_TOOLBAR[] = "QodeAssist.caEnableChatInBottomToolbar"; +const char CA_ENABLE_CHAT_IN_NAVIGATION_PANEL[] = "QodeAssist.caEnableChatInNavigationPanel"; + const char QODE_ASSIST_GENERAL_OPTIONS_ID[] = "QodeAssist.GeneralOptions"; const char QODE_ASSIST_GENERAL_SETTINGS_PAGE_ID[] = "QodeAssist.1GeneralSettingsPageId"; const char QODE_ASSIST_CODE_COMPLETION_SETTINGS_PAGE_ID[]