mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2025-05-28 03:10:28 -04:00
feat: Add check plugin update and dialog for update
This commit is contained in:
parent
70481b3116
commit
9db61119aa
@ -68,4 +68,5 @@ add_qtc_plugin(QodeAssist
|
||||
chat/NavigationPanel.hpp chat/NavigationPanel.cpp
|
||||
ConfigurationManager.hpp ConfigurationManager.cpp
|
||||
CodeHandler.hpp CodeHandler.cpp
|
||||
UpdateStatusWidget.hpp UpdateStatusWidget.cpp
|
||||
)
|
||||
|
72
UpdateStatusWidget.cpp
Normal file
72
UpdateStatusWidget.cpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "UpdateStatusWidget.hpp"
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
UpdateStatusWidget::UpdateStatusWidget(QWidget *parent)
|
||||
: QFrame(parent)
|
||||
{
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
|
||||
auto layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(4, 0, 4, 0);
|
||||
layout->setSpacing(4);
|
||||
|
||||
m_actionButton = new QToolButton(this);
|
||||
m_actionButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||
|
||||
m_versionLabel = new QLabel(this);
|
||||
m_versionLabel->setVisible(false);
|
||||
|
||||
m_updateButton = new QPushButton(tr("Update"), this);
|
||||
m_updateButton->setVisible(false);
|
||||
m_updateButton->setStyleSheet("QPushButton { padding: 2px 8px; }");
|
||||
|
||||
layout->addWidget(m_actionButton);
|
||||
layout->addWidget(m_versionLabel);
|
||||
layout->addWidget(m_updateButton);
|
||||
}
|
||||
|
||||
void UpdateStatusWidget::setDefaultAction(QAction *action)
|
||||
{
|
||||
m_actionButton->setDefaultAction(action);
|
||||
}
|
||||
|
||||
void UpdateStatusWidget::showUpdateAvailable(const QString &version)
|
||||
{
|
||||
m_versionLabel->setText(tr("new version: v%1").arg(version));
|
||||
m_versionLabel->setVisible(true);
|
||||
m_updateButton->setVisible(true);
|
||||
m_updateButton->setToolTip(tr("Update QodeAssist to version %1").arg(version));
|
||||
}
|
||||
|
||||
void UpdateStatusWidget::hideUpdateInfo()
|
||||
{
|
||||
m_versionLabel->setVisible(false);
|
||||
m_updateButton->setVisible(false);
|
||||
}
|
||||
|
||||
QPushButton *UpdateStatusWidget::updateButton() const
|
||||
{
|
||||
return m_updateButton;
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
47
UpdateStatusWidget.hpp
Normal file
47
UpdateStatusWidget.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class UpdateStatusWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UpdateStatusWidget(QWidget *parent = nullptr);
|
||||
|
||||
void setDefaultAction(QAction *action);
|
||||
void showUpdateAvailable(const QString &version);
|
||||
void hideUpdateInfo();
|
||||
|
||||
QPushButton *updateButton() const;
|
||||
|
||||
private:
|
||||
QToolButton *m_actionButton;
|
||||
QLabel *m_versionLabel;
|
||||
QPushButton *m_updateButton;
|
||||
};
|
||||
} // namespace QodeAssist
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "QodeAssistConstants.hpp"
|
||||
#include "QodeAssisttr.h"
|
||||
#include "settings/PluginUpdater.hpp"
|
||||
#include "settings/UpdateDialog.hpp"
|
||||
|
||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||
#include <coreplugin/actionmanager/actionmanager.h>
|
||||
@ -32,19 +34,21 @@
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <languageclient/languageclientmanager.h>
|
||||
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <utils/icon.h>
|
||||
#include <QAction>
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <utils/icon.h>
|
||||
|
||||
#include "ConfigurationManager.hpp"
|
||||
#include "QodeAssistClient.hpp"
|
||||
#include "chat/ChatOutputPane.h"
|
||||
#include "chat/NavigationPanel.hpp"
|
||||
#include "settings/GeneralSettings.hpp"
|
||||
#include "settings/ProjectSettingsPanel.hpp"
|
||||
|
||||
#include "UpdateStatusWidget.hpp"
|
||||
#include "providers/Providers.hpp"
|
||||
#include "templates/Templates.hpp"
|
||||
|
||||
@ -61,8 +65,8 @@ class QodeAssistPlugin final : public ExtensionSystem::IPlugin
|
||||
|
||||
public:
|
||||
QodeAssistPlugin()
|
||||
{
|
||||
}
|
||||
: m_updater(new PluginUpdater(this))
|
||||
{}
|
||||
|
||||
~QodeAssistPlugin() final
|
||||
{
|
||||
@ -96,33 +100,36 @@ public:
|
||||
}
|
||||
});
|
||||
|
||||
auto toggleButton = new QToolButton;
|
||||
toggleButton->setDefaultAction(requestAction.contextAction());
|
||||
StatusBarManager::addStatusBarWidget(toggleButton, StatusBarManager::RightCorner);
|
||||
m_statusWidget = new UpdateStatusWidget;
|
||||
m_statusWidget->setDefaultAction(requestAction.contextAction());
|
||||
StatusBarManager::addStatusBarWidget(m_statusWidget, StatusBarManager::RightCorner);
|
||||
|
||||
connect(m_statusWidget->updateButton(), &QPushButton::clicked, this, [this]() {
|
||||
UpdateDialog::checkForUpdatesAndShow(Core::ICore::mainWindow());
|
||||
});
|
||||
|
||||
m_chatOutputPane = new Chat::ChatOutputPane(this);
|
||||
m_navigationPanel = new Chat::NavigationPanel();
|
||||
|
||||
Settings::setupProjectPanel();
|
||||
|
||||
ConfigurationManager::instance().init();
|
||||
|
||||
if (Settings::generalSettings().enableCheckUpdate()) {
|
||||
QTimer::singleShot(3000, this, &QodeAssistPlugin::checkForUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
void extensionsInitialized() final
|
||||
{
|
||||
}
|
||||
void extensionsInitialized() final {}
|
||||
|
||||
void restartClient()
|
||||
{
|
||||
LanguageClient::LanguageClientManager::shutdownClient(m_qodeAssistClient);
|
||||
|
||||
m_qodeAssistClient = new QodeAssistClient();
|
||||
}
|
||||
|
||||
bool delayedInitialize() final
|
||||
{
|
||||
restartClient();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -130,17 +137,36 @@ public:
|
||||
{
|
||||
if (!m_qodeAssistClient)
|
||||
return SynchronousShutdown;
|
||||
connect(m_qodeAssistClient,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
&IPlugin::asynchronousShutdownFinished);
|
||||
connect(m_qodeAssistClient, &QObject::destroyed, this, &IPlugin::asynchronousShutdownFinished);
|
||||
return AsynchronousShutdown;
|
||||
}
|
||||
|
||||
private:
|
||||
void checkForUpdates()
|
||||
{
|
||||
connect(
|
||||
m_updater,
|
||||
&PluginUpdater::updateCheckFinished,
|
||||
this,
|
||||
&QodeAssistPlugin::handleUpdateCheckResult,
|
||||
Qt::UniqueConnection);
|
||||
m_updater->checkForUpdates();
|
||||
}
|
||||
|
||||
void handleUpdateCheckResult(const PluginUpdater::UpdateInfo &info)
|
||||
{
|
||||
if (!info.isUpdateAvailable)
|
||||
return;
|
||||
|
||||
if (m_statusWidget)
|
||||
m_statusWidget->showUpdateAvailable(info.version);
|
||||
}
|
||||
|
||||
QPointer<QodeAssistClient> m_qodeAssistClient;
|
||||
QPointer<Chat::ChatOutputPane> m_chatOutputPane;
|
||||
QPointer<Chat::NavigationPanel> m_navigationPanel;
|
||||
QPointer<PluginUpdater> m_updater;
|
||||
UpdateStatusWidget *m_statusWidget{nullptr};
|
||||
};
|
||||
|
||||
} // namespace QodeAssist::Internal
|
||||
|
@ -11,6 +11,8 @@ add_library(QodeAssistSettings STATIC
|
||||
ProjectSettings.hpp ProjectSettings.cpp
|
||||
ProjectSettingsPanel.hpp ProjectSettingsPanel.cpp
|
||||
ProviderSettings.hpp ProviderSettings.cpp
|
||||
PluginUpdater.hpp PluginUpdater.cpp
|
||||
UpdateDialog.hpp UpdateDialog.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(QodeAssistSettings
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "SettingsDialog.hpp"
|
||||
#include "SettingsTr.hpp"
|
||||
#include "SettingsUtils.hpp"
|
||||
#include "UpdateDialog.hpp"
|
||||
|
||||
namespace QodeAssist::Settings {
|
||||
|
||||
@ -60,7 +61,12 @@ GeneralSettings::GeneralSettings()
|
||||
enableLogging.setLabelText(TrConstants::ENABLE_LOG);
|
||||
enableLogging.setDefaultValue(false);
|
||||
|
||||
enableCheckUpdate.setSettingsKey(Constants::ENABLE_CHECK_UPDATE);
|
||||
enableCheckUpdate.setLabelText(TrConstants::ENABLE_CHECK_UPDATE_ON_START);
|
||||
enableCheckUpdate.setDefaultValue(true);
|
||||
|
||||
resetToDefaults.m_buttonText = TrConstants::RESET_TO_DEFAULTS;
|
||||
checkUpdate.m_buttonText = TrConstants::CHECK_UPDATE;
|
||||
|
||||
initStringAspect(ccProvider, Constants::CC_PROVIDER, TrConstants::PROVIDER, "Ollama");
|
||||
ccProvider.setReadOnly(true);
|
||||
@ -129,13 +135,15 @@ GeneralSettings::GeneralSettings()
|
||||
auto ccGroup = Group{title(TrConstants::CODE_COMPLETION), ccGrid};
|
||||
auto caGroup = Group{title(TrConstants::CHAT_ASSISTANT), caGrid};
|
||||
|
||||
auto rootLayout = Column{Row{enableQodeAssist, Stretch{1}, resetToDefaults},
|
||||
Row{enableLogging, Stretch{1}},
|
||||
Space{8},
|
||||
ccGroup,
|
||||
Space{8},
|
||||
caGroup,
|
||||
Stretch{1}};
|
||||
auto rootLayout = Column{
|
||||
Row{enableQodeAssist, Stretch{1}, Row{checkUpdate, resetToDefaults}},
|
||||
Row{enableLogging, Stretch{1}},
|
||||
Row{enableCheckUpdate, Stretch{1}},
|
||||
Space{8},
|
||||
ccGroup,
|
||||
Space{8},
|
||||
caGroup,
|
||||
Stretch{1}};
|
||||
|
||||
return rootLayout;
|
||||
});
|
||||
@ -295,6 +303,9 @@ void GeneralSettings::setupConnections()
|
||||
Logger::instance().setLoggingEnabled(enableLogging.volatileValue());
|
||||
});
|
||||
connect(&resetToDefaults, &ButtonAspect::clicked, this, &GeneralSettings::resetPageToDefaults);
|
||||
connect(&checkUpdate, &ButtonAspect::clicked, this, [this]() {
|
||||
QodeAssist::UpdateDialog::checkForUpdatesAndShow(Core::ICore::dialogParent());
|
||||
});
|
||||
}
|
||||
|
||||
void GeneralSettings::resetPageToDefaults()
|
||||
@ -316,6 +327,7 @@ void GeneralSettings::resetPageToDefaults()
|
||||
resetAspect(caModel);
|
||||
resetAspect(caTemplate);
|
||||
resetAspect(caUrl);
|
||||
resetAspect(enableCheckUpdate);
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ public:
|
||||
|
||||
Utils::BoolAspect enableQodeAssist{this};
|
||||
Utils::BoolAspect enableLogging{this};
|
||||
Utils::BoolAspect enableCheckUpdate{this};
|
||||
ButtonAspect checkUpdate{this};
|
||||
ButtonAspect resetToDefaults{this};
|
||||
|
||||
// code completion setttings
|
||||
|
192
settings/PluginUpdater.cpp
Normal file
192
settings/PluginUpdater.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PluginUpdater.hpp"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/coreplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <extensionsystem/pluginspec.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
PluginUpdater::PluginUpdater(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_networkManager(new QNetworkAccessManager(this))
|
||||
{}
|
||||
|
||||
void PluginUpdater::checkForUpdates()
|
||||
{
|
||||
if (m_isCheckingUpdate)
|
||||
return;
|
||||
|
||||
m_isCheckingUpdate = true;
|
||||
QNetworkRequest request((QUrl(getUpdateUrl())));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QNetworkReply *reply = m_networkManager->get(request);
|
||||
|
||||
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
|
||||
handleUpdateResponse(reply);
|
||||
m_isCheckingUpdate = false;
|
||||
reply->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void PluginUpdater::handleUpdateResponse(QNetworkReply *reply)
|
||||
{
|
||||
UpdateInfo info;
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
emit downloadError(reply->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
||||
QJsonObject obj = doc.object();
|
||||
|
||||
info.version = obj["tag_name"].toString();
|
||||
if (info.version.startsWith('v'))
|
||||
info.version.remove(0, 1);
|
||||
|
||||
QString qtcVersionStr = Core::ICore::versionString().split(' ').last();
|
||||
QVersionNumber qtcVersion = QVersionNumber::fromString(qtcVersionStr);
|
||||
info.currentIdeVersion = qtcVersionStr;
|
||||
|
||||
auto assets = obj["assets"].toArray();
|
||||
for (const auto &asset : assets) {
|
||||
QString name = asset.toObject()["name"].toString();
|
||||
|
||||
if (name.startsWith("QodeAssist-")) {
|
||||
QString assetVersionStr = name.section('-', 1, 1);
|
||||
QVersionNumber assetVersion = QVersionNumber::fromString(assetVersionStr);
|
||||
info.targetIdeVersion = assetVersionStr;
|
||||
|
||||
if (assetVersion != qtcVersion) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
if (name.contains("Windows"))
|
||||
#elif defined(Q_OS_MACOS)
|
||||
if (name.contains("macOS"))
|
||||
#else
|
||||
if (name.contains("Linux"))
|
||||
#endif
|
||||
{
|
||||
info.downloadUrl = asset.toObject()["browser_download_url"].toString();
|
||||
info.fileName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.downloadUrl.isEmpty()) {
|
||||
info.incompatibleIdeVersion = true;
|
||||
emit updateCheckFinished(info);
|
||||
return;
|
||||
}
|
||||
|
||||
info.changeLog = obj["body"].toString();
|
||||
info.isUpdateAvailable = QVersionNumber::fromString(info.version)
|
||||
> QVersionNumber::fromString(currentVersion());
|
||||
|
||||
m_lastUpdateInfo = info;
|
||||
emit updateCheckFinished(info);
|
||||
}
|
||||
|
||||
void PluginUpdater::downloadUpdate(const QString &url)
|
||||
{
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply *reply = m_networkManager->get(request);
|
||||
|
||||
connect(reply, &QNetworkReply::downloadProgress, this, &PluginUpdater::handleDownloadProgress);
|
||||
connect(reply, &QNetworkReply::finished, this, &PluginUpdater::handleDownloadFinished);
|
||||
}
|
||||
|
||||
QString PluginUpdater::currentVersion() const
|
||||
{
|
||||
const auto pluginSpecs = ExtensionSystem::PluginManager::plugins();
|
||||
for (const ExtensionSystem::PluginSpec *spec : pluginSpecs) {
|
||||
if (spec->name() == QLatin1String("QodeAssist"))
|
||||
return spec->version();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool PluginUpdater::isUpdateAvailable() const
|
||||
{
|
||||
return m_lastUpdateInfo.isUpdateAvailable;
|
||||
}
|
||||
|
||||
QString PluginUpdater::getUpdateUrl() const
|
||||
{
|
||||
return "https://api.github.com/repos/Palm1r/qodeassist/releases/latest";
|
||||
}
|
||||
|
||||
void PluginUpdater::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
emit downloadProgress(bytesReceived, bytesTotal);
|
||||
}
|
||||
|
||||
void PluginUpdater::handleDownloadFinished()
|
||||
{
|
||||
auto reply = qobject_cast<QNetworkReply *>(sender());
|
||||
QTC_ASSERT(reply, return);
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
emit downloadError(reply->errorString());
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
QString downloadPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)
|
||||
+ QDir::separator() + "qodeassisttemp";
|
||||
QDir().mkpath(downloadPath);
|
||||
|
||||
QString filePath = downloadPath + "/" + m_lastUpdateInfo.fileName;
|
||||
QFile file(filePath);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
emit downloadError(tr("Could not save the update file"));
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
file.write(reply->readAll());
|
||||
file.close();
|
||||
|
||||
if (!Core::executePluginInstallWizard(Utils::FilePath::fromString(filePath))) {
|
||||
emit downloadError(tr("Failed to install the update"));
|
||||
} else {
|
||||
emit downloadFinished(filePath);
|
||||
}
|
||||
|
||||
auto tempDir = QDir(downloadPath);
|
||||
if (tempDir.exists()) {
|
||||
tempDir.removeRecursively();
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
72
settings/PluginUpdater.hpp
Normal file
72
settings/PluginUpdater.hpp
Normal file
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/plugininstallwizard.h>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QObject>
|
||||
#include <QVersionNumber>
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class PluginUpdater : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct UpdateInfo
|
||||
{
|
||||
QString version;
|
||||
QString downloadUrl;
|
||||
QString changeLog;
|
||||
QString fileName;
|
||||
bool isUpdateAvailable;
|
||||
bool incompatibleIdeVersion{false};
|
||||
QString targetIdeVersion;
|
||||
QString currentIdeVersion;
|
||||
};
|
||||
|
||||
explicit PluginUpdater(QObject *parent = nullptr);
|
||||
~PluginUpdater() = default;
|
||||
|
||||
void checkForUpdates();
|
||||
void downloadUpdate(const QString &url);
|
||||
QString currentVersion() const;
|
||||
bool isUpdateAvailable() const;
|
||||
|
||||
signals:
|
||||
void updateCheckFinished(const UpdateInfo &info);
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void downloadFinished(const QString &filePath);
|
||||
void downloadError(const QString &error);
|
||||
|
||||
private:
|
||||
void handleUpdateResponse(QNetworkReply *reply);
|
||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleDownloadFinished();
|
||||
QString getUpdateUrl() const;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
UpdateInfo m_lastUpdateInfo;
|
||||
bool m_isCheckingUpdate{false};
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
@ -50,6 +50,8 @@ const char CA_URL_HISTORY[] = "QodeAssist.caUrlHistory";
|
||||
const char ENABLE_QODE_ASSIST[] = "QodeAssist.enableQodeAssist";
|
||||
const char CC_AUTO_COMPLETION[] = "QodeAssist.ccAutoCompletion";
|
||||
const char ENABLE_LOGGING[] = "QodeAssist.enableLogging";
|
||||
const char ENABLE_CHECK_UPDATE[] = "QodeAssist.enableCheckUpdate";
|
||||
|
||||
const char PROVIDER_PATHS[] = "QodeAssist.providerPaths";
|
||||
const char СС_START_SUGGESTION_TIMER[] = "QodeAssist.startSuggestionTimer";
|
||||
const char СС_AUTO_COMPLETION_CHAR_THRESHOLD[] = "QodeAssist.autoCompletionCharThreshold";
|
||||
|
@ -28,6 +28,7 @@ inline const char *ENABLE_QODE_ASSIST = QT_TRANSLATE_NOOP("QtC::QodeAssist", "En
|
||||
inline const char *GENERAL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "General");
|
||||
inline const char *RESET_TO_DEFAULTS = QT_TRANSLATE_NOOP("QtC::QodeAssist",
|
||||
"Reset Page to Defaults");
|
||||
inline const char *CHECK_UPDATE = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Check Update");
|
||||
inline const char *SELECT = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Select...");
|
||||
inline const char *PROVIDER = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Provider:");
|
||||
inline const char *MODEL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Model:");
|
||||
@ -36,6 +37,9 @@ inline const char *URL = QT_TRANSLATE_NOOP("QtC::QodeAssist", "URL:");
|
||||
inline const char *STATUS = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Status:");
|
||||
inline const char *TEST = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Test");
|
||||
inline const char *ENABLE_LOG = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Enable Logging");
|
||||
inline const char *ENABLE_CHECK_UPDATE_ON_START
|
||||
= QT_TRANSLATE_NOOP("QtC::QodeAssist", "Check for updates when Qt Creator starts");
|
||||
|
||||
inline const char *CODE_COMPLETION = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Code Completion");
|
||||
inline const char *CHAT_ASSISTANT = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Chat Assistant");
|
||||
inline const char *RESET_SETTINGS = QT_TRANSLATE_NOOP("QtC::QodeAssist", "Reset Settings");
|
||||
|
174
settings/UpdateDialog.cpp
Normal file
174
settings/UpdateDialog.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "UpdateDialog.hpp"
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
UpdateDialog::UpdateDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, m_updater(new PluginUpdater(this))
|
||||
{
|
||||
setWindowTitle(tr("QodeAssist Update"));
|
||||
setMinimumWidth(400);
|
||||
setMinimumHeight(500);
|
||||
|
||||
m_layout = new QVBoxLayout(this);
|
||||
m_layout->setSpacing(12);
|
||||
|
||||
auto *supportLabel = new QLabel(
|
||||
tr("QodeAssist is an open-source project that helps\n"
|
||||
"developers write better code. If you find it useful, please"),
|
||||
this);
|
||||
supportLabel->setAlignment(Qt::AlignCenter);
|
||||
m_layout->addWidget(supportLabel);
|
||||
|
||||
auto *supportLink = new QLabel(
|
||||
tr("<a href='https://ko-fi.com/qodeassist' style='color: #0066cc;'>Support on Ko-fi "
|
||||
"☕</a>"),
|
||||
this);
|
||||
supportLink->setOpenExternalLinks(true);
|
||||
supportLink->setTextFormat(Qt::RichText);
|
||||
supportLink->setAlignment(Qt::AlignCenter);
|
||||
m_layout->addWidget(supportLink);
|
||||
|
||||
m_layout->addSpacing(20);
|
||||
|
||||
m_titleLabel = new QLabel(tr("A new version of QodeAssist is available!"), this);
|
||||
m_titleLabel->setStyleSheet("font-weight: bold; font-size: 14px;");
|
||||
m_titleLabel->setAlignment(Qt::AlignCenter);
|
||||
m_layout->addWidget(m_titleLabel);
|
||||
|
||||
m_versionLabel = new QLabel(
|
||||
tr("Version %1 is now available - you have %2").arg(m_updater->currentVersion()), this);
|
||||
m_versionLabel->setAlignment(Qt::AlignCenter);
|
||||
m_layout->addWidget(m_versionLabel);
|
||||
|
||||
if (!m_changelogLabel) {
|
||||
m_changelogLabel = new QLabel(tr("Release Notes:"), this);
|
||||
m_layout->addWidget(m_changelogLabel);
|
||||
|
||||
m_changelogText = new QTextEdit(this);
|
||||
m_changelogText->setReadOnly(true);
|
||||
m_changelogText->setMinimumHeight(100);
|
||||
m_layout->addWidget(m_changelogText);
|
||||
}
|
||||
|
||||
m_progress = new QProgressBar(this);
|
||||
m_progress->setVisible(false);
|
||||
m_layout->addWidget(m_progress);
|
||||
|
||||
auto *buttonLayout = new QHBoxLayout;
|
||||
m_downloadButton = new QPushButton(tr("Download and Install"), this);
|
||||
m_downloadButton->setEnabled(false);
|
||||
buttonLayout->addWidget(m_downloadButton);
|
||||
|
||||
m_closeButton = new QPushButton(tr("Close"), this);
|
||||
buttonLayout->addWidget(m_closeButton);
|
||||
|
||||
m_layout->addLayout(buttonLayout);
|
||||
|
||||
connect(m_updater, &PluginUpdater::updateCheckFinished, this, &UpdateDialog::handleUpdateInfo);
|
||||
connect(m_updater, &PluginUpdater::downloadProgress, this, &UpdateDialog::updateProgress);
|
||||
connect(m_updater, &PluginUpdater::downloadFinished, this, &UpdateDialog::handleDownloadFinished);
|
||||
connect(m_updater, &PluginUpdater::downloadError, this, &UpdateDialog::handleDownloadError);
|
||||
|
||||
connect(m_downloadButton, &QPushButton::clicked, this, &UpdateDialog::startDownload);
|
||||
connect(m_closeButton, &QPushButton::clicked, this, &QDialog::reject);
|
||||
|
||||
m_updater->checkForUpdates();
|
||||
}
|
||||
|
||||
void UpdateDialog::checkForUpdatesAndShow(QWidget *parent)
|
||||
{
|
||||
auto *dialog = new UpdateDialog(parent);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void UpdateDialog::handleUpdateInfo(const PluginUpdater::UpdateInfo &info)
|
||||
{
|
||||
if (info.incompatibleIdeVersion) {
|
||||
m_titleLabel->setText(tr("Incompatible Qt Creator Version"));
|
||||
m_versionLabel->setText(tr("This update requires Qt Creator %1, current is %2.\n"
|
||||
"Please upgrade Qt Creator to use this version of QodeAssist.")
|
||||
.arg(info.targetIdeVersion, info.currentIdeVersion));
|
||||
m_downloadButton->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info.isUpdateAvailable) {
|
||||
m_titleLabel->setText(tr("QodeAssist is up to date"));
|
||||
m_downloadButton->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
m_titleLabel->setText(tr("A new version of QodeAssist is available!"));
|
||||
m_versionLabel->setText(tr("Version %1 is now available - you have %2")
|
||||
.arg(info.version, m_updater->currentVersion()));
|
||||
|
||||
if (!info.changeLog.isEmpty()) {
|
||||
if (!m_changelogLabel) {
|
||||
m_changelogLabel = new QLabel(tr("Release Notes:"), this);
|
||||
m_layout->insertWidget(2, m_changelogLabel);
|
||||
|
||||
m_changelogText = new QTextEdit(this);
|
||||
m_changelogText->setReadOnly(true);
|
||||
m_changelogText->setMaximumHeight(200);
|
||||
m_layout->insertWidget(3, m_changelogText);
|
||||
}
|
||||
m_changelogText->setText(info.changeLog);
|
||||
}
|
||||
|
||||
m_downloadButton->setEnabled(true);
|
||||
m_updateInfo = info;
|
||||
}
|
||||
|
||||
void UpdateDialog::startDownload()
|
||||
{
|
||||
m_downloadButton->setEnabled(false);
|
||||
m_progress->setVisible(true);
|
||||
m_updater->downloadUpdate(m_updateInfo.downloadUrl);
|
||||
}
|
||||
|
||||
void UpdateDialog::updateProgress(qint64 received, qint64 total)
|
||||
{
|
||||
m_progress->setMaximum(total);
|
||||
m_progress->setValue(received);
|
||||
}
|
||||
|
||||
void UpdateDialog::handleDownloadFinished(const QString &path)
|
||||
{
|
||||
m_progress->setVisible(false);
|
||||
QMessageBox::information(
|
||||
this,
|
||||
tr("Update Successful"),
|
||||
tr("Update has been downloaded and installed. "
|
||||
"Please restart Qt Creator to apply changes."));
|
||||
accept();
|
||||
}
|
||||
|
||||
void UpdateDialog::handleDownloadError(const QString &error)
|
||||
{
|
||||
m_progress->setVisible(false);
|
||||
m_downloadButton->setEnabled(true);
|
||||
QMessageBox::critical(this, tr("Update Error"), tr("Failed to update: %1").arg(error));
|
||||
}
|
||||
|
||||
} // namespace QodeAssist
|
63
settings/UpdateDialog.hpp
Normal file
63
settings/UpdateDialog.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressBar>
|
||||
#include <QPushButton>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "PluginUpdater.hpp"
|
||||
|
||||
namespace QodeAssist {
|
||||
|
||||
class UpdateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UpdateDialog(QWidget *parent = nullptr);
|
||||
|
||||
static void checkForUpdatesAndShow(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void handleUpdateInfo(const PluginUpdater::UpdateInfo &info);
|
||||
void startDownload();
|
||||
void updateProgress(qint64 received, qint64 total);
|
||||
void handleDownloadFinished(const QString &path);
|
||||
void handleDownloadError(const QString &error);
|
||||
|
||||
private:
|
||||
PluginUpdater *m_updater;
|
||||
QVBoxLayout *m_layout;
|
||||
QLabel *m_titleLabel;
|
||||
QLabel *m_versionLabel;
|
||||
QLabel *m_changelogLabel{nullptr};
|
||||
QTextEdit *m_changelogText{nullptr};
|
||||
QProgressBar *m_progress;
|
||||
QPushButton *m_downloadButton;
|
||||
QPushButton *m_closeButton;
|
||||
PluginUpdater::UpdateInfo m_updateInfo;
|
||||
};
|
||||
|
||||
} // namespace QodeAssist
|
Loading…
Reference in New Issue
Block a user