Compare commits

...

1 Commits

6 changed files with 492 additions and 108 deletions

View File

@ -1,4 +1,4 @@
QT += core gui
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
@ -20,6 +20,7 @@ SOURCES += \
hubmainwidget.cpp
HEADERS += \
downloadmanager.h \
hubmainwidget.h
FORMS += \

198
CetHub/downloadmanager.h Normal file
View File

@ -0,0 +1,198 @@
#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H
#include <QApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
#include <QProgressDialog>
#include <QPushButton>
#include <QUrl>
#include <QDebug>
class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = nullptr) : QObject(parent), m_manager(new QNetworkAccessManager(this)) {}
// void downloadFile(const QUrl &url, const QString &destinationFilePath)
// {
// m_destinationFilePath = destinationFilePath;
// QNetworkRequest request(url);
// // Устанавливаем время ожидания тайм-аута передачи сети
// request.setTransferTimeout(5000); // 5000 миллисекунд (5 секунд)
// m_reply = m_manager->get(request);
// connect(m_reply, &QNetworkReply::downloadProgress, this, &Downloader::onDownloadProgress);
// connect(m_reply, &QNetworkReply::finished, this, &Downloader::onDownloadFinished);
// // Обрабатываем ошибки сети
// connect(m_reply, &QNetworkReply::error, this, &Downloader::onErrorOccurred);
//// connect(m_reply, &QNetworkReply::error, this, &Downloader::onDownloadError);//QNetworkReply::errorOccurred(QNetworkReply::NetworkError)
// //connect(m_reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &Downloader::onError);
// }
signals:
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
void downloadFinished(bool success);
void downloadError(const QString &errorString);
private slots:
void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
emit downloadProgress(bytesReceived, bytesTotal);
}
void onDownloadFinished()
{
if (m_reply->error() == QNetworkReply::NoError)
{
qDebug() << "finish download";
// Проверяем статус HTTP ответа
if (m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 404)
{
emit downloadError("File not found.");
emit downloadFinished(false);
return;
}
QFile file(m_destinationFilePath);
if (file.open(QIODevice::WriteOnly))
{
file.write(m_reply->readAll());
file.close();
emit downloadFinished(true);
}
else
{
emit downloadError("Failed to open destination file for writing.");
emit downloadFinished(false);
}
}
else
{
qDebug() << "finish download and error";
emit downloadError(m_reply->errorString());
emit downloadFinished(false);
}
m_reply->deleteLater();
}
void onErrorOccurred(QNetworkReply::NetworkError code)
{
qDebug() << "Error occurred:" << m_reply->errorString();
qDebug() << "Network error occurred:" << code;
emit downloadError(m_reply->errorString());
emit downloadFinished(false);
}
// void onDownloadError(QNetworkReply::NetworkError code)
// {
// qDebug() << "Network error occurred:" << code;
// emit downloadError(m_reply->errorString());
// emit downloadFinished(false);
// }
private:
QNetworkAccessManager *m_manager;
QNetworkReply *m_reply;
QString m_destinationFilePath;
public:
void downloadFile(const QUrl &url, const QString &destinationFilePath)
{
m_destinationFilePath = destinationFilePath;
QNetworkRequest request(url);
// Устанавливаем время ожидания тайм-аута передачи сети
//request.setTransferTimeout(5000); // 5000 миллисекунд (5 секунд)
m_reply = m_manager->get(request);
connect(m_reply, &QNetworkReply::downloadProgress, this, &Downloader::onDownloadProgress);
connect(m_reply, &QNetworkReply::finished, this, &Downloader::onDownloadFinished);
// Обрабатываем ошибки сети
connect(m_reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &Downloader::onErrorOccurred);
// connect(m_reply, &QNetworkReply::error, this, &Downloader::onDownloadError);//QNetworkReply::errorOccurred(QNetworkReply::NetworkError)
//connect(m_reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &Downloader::onError);
}
};
//enum UpdateErrorCode {
// UpdateNoError = 0,
// DownloadError = 1,
// RenameError = 2,
// DownloadCancelled = 3
//};
//class DownloadManager : public QObject {
// Q_OBJECT
//public:
// DownloadManager(QObject *parent = nullptr) : QObject(parent) {
// connect(&manager, &QNetworkAccessManager::finished, this, &DownloadManager::onDownloadFinished);
// }
// void downloadFile(const QUrl &url, const QString &outputFileName) {
// QNetworkRequest request(url);
// currentDownload = manager.get(request);
// outputFile.setFileName(outputFileName);
// if (!outputFile.open(QIODevice::WriteOnly)) {
// emit downloadError(DownloadError);
// return;
// }
// connect(currentDownload, &QNetworkReply::downloadProgress, this, &DownloadManager::onDownloadProgress);
// connect(currentDownload, &QNetworkReply::readyRead, this, [this]() {
// outputFile.write(currentDownload->readAll());
// });
// }
// void cancelDownload() {
// if (currentDownload) {
// currentDownload->abort();
// }
// }
//signals:
// void downloadProgress(qint64 bytesRead, qint64 totalBytes);
// void downloadError(int errorCode);
// void downloadFinished();
//private slots:
// void onDownloadFinished(QNetworkReply *reply) {
// if (reply->error()) {
// emit downloadError(DownloadError);
// } else {
// outputFile.close();
// emit downloadFinished();
// }
// }
// void onDownloadProgress(qint64 bytesRead, qint64 totalBytes) {
// emit downloadProgress(bytesRead, totalBytes);
// }
//private:
// QNetworkAccessManager manager;
// QNetworkReply *currentDownload = nullptr;
// QFile outputFile;
//};
#endif // DOWNLOADMANAGER_H

View File

@ -2,11 +2,12 @@
#include "ui_hubmainwidget.h"
#include "QtNetwork/QNetworkReply"
HubMainWidget::HubMainWidget(QWidget *parent)
HubMainWidget::HubMainWidget(QWidget *parent, QApplication *app)
: QWidget(parent)
, ui(new Ui::HubMainWidget)
{
ui->setupUi(this);
parentApp = app;
connect(&sysTimer, &QTimer::timeout, this, [this]()
{
ui->dateTimeEdit->setTime(QTime::currentTime());
@ -14,80 +15,122 @@ HubMainWidget::HubMainWidget(QWidget *parent)
});
sysTimer.start(1000);
getModules();
setupTableHeaders();
getModules();
}
bool HubMainWidget::getModules()
{
dllInfo UnionCom;
UnionCom.libName = "Терминал CAN, RS, Modbus";
QStringList appDep;
appInfo UnionCom;
UnionCom.appName = "Терминал CAN, RS, Modbus";
UnionCom.fileName = "UnionCom";
UnionCom.initFuncName = "init";
UnionCom.adr = "https://git.arktika.cyou/Tenocha/UnionComDLL";
UnionCom.fileDir = QDir::currentPath() + "/UnionCom/";
UnionCom.sourceAdr = "https://git.arktika.cyou/Tenocha/UnionComDLL";
UnionCom.downloadAdr = "https://git.arktika.cyou/Tenocha/UnionComDLL/archive/Release.zip";
connectLibrary(UnionCom);
connectModule(UnionCom);
dllInfo M3KTE_TERM;
M3KTE_TERM.libName = "МЗКТЕ Терминал";
appInfo M3KTE_TERM;
M3KTE_TERM.appName = "МЗКТЕ Терминал";
M3KTE_TERM.fileName = "M3KTE_TERM";
M3KTE_TERM.initFuncName = "init";
M3KTE_TERM.adr = "https://git.arktika.cyou/Tenocha/M3KTE_TERM";
M3KTE_TERM.fileDir = QDir::currentPath() + "/M3KTE_TERM/";
M3KTE_TERM.sourceAdr = "https://git.arktika.cyou/Tenocha/M3KTE_TERM";
M3KTE_TERM.downloadAdr = "https://git.arktika.cyou/Tenocha/M3KTE_TERM/releases/download/Pre-release/M3KTETERM.rar";
connectLibrary(M3KTE_TERM);
connectModule(M3KTE_TERM);
dllInfo LineRingerLib;
LineRingerLib.libName = "Поиск modbus устройств";
LineRingerLib.fileName = "LineRingerLib32Bit";
LineRingerLib.initFuncName = "init";
LineRingerLib.adr = "https://git.arktika.cyou/Tenocha/LineRingerDLL";
appInfo LineRingerLib;
LineRingerLib.appName = "Поиск modbus устройств";
LineRingerLib.fileName = "LineRinger";
LineRingerLib.fileDir = QDir::currentPath() + "/LineRinge/";
LineRingerLib.sourceAdr = "https://git.arktika.cyou/Tenocha/LineRingerDLL";
LineRingerLib.downloadAdr = "https://git.arktika.cyou/Tenocha/LineRingerDLL/archive/Release.zip";
connectLibrary(LineRingerLib);
connectModule(LineRingerLib);
appInfo CanGaroo;
CanGaroo.appName = "CanGaroo";
CanGaroo.fileName = "cangaroo";
CanGaroo.fileDir = QDir::currentPath() + "/CanGaroo/";
CanGaroo.sourceAdr = "https://git.arktika.cyou/Tenocha/LineRingerDLL";
CanGaroo.downloadAdr = "https://git.arktika.cyou/Tenocha/LineRingerDLL/archive/Release.zip";
connectModule(CanGaroo);
//LogsViewS
appInfo LogsViewS;
LogsViewS.appName = "LogsViewS";
LogsViewS.fileName = "LogsViewS";
LogsViewS.fileDir = QDir::currentPath() + "/LogsViewS/";
LogsViewS.sourceAdr = "http://git.arktika.cyou/Tenocha/LineRingerDLL";
LogsViewS.downloadAdr = "http://git.arktika.cyou/all_public/LogViewNovel/raw/branch/master/LogsView_64/LogsViewS_64.exe";
connectModule(LogsViewS);
ui->appTable->resizeColumnsToContents();
setupTableHeaders();
return true;
}
bool HubMainWidget::connectLibrary(dllInfo modul)
void HubMainWidget::setupTableHeaders()
{
QLibrary myLib(modul.fileName);
myLib.load();
//QString check = myLib.errorString();
unsigned newRow = ui->libraryTable->rowCount();
ui->libraryTable->insertRow(newRow);
ui->libraryTable->setItem(newRow, 0, new QTableWidgetItem(modul.libName));
ui->libraryTable->setItem(newRow, 1, new QTableWidgetItem(modul.fileName));
QTableWidgetItem *item = new QTableWidgetItem();
item->setText("");
QLabel *url = new QLabel();
url->setText(tr("<a href=\"%1\">Source</a>").arg(modul.adr.toString()));
url->setTextFormat(Qt::RichText);
url->setTextInteractionFlags(Qt::TextBrowserInteraction);
url->setOpenExternalLinks(true);
ui->libraryTable->setCellWidget(newRow, 3, url);
//ui->libraryTable->setItem(newRow, 2, new QTableWidgetItem(modul.adr));
if(myLib.isLoaded())
{
typedef QWidget* (*DLL_Init_Function)(QWidget*);
DLL_Init_Function DLL_Init = (DLL_Init_Function) myLib.resolve(modul.initFuncName.toUtf8());
if(DLL_Init)
{
item->setCheckState(Qt::Checked);
ui->libraryTable->setItem(newRow, 2, item);
modul.widget = DLL_Init(nullptr);
connectedModules.append(modul);
ui->appBox->addItem(modul.libName);
ui->libraryTable->resizeColumnsToContents();
return true;
}
}
else
{
item->setCheckState(Qt::Unchecked);
ui->libraryTable->setItem(newRow, 2, item);
connectedModules.append(modul);
ui->appBox->addItem(modul.libName);
ui->libraryTable->resizeColumnsToContents();
}
return false;
// Устанавливаем заголовки для каждой колонки
QStringList headers;
headers << "Наличие файла" // колонка 0
<< "Название программы" // колонка 1
<< "Название файла" // колонка 2
<< "Источник"; // колонка 3
ui->appTable->setHorizontalHeaderLabels(headers);
}
void HubMainWidget::connectModule(appInfo &info)
{
// 1. Проверка наличия файла .exe в директории
QString dirPath = info.fileDir; // предполагается, что это уже полный путь
QString filePath = dirPath + "/" + info.fileName;
// Проверяем наличие файла с расширением .exe
QString exeFilePath = filePath + ".exe";
info.isFileExists = QFile::exists(exeFilePath);
// 2. Создаём новую строку таблицы
int row = ui->appTable->rowCount();
ui->appTable->insertRow(row);
// 3. Создаём виджеты и заполняем ячейки таблицы
// 1) Наличие файла (QCheckBox)
QCheckBox *fileCheckBox = new QCheckBox();
fileCheckBox->setChecked(info.isFileExists);
QWidget *fileCellWidget = new QWidget();
QHBoxLayout *fileLayout = new QHBoxLayout(fileCellWidget);
fileLayout->addWidget(fileCheckBox);
fileLayout->setAlignment(Qt::AlignCenter);
fileLayout->setContentsMargins(0,0,0,0);
fileCellWidget->setLayout(fileLayout);
ui->appTable->setCellWidget(row, 0, fileCellWidget);
// 2) Название программы (QString)
QTableWidgetItem *nameItem = new QTableWidgetItem(info.appName);
ui->appTable->setItem(row, 1, nameItem);
// 3) Название файла (QString)
QTableWidgetItem *fileNameItem = new QTableWidgetItem(info.fileName);
ui->appTable->setItem(row, 2, fileNameItem);
// 4) Источник файла (QString из sourceAdr)
QLabel *sourceLabel = new QLabel();
QString linkText = QString("<a href=\"%1\">Source</a>").arg(info.sourceAdr.toString());
sourceLabel->setText(linkText);
sourceLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
sourceLabel->setOpenExternalLinks(true);
ui->appTable->setCellWidget(row, 3, sourceLabel);
// 4. Добавляем структуру в QVector
connectedModules.append(info);
// 5. Добавляем название программы
ui->appBox->addItem(info.appName);
}
HubMainWidget::~HubMainWidget()
@ -98,27 +141,161 @@ HubMainWidget::~HubMainWidget()
void HubMainWidget::on_openOrDownloadButton_clicked()
{
if(ui->appBox->count()!=0)
int index = ui->appBox->currentIndex();
if (index < 0 || index >= connectedModules.size())
return; // Защита
auto &module = connectedModules.at(index);
QString filePath = module.fileDir + "/" + module.fileName + ".exe";
if (QFile::exists(filePath))
{
if(connectedModules.at(ui->appBox->currentIndex()).widget != nullptr)
{
connectedModules.at(ui->appBox->currentIndex()).widget->show();
}
else
{
QDesktopServices::openUrl(connectedModules.at(ui->appBox->currentIndex()).adr);
// // Файл есть, запускаем
QProcess process;
process.setWorkingDirectory(module.fileDir);
process.setProgram(filePath);
process.startDetached();
}
else
{
// Получаем путь к директории
QDir dir(module.fileDir);
// Проверяем, существует ли директория
if (!dir.exists()) {
// Создаём директорию (включая все недостающие промежуточные папки)
if (!dir.mkpath(".")) {
QMessageBox::warning(this, "Ошибка", "Не удалось создать директорию: " + module.fileDir);
return; // Выходим из функции, т.к. сохранить файл невозможно
}
}
// Путь для сохранения файла (включая имя файла и расширение)
QString saveFilePath = filePath;
// Создаем объект Downloader
Downloader downloader;
// Создаем диалог прогресса
QProgressDialog progressDialog;
progressDialog.setWindowTitle("Downloading");
progressDialog.setLabelText("Downloading file:\n" + module.downloadAdr.toString() + "...");
progressDialog.setCancelButton(new QPushButton("Cancel"));
progressDialog.setMinimumDuration(200);
// Связываем прогресс скачивания с диалогом
QObject::connect(&downloader, &Downloader::downloadProgress, [&](qint64 bytesReceived, qint64 bytesTotal) {
progressDialog.setMaximum(bytesTotal);
progressDialog.setValue(bytesReceived);
});
// Обработка завершения скачивания
QObject::connect(&downloader, &Downloader::downloadFinished, [&](bool success) {
if (success) {
QMessageBox::information(nullptr, "Загрузка завершена", "Файл успешно скачан:\n" + saveFilePath);
QWidget *statusWidget = ui->appTable->cellWidget(index, 0);
if (statusWidget) {
QCheckBox *statusCheckBox = statusWidget->findChild<QCheckBox *>();
if (statusCheckBox) {
statusCheckBox->setChecked(true); // файл есть
}
on_appBox_currentIndexChanged(ui->appBox->currentIndex());
}
} else {
QMessageBox::warning(nullptr, "Ошибка", "Ошибка при скачивании файла");
QFile::remove(saveFilePath); // удаляем поврежденный или неполный файл
if (dir.exists()) {
if (!dir.removeRecursively()) {
QMessageBox::warning(this, "Ошибка", "Не удалось удалить созданную директорию: " + module.fileDir);
}
}
}
progressDialog.setValue(progressDialog.maximum());
progressDialog.close();
});
// Запускаем скачивание
qDebug() << "Start download:" << module.downloadAdr.toString() << " to " << saveFilePath;
downloader.downloadFile(module.downloadAdr, saveFilePath);
// Показываем диалог прогресса
progressDialog.exec();
// // Файл отсутствует, скачиваем
// QUrl downloadUrl(module.downloadAdr);
// QNetworkRequest request(downloadUrl);
// QNetworkReply *reply = networkManager->get(request);
// // Ожидаем завершения скачивания
// QEventLoop loop;
// connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
// loop.exec();
// if (reply->error() == QNetworkReply::NoError)
// {
// QByteArray data = reply->readAll();
// // Получаем путь к директории
// QDir dir(module.fileDir);
// // Проверяем, существует ли директория
// if (!dir.exists()) {
// // Создаём директорию (включая все недостающие промежуточные папки)
// if (!dir.mkpath(".")) {
// QMessageBox::warning(this, "Ошибка", "Не удалось создать директорию: " + module.fileDir);
// return; // Выходим из функции, т.к. сохранить файл невозможно
// }
// }
// // Записываем файл
// QFile file(filePath);
// if (file.open(QIODevice::WriteOnly))
// {
// file.write(data);
// file.close();
// QMessageBox::information(this, "Загрузка завершена", "Файл успешно скачан.");
// // После скачивания можно запустить файл
// //QProcess::startDetached(filePath);
// // Обновляем статус наличия файла (чекбокс)
// QWidget *statusWidget = ui->appTable->cellWidget(index, 0);
// if (statusWidget) {
// QCheckBox *statusCheckBox = statusWidget->findChild<QCheckBox *>();
// if (statusCheckBox) {
// statusCheckBox->setChecked(true); // файл есть
// }
// }
// connectedModules[index].isFileExists = true;
// on_appBox_currentIndexChanged(ui->appBox->currentIndex());
// }
// else
// {
// QMessageBox::warning(this, "Ошибка", "Не удалось сохранить файл.");
// }
// }
// else
// {
// QMessageBox::warning(this, "Ошибка загрузки", reply->errorString());
// }
// reply->deleteLater();
}
}
void HubMainWidget::on_appBox_currentIndexChanged(int index)
{
if(connectedModules.at(index).widget == nullptr)
{
ui->openOrDownloadButton->setText("Скачать");
}
else
if (index < 0 || index >= connectedModules.size())
return; // Защита от выхода за границы
const appInfo &info = connectedModules.at(index);
if (info.isFileExists)
{
ui->openOrDownloadButton->setText("Открыть");
}
else
{
ui->openOrDownloadButton->setText("Скачать");
}
}

View File

@ -4,11 +4,28 @@
#include <QWidget>
#include <QTime>
#include <QTimer>
#include <QLibrary>
#include <QFile>
#include <QDir>
#include <QCheckBox>
#include <QTableWidgetItem>
#include <QHBoxLayout>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QEventLoop>
#include <QProcess>
#include <QMessageBox>
#include <QUrl>
#include <QLabel>
#include <QProgressDialog>
#include "windows.h"
#include "downloadmanager.h"
#include <QDesktopServices>
#include "QtNetwork/QNetworkAccessManager"
QT_BEGIN_NAMESPACE
namespace Ui { class HubMainWidget; }
@ -19,7 +36,7 @@ class HubMainWidget : public QWidget
Q_OBJECT
public:
HubMainWidget(QWidget *parent = nullptr);
HubMainWidget(QWidget *parent = nullptr, QApplication *app = nullptr);
~HubMainWidget();
private slots:
@ -29,21 +46,24 @@ private slots:
private:
QTimer sysTimer;
QApplication *parentApp;
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
struct dllInfo
struct appInfo
{
QWidget* widget = nullptr;
QString libName;
QString fileName;
QString initFuncName;
QUrl adr;
QString appName = "appName";
QString fileName = "fileName";
bool isFileExists = false;
QString fileDir = "fileDir";
QUrl sourceAdr;
QUrl downloadAdr;
};
QVector<dllInfo>connectedModules;
QVector<appInfo>connectedModules;
bool getModules();
bool connectLibrary(dllInfo modul);
void connectModule(appInfo &info);
void setupTableHeaders();
Ui::HubMainWidget *ui;
};

View File

@ -80,7 +80,7 @@
</layout>
</item>
<item row="0" column="0">
<widget class="QTableWidget" name="libraryTable">
<widget class="QTableWidget" name="appTable">
<property name="enabled">
<bool>true</bool>
</property>
@ -90,6 +90,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="columnCount">
<number>4</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
@ -97,28 +100,12 @@
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>true</bool>
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Modul</string>
</property>
</column>
<column>
<property name="text">
<string>DLL</string>
</property>
</column>
<column>
<property name="text">
<string>Finded</string>
</property>
</column>
<column>
<property name="text">
<string>Link</string>
</property>
</column>
<column/>
<column/>
<column/>
<column/>
</widget>
</item>
</layout>

View File

@ -5,7 +5,8 @@
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
HubMainWidget w;
w.show();
a.addLibraryPath(QDir::currentPath());
HubMainWidget *w = new HubMainWidget(nullptr, &a);
w->show();
return a.exec();
}