mainwindow.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #include "mainwindow.h"
  2. #include <QtCore/qlist.h>
  3. #include <QtCore/qobject.h>
  4. #include <QDebug>
  5. #include <QPushButton>
  6. #include <QWidget>
  7. #include "../components/loadingWidget.h"
  8. #include "../mqtt/mqttclient.h"
  9. #include "../serial/serialgpsthread.h"
  10. #include "../ui_mainwindow.h"
  11. #include "../utils/backendapimanager.h"
  12. #include "../utils/global.h"
  13. #include "../utils/jobs.h"
  14. #include "../utils/logger.h"
  15. // 定义 ANzI 转义序列来设置颜色
  16. #define ANSI_COLOR_GREEN "\x1B[32m"
  17. #define ANSI_COLOR_RESET "\x1B[0m"
  18. #include <QMessageBox>
  19. #include <exception>
  20. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
  21. try {
  22. this->setWindowFlags(Qt::FramelessWindowHint | Qt::Window);
  23. this->setWindowState(Qt::WindowMaximized); // Maximizes the window
  24. this->setStyleSheet("QWidget { font-size: 16px; }");
  25. this->setStyleSheet("QPushButton { font-size: 16px; }");
  26. ui->setupUi(this);
  27. LoadingWidget::init(ui->stackedWidget);
  28. initializeAnimate();
  29. initialMqttService();
  30. pageFactories[ui->btnHome] = new HomepageFactory();
  31. pageFactories[ui->btnNew] = new AddressFactory();
  32. pageFactories[ui->btnBlastProject] = new BlastProjectFactory();
  33. pageFactories[ui->btnEquipment] = new EquipmentFactory();
  34. pageFactories[ui->btnDet] = new DetInfoFactory();
  35. pageFactories[ui->btnBlastOper] = new BlastOperationFactory();
  36. pageFactories[ui->btnRecord] = new BlastRecordFactory();
  37. connect(ui->btnToggle, &QPushButton::clicked, this, &MainWindow::onToggleButtonClicked);
  38. for (auto *widget : left_button_station) {
  39. QPushButton *button = qobject_cast<QPushButton *>(widget);
  40. if (button) {
  41. connect(button, &QPushButton::clicked, this, [this, button] { onButtonClicked(button); });
  42. }
  43. }
  44. initDateTime();
  45. initialBtnSerial();
  46. // initialGPSSerial();
  47. ui->labLat->setText("经度: " + lat);
  48. ui->labLon->setText("维度: " + lon);
  49. connect(ui->btnClose, &QPushButton::clicked, this, &MainWindow::close);
  50. connect(this, &MainWindow::menubarTitleChanged, this, &MainWindow::updateProjectTitleLabel);
  51. } catch (const std::exception &ex) {
  52. Logger::getInstance().error(QString("Application crashed: %1").arg(ex.what()));
  53. QMessageBox::critical(this, "Error", QString("Application crashed: %1").arg(ex.what()));
  54. throw; // rethrow to allow further handling if needed
  55. } catch (...) {
  56. Logger::getInstance().error("Application crashed: Unknown exception");
  57. QMessageBox::critical(this, "Error", "Application crashed: Unknown exception");
  58. throw;
  59. }
  60. this->switchPage(ui->btnHome); // 默认显示首页
  61. }
  62. void MainWindow::updateProjectTitleLabel(const QString &newTitle) { ui->projectTitleLable->setText(newTitle); }
  63. void MainWindow::handleRefreshPage() {
  64. // 刷新页面
  65. ui->stackedWidget->currentWidget()->update();
  66. }
  67. void MainWindow::setMenubarTitle(const QString &newTitle) {
  68. if (m_currentProjectTitle != newTitle) {
  69. m_currentProjectTitle = newTitle;
  70. // Emit the signal to notify listeners (like our QLabel slot)
  71. emit menubarTitleChanged(m_currentProjectTitle);
  72. }
  73. }
  74. void MainWindow::initializeAnimate() {
  75. move(200, 200);
  76. animate_leftFrame = new QPropertyAnimation(ui->leftFrame, "minimumWidth");
  77. animate_leftFrame->setDuration(300);
  78. for (QObject *child : ui->left_buttonsBox->children()) {
  79. if (qobject_cast<QWidget *>(child)) {
  80. left_button_station.append(qobject_cast<QWidget *>(child));
  81. }
  82. }
  83. }
  84. void MainWindow::onToggleButtonClicked() {
  85. // 执行动画
  86. JOBS ::btn_animation(ui->leftFrame, animate_leftFrame);
  87. for (QWidget *b : left_button_station) {
  88. b->setProperty("spread", !b->property("spread").toBool());
  89. b->setStyleSheet(b->styleSheet());
  90. }
  91. }
  92. // 选中按钮
  93. void MainWindow::onButtonClicked(QPushButton *button) {
  94. setStyleSheets(static_cast<QPushButton *>(button));
  95. switchPage(static_cast<QPushButton *>(button));
  96. }
  97. void MainWindow::switchPage(QWidget *button) {
  98. LoadingWidget::showLoading(this, "请稍等");
  99. if (pageFactories.contains(button)) {
  100. PageFactory *factory = pageFactories[button];
  101. if (createdPageByButton.contains(button)) {
  102. QWidget *existingPage = createdPageByButton[button];
  103. existingPage->hide();
  104. ui->stackedWidget->removeWidget(existingPage);
  105. createdPageByButton.remove(button);
  106. }
  107. QWidget *newPage = factory->createPage(this);
  108. ui->stackedWidget->addWidget(newPage);
  109. ui->stackedWidget->setCurrentWidget(newPage);
  110. setMenubarTitle(qobject_cast<QPushButton *>(button)->text());
  111. createdPageByButton.insert(button, newPage);
  112. int pageCount = ui->stackedWidget->count();
  113. }
  114. LoadingWidget::hideLoading();
  115. }
  116. void MainWindow::initialMqttService() {
  117. Logger::getInstance().info("Start init Mqtt server.");
  118. if (mainMqttClient != nullptr) {
  119. QMqttSubscription *projectMsgSubsciber = mainMqttClient->subscribeToTopic(MQTT_TOPIC_COMPANY_PROJECTS_SUB);
  120. if (projectMsgSubsciber != nullptr) {
  121. connect(projectMsgSubsciber, &QMqttSubscription::messageReceived, this,
  122. &MainWindow::handleMqttProjectsMessage);
  123. } else {
  124. Logger::getInstance().error("Failed to subscribe to MQTT topic: " + MQTT_TOPIC_COMPANY_PROJECTS_SUB);
  125. }
  126. } else {
  127. Logger::getInstance().error("mainMqttClient is null, cannot initialize MQTT service");
  128. }
  129. }
  130. void MainWindow::publishBlastProjects() {
  131. // TODO: publish by emit message
  132. // QJsonArray jsonArray;
  133. // HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
  134. // QList<QSharedPointer<HProject>> projectsReg = dao.getAllHProjectsReg();
  135. // for (const auto &projectPtr : projectsReg) {
  136. // if (projectPtr) {
  137. // QByteArray projectJson = projectPtr->ProjectToJson(*projectPtr);
  138. // QJsonDocument doc = QJsonDocument::fromJson(projectJson);
  139. // jsonArray.append(doc.object());
  140. // }
  141. // }
  142. // QJsonDocument jsonDoc(jsonArray);
  143. // QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);
  144. // mainMqttClient->sendMessage(MQTT_TOPIC_COMPANY_PROJECTS_PUBLISH, jsonData, 2, true);
  145. }
  146. void MainWindow::handleMqttProjectsMessage(const QMqttMessage &message) {
  147. Logger::getInstance().info("Received Mqtt message on topic: " + message.topic().name() +
  148. ", message: " + QString::fromUtf8(message.payload()));
  149. QJsonDocument jsonDoc = QJsonDocument::fromJson(message.payload());
  150. if (!jsonDoc.isNull() && jsonDoc.isObject()) {
  151. // 注册工程信息
  152. QJsonObject jsonObj = jsonDoc.object();
  153. if (jsonObj.contains("msgType") && jsonObj["msgType"].toString() == "blastSuccess") {
  154. // 爆破成功, 更新状态; 尤其是离线爆破的; 服务器收到爆破记录后发布
  155. HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
  156. for (const QJsonValue &projectUuid : jsonObj["projectUuids"].toArray()) {
  157. qDebug() << "Received offline project blasted UUID: " << projectUuid;
  158. dao.updateBlastStatusByUuid(projectUuid.toString(), BlastStatus::Blasted);
  159. }
  160. publishBlastProjects();
  161. }
  162. }
  163. }
  164. void MainWindow::setStyleSheets(QPushButton *selectedButton) {
  165. for (auto *b : left_button_station) {
  166. b->setProperty("selected", b == selectedButton);
  167. b->setStyleSheet(b->styleSheet()); // 刷新显示
  168. }
  169. }
  170. // 处理 MQTT 连接成功的槽函数
  171. void MainWindow::onMqttConnected() {
  172. m_isMqttConnected = true;
  173. Logger::getInstance().info("Mqtt connected.");
  174. }
  175. void MainWindow::initialBtnSerial() {
  176. bool success;
  177. serialTool = SerialTool::getInstance(this, &success);
  178. connect(serialTool, &SerialTool::serialPortOpened, this, &MainWindow::onSerialToolCreated);
  179. serialTool->setupSerialPort();
  180. Logger::getInstance().info("Fire buttons initialized");
  181. }
  182. void MainWindow::onSerialToolCreated() {
  183. m_btnSerialInitialized = true;
  184. serialTool->releaseInstance();
  185. qDebug() << ANSI_COLOR_GREEN << "Serial tool initialized" << ANSI_COLOR_RESET;
  186. Logger::getInstance().info("SerialTool initialized");
  187. }
  188. void MainWindow::initialGPSSerial() {
  189. Logger::getInstance().info("开始初始化GPS");
  190. SerialGPSThread *threadGPS = new SerialGPSThread(this);
  191. connect(threadGPS, &SerialGPSThread::storedGNRMCDataUpdated, this, &MainWindow::handleStoredGNRMCData);
  192. threadGPS->start();
  193. }
  194. // 槽函数,用于接收 RMCData 数据
  195. void MainWindow::handleStoredGNRMCData(const RMCData &data) {
  196. if (data.isValid) {
  197. lat = QString::number(data.latitude);
  198. lon = QString::number(data.longitude);
  199. } else {
  200. lat = "定位失败";
  201. lon = "定位失败";
  202. }
  203. ui->labLat->setText("经度: " + lat);
  204. ui->labLon->setText("纬度: " + lon);
  205. labLat = lat;
  206. labLon = lon;
  207. }
  208. void MainWindow::initDateTime() {
  209. timeThread = new TimeUpdateThread(this);
  210. connect(timeThread, &TimeUpdateThread::timeUpdated, this, &MainWindow::onTimeUpdated);
  211. timeThread->start();
  212. }
  213. void MainWindow::onTimeUpdated(const QString &timeString) { ui->dateTimeShow->setText(timeString); }
  214. MainWindow::~MainWindow() {
  215. timeThread->stop();
  216. delete ui;
  217. }
  218. void MainWindow::mousePressEvent(QMouseEvent *event) {
  219. // if (event->button() == Qt::LeftButton) {
  220. // m_dragPosition = event->globalPos() - frameGeometry().topLeft();
  221. // event->accept();
  222. // }
  223. }
  224. void MainWindow::mouseMoveEvent(QMouseEvent *event) {
  225. // if (event->buttons() & Qt::LeftButton) {
  226. // move(event->globalPos() - m_dragPosition);
  227. // event->accept();
  228. // }
  229. }