diff --git a/CMakeLists.txt b/CMakeLists.txt index cef074d..54337e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) find_package(QtCreator REQUIRED COMPONENTS Core) find_package(Qt6 COMPONENTS Core Gui Widgets Network REQUIRED) +add_subdirectory(chatview) + add_qtc_plugin(QodeAssist PLUGIN_DEPENDS QtCreator::Core @@ -62,4 +64,7 @@ add_qtc_plugin(QodeAssist chat/ChatWidget.h chat/ChatWidget.cpp chat/ChatOutputPane.h chat/ChatOutputPane.cpp chat/ChatClientInterface.hpp chat/ChatClientInterface.cpp + chat/NavigationPanel.hpp chat/NavigationPanel.cpp ) + +target_link_libraries(QodeAssist PUBLIC QodeAssistChatViewplugin) diff --git a/QodeAssist.json.in b/QodeAssist.json.in index 4389e57..14543c1 100644 --- a/QodeAssist.json.in +++ b/QodeAssist.json.in @@ -1,6 +1,6 @@ { "Name" : "QodeAssist", - "Version" : "0.2.3", + "Version" : "0.2.4", "CompatVersion" : "${IDE_VERSION_COMPAT}", "Vendor" : "Petr Mironychev", "Copyright" : "(C) ${IDE_COPYRIGHT_YEAR} Petr Mironychev, (C) ${IDE_COPYRIGHT_YEAR} The Qt Company Ltd", diff --git a/chat/NavigationPanel.cpp b/chat/NavigationPanel.cpp new file mode 100644 index 0000000..19b9211 --- /dev/null +++ b/chat/NavigationPanel.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 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 "NavigationPanel.hpp" + +#include "chatview/BaseChatWidget.hpp" + +namespace QodeAssist::Chat { + +NavigationPanel::NavigationPanel() { + setDisplayName(tr("QodeAssist Chat")); + setPriority(500); + setId("QodeAssistChat"); + setActivationSequence(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_C)); +} + +NavigationPanel::~NavigationPanel() +{ +} + +Core::NavigationView NavigationPanel::createWidget() +{ + Core::NavigationView view; + view.widget = new BaseChatWidget; + + return view; +} + +} diff --git a/chat/NavigationPanel.hpp b/chat/NavigationPanel.hpp new file mode 100644 index 0000000..e7eff5a --- /dev/null +++ b/chat/NavigationPanel.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 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 NavigationPanel : public Core::INavigationWidgetFactory +{ + Q_OBJECT +public: + explicit NavigationPanel(); + ~NavigationPanel(); + + Core::NavigationView createWidget() override; +}; + +} diff --git a/chatview/BaseChatWidget.cpp b/chatview/BaseChatWidget.cpp new file mode 100644 index 0000000..bb16c20 --- /dev/null +++ b/chatview/BaseChatWidget.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 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 "BaseChatWidget.hpp" + +#include +#include + +namespace QodeAssist::Chat { + +BaseChatWidget::BaseChatWidget(QWidget *parent) : QQuickWidget(parent) +{ + setSource(QUrl("qrc:/ChatView/qml/RootItem.qml")); + setResizeMode(QQuickWidget::SizeRootObjectToView); + + engine()->rootContext()->setContextObject(this); +} + +} diff --git a/chatview/BaseChatWidget.hpp b/chatview/BaseChatWidget.hpp new file mode 100644 index 0000000..e255672 --- /dev/null +++ b/chatview/BaseChatWidget.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 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 + +namespace QodeAssist::Chat { + +class BaseChatWidget : public QQuickWidget +{ + Q_OBJECT + +public: + explicit BaseChatWidget(QWidget *parent = nullptr); + ~BaseChatWidget() = default; +}; + +} diff --git a/chatview/CMakeLists.txt b/chatview/CMakeLists.txt new file mode 100644 index 0000000..cdba3b7 --- /dev/null +++ b/chatview/CMakeLists.txt @@ -0,0 +1,26 @@ +qt_add_library(QodeAssistChatView STATIC) + +find_package(Qt6 COMPONENTS Core Widgets Quick QuickWidgets Network REQUIRED) + +qt_add_qml_module(QodeAssistChatView + URI ChatView + VERSION 1.0 + QML_FILES + qml/RootItem.qml + SOURCES + BaseChatWidget.hpp BaseChatWidget.cpp + ChatModel.hpp ChatModel.cpp + ChatRootView.hpp ChatRootView.cpp +) + +target_link_libraries(QodeAssistChatView + PRIVATE + Qt::Widgets + Qt::Quick + Qt::QuickWidgets + Qt::Network +) + +target_include_directories(QodeAssistChatView + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/chatview/ChatModel.cpp b/chatview/ChatModel.cpp new file mode 100644 index 0000000..67eda66 --- /dev/null +++ b/chatview/ChatModel.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 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 "ChatModel.hpp" + +namespace QodeAssist::Chat { + +ChatModel::ChatModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int ChatModel::rowCount(const QModelIndex &parent) const +{ + return m_messages.size(); +} + +QVariant ChatModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= m_messages.size()) + return QVariant(); + + const Message &message = m_messages[index.row()]; + switch (static_cast(role)) { + case Roles::RoleType: + return QVariant::fromValue(message.role); + case Roles::Content: + return message.content; + default: + return QVariant(); + } +} + +QHash ChatModel::roleNames() const +{ + QHash roles; + roles[Roles::RoleType] = "roleType"; + roles[Roles::Content] = "content"; + return roles; +} + +void ChatModel::addMessage(const QString &content, ChatRole role) +{ + beginInsertRows(QModelIndex(), m_messages.size(), m_messages.size()); + m_messages.append({role, content}); + endInsertRows(); +} + +void ChatModel::clear() +{ + beginResetModel(); + m_messages.clear(); + endResetModel(); +} + +} // namespace QodeAssist::Chat diff --git a/chatview/ChatModel.hpp b/chatview/ChatModel.hpp new file mode 100644 index 0000000..2058d34 --- /dev/null +++ b/chatview/ChatModel.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 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 + +namespace QodeAssist::Chat { + +enum class ChatRole { System, User, Assistant }; + +struct Message +{ + ChatRole role; + QString content; +}; + +class ChatModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { RoleType = Qt::UserRole, Content }; + + explicit ChatModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + + Q_INVOKABLE void addMessage(const QString &content, ChatRole role); + Q_INVOKABLE void clear(); + +private: + QVector m_messages; +}; + +} // namespace QodeAssist::Chat + +Q_DECLARE_METATYPE(QodeAssist::Chat::ChatRole) diff --git a/chatview/ChatRootView.cpp b/chatview/ChatRootView.cpp new file mode 100644 index 0000000..c98f1f4 --- /dev/null +++ b/chatview/ChatRootView.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 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 "ChatRootView.hpp" + +namespace QodeAssist::Chat { + +ChatRootView::ChatRootView(QQuickItem *parent) + : QQuickItem(parent) + , m_chatModel(new ChatModel(this)) +{} + +ChatModel *ChatRootView::chatModel() const +{ + return m_chatModel; +} + +} // namespace QodeAssist::Chat diff --git a/chatview/ChatRootView.hpp b/chatview/ChatRootView.hpp new file mode 100644 index 0000000..9f83ed7 --- /dev/null +++ b/chatview/ChatRootView.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 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 "ChatModel.hpp" + +namespace QodeAssist::Chat { + +class ChatRootView : public QQuickItem +{ + Q_OBJECT + QML_ELEMENT + + Q_PROPERTY(ChatModel *chatModel READ chatModel NOTIFY chatModelChanged FINAL) +public: + ChatRootView(QQuickItem *parent = nullptr); + + ChatModel *chatModel() const; + +signals: + void chatModelChanged(); + +private: + ChatModel *m_chatModel = nullptr; +}; + +} // namespace QodeAssist::Chat diff --git a/chatview/qml/RootItem.qml b/chatview/qml/RootItem.qml new file mode 100644 index 0000000..f166a45 --- /dev/null +++ b/chatview/qml/RootItem.qml @@ -0,0 +1,13 @@ +import QtQuick +import ChatView + +ChatRootView { + id: root + + Rectangle { + id: bg + + anchors.fill: parent + color: "gray" + } +} diff --git a/qodeassist.cpp b/qodeassist.cpp index 9dc8128..87ea06d 100644 --- a/qodeassist.cpp +++ b/qodeassist.cpp @@ -124,9 +124,9 @@ public: void restartClient() { - LanguageClient::LanguageClientManager::shutdownClient(m_qodeAssistClient); + LanguageClient::LanguageClientManager::shutdownClient(m_qodeAssistClient.get()); - m_qodeAssistClient = new QodeAssistClient(); + m_qodeAssistClient.reset(new QodeAssistClient()); } bool delayedInitialize() final @@ -140,7 +140,7 @@ public: { if (!m_qodeAssistClient) return SynchronousShutdown; - connect(m_qodeAssistClient, + connect(m_qodeAssistClient.get(), &QObject::destroyed, this, &IPlugin::asynchronousShutdownFinished); @@ -148,7 +148,7 @@ public: } private: - QPointer m_qodeAssistClient; + QScopedPointer m_qodeAssistClient; QPointer m_chatOutputPane; };