#include "mainwindow.h" #include #include #include #include "appcontext.h" #include "canvas.h" #include "logger.h" #include "utils.h" #include "abstractwidget.h" #include #include #include #include "defs.h" MainWindow::MainWindow(const int &frequency, QWidget *parent) : QMainWindow(parent) , m_pStackedWidget(nullptr) , m_pErrStrLabel(nullptr) , m_broadcast(Broadcast(BROADCAST_PORT)) , m_frequency(frequency) { setWindowFlags(Qt::FramelessWindowHint | Qt::Window); init_ui(); Network &network = AppContext::instance().network(); connect(&network, &Network::updateScreen, this, &MainWindow::onUpdateScreen); SerialPort &serialPort = AppContext::instance().serialPort(); connect(&serialPort, &SerialPort::pageSwitch, this, &MainWindow::onPageSwitdh); HttpServer &httpServer = AppContext::instance().httpServer(); connect(&httpServer, &HttpServer::monitorConfigureUpdate, this, &MainWindow::onConfigureUpdate); connect(&httpServer, &HttpServer::reloadCanvas, this, &MainWindow::onReloadCanvas); DataFifo &dataFifo = AppContext::instance().dataFifo(); connect(&dataFifo, &DataFifo::updateScreen, this, &MainWindow::onUpdateScreen); connect(&m_reportTimer, &QTimer::timeout, this, &MainWindow::onReport); m_reportTimer.start(1000); connect(&m_timer, &QTimer::timeout, this, [this](){ DataFifo &dataFifo = AppContext::instance().dataFifo(); qint64 recvTimestamp = dataFifo.recvTimestamp(); qint64 timestamp = QDateTime::currentMSecsSinceEpoch(); if((timestamp - recvTimestamp) >= 5000) { emit disconnect(); LOG_WARN("data transfer interrupted"); if(!m_pErrStrLabel) { QFont font; font.setPixelSize(40); font.setBold(true); m_pErrStrLabel = new QLabel("数据传输中断!", this); m_pErrStrLabel->resize(this->size()); m_pErrStrLabel->setFont(font); m_pErrStrLabel->setAlignment(Qt::AlignCenter); m_pErrStrLabel->setStyleSheet("QLabel { background-color: #FFD6D6; color: #D8000C; padding: 4px; border-radius: 4px; }"); m_pErrStrLabel->move((this->width() - m_pErrStrLabel->width()) / 2, (this->height() - m_pErrStrLabel->height()) / 2); m_pErrStrLabel->show(); } } else { if(m_pErrStrLabel) { delete m_pErrStrLabel; m_pErrStrLabel = nullptr; } } // LOG_INFO("{} {}", timestamp, recvTimestamp); }); m_timer.start(5000); // connect(&m_updateScreenTimer, &QTimer::timeout, this, &MainWindow::onUpdateScreen); // m_updateScreenTimer.start(1000 / m_frequency); } MainWindow::~MainWindow() { } void MainWindow::init_ui() { QWidget *pCentralWidget = new QWidget(this); setCentralWidget(pCentralWidget); QVBoxLayout *pMainLayout = new QVBoxLayout(pCentralWidget); m_pStackedWidget = new QStackedWidget(pCentralWidget); pMainLayout->addWidget(m_pStackedWidget); pMainLayout->setSpacing(0); pMainLayout->setContentsMargins(0, 0, 0, 0); if(reload()) { setCurrentCanvas(); } } bool MainWindow::reload() { ProjectManager &projectMgr = AppContext::instance().projectManager(); QString fileName = QString("%1/%2").arg(QDir::currentPath(), "conf/monitor.xml"); bool result = projectMgr.openProject(fileName); if(result) { LOG_INFO("open monitor config xml success: {}, canvas count: {}", fileName.toUtf8().data(), projectMgr.canvasCount()); } else { LOG_ERROR("open monitor config xml failed: {}", fileName.toUtf8().data()); return false; } LOG_INFO("start reload monitor configure"); int canvasCount = projectMgr.canvasCount(); for(int i = 0; i < canvasCount; i++) { LOG_DEBUG("----------------canvas {}----------------", i); Canvas *pCanvas = new Canvas(projectMgr.canvas(i), m_pStackedWidget); pCanvas->resize(1280, 720); m_pStackedWidget->insertWidget(i, pCanvas); } LOG_INFO("reload monitor configure complete"); return true; } void MainWindow::clear() { LOG_INFO("begin release exist canvas"); { QList widgets; for (int i = 0; i < m_pStackedWidget->count(); ++i) { widgets << m_pStackedWidget->widget(i); } for (QWidget *w : widgets) { Canvas *pCanvas = static_cast(w); pCanvas->clear(); m_pStackedWidget->removeWidget(w); delete w; } } ProjectManager &projectMgr = AppContext::instance().projectManager(); projectMgr.closeProject(); LOG_INFO("release exist canvas complete, widget count: {}", m_pStackedWidget->count()); } void MainWindow::setCurrentCanvas(bool isNewComfigure) { int index = 0; if(isNewComfigure) { int canvasCount = m_pStackedWidget->count(); for(int i = 0; i < canvasCount; i++) { QWidget *pWidget = m_pStackedWidget->widget(i); Canvas *pCanvas = static_cast(pWidget); if(pCanvas->isDefault()) { index = i; break; } } } else { QSettings settings("storage/conf/settings.ini", QSettings::IniFormat); settings.setIniCodec("UTF-8"); settings.beginGroup("CANVAS"); if(settings.contains("INDEX")) { index = settings.value("INDEX").toInt(); LOG_INFO("find saved canvas index, set index {}", index); } else { LOG_INFO("not find saved canvas index, set index 0"); settings.setValue("INDEX", 0); } settings.endGroup(); } m_pStackedWidget->setCurrentIndex(index); ProjectManager &projectMgr = AppContext::instance().projectManager(); projectMgr.setCurrentCanvasIndex(index); } void MainWindow::onUpdateScreen(const QJsonObject &obj) { // QElapsedTimer timer; // timer.start(); // 开始计时 LOG_DEBUG("update screen"); ProjectManager &projectMgr = AppContext::instance().projectManager(); // DataDict &dataDict = AppContext::instance().dataDict(); // const QJsonObject obj = dataDict.data(); int canvasCount = projectMgr.canvasCount(); QString timestamp = obj["timestamp"].toString(); LOG_DEBUG("timestamp {}", timestamp.toStdString()); timestamp = QString("%1").arg(timestamp.toULongLong() / 1000000); QList widgets; QList parameters; for(int i = 0; i < canvasCount; i++) { Canvas *pCanvas = static_cast(m_pStackedWidget->widget(i)); if(!pCanvas) { LOG_ERROR("error current canvas"); return; } widgets = pCanvas->widgetList(); parameters = pCanvas->parameterList(); if(widgets.count() != parameters.count()) { LOG_ERROR("error widget count and parameters count"); return; } int count = widgets.count(); for(int j = 0; j < count; j++) { AbstractWidget *pAbstractWidget = static_cast(widgets[j]); QStringList widgetParameters; QMetaObject::invokeMethod(pAbstractWidget, "parameters", Qt::AutoConnection, Q_RETURN_ARG(QStringList, widgetParameters)); for(auto parameter : widgetParameters) { if(obj.contains(parameter)) { QMetaObject::invokeMethod( pAbstractWidget, "setValue", Qt::AutoConnection, Q_ARG(QString, parameter), Q_ARG(QVariant, obj[parameter].toVariant()), Q_ARG(QString, timestamp)); } } if(pCanvas == m_pStackedWidget->currentWidget()) { QMetaObject::invokeMethod(pAbstractWidget, "redraw", Qt::AutoConnection); } } } // qint64 duration = timer.elapsed(); // 获取经过的毫秒数 qint64 startTime = obj["time_arrived"].toString().toLongLong(); qint64 endTime = Utils::currentNanoTimestamp(); LOG_DEBUG("startTime: {}, endTime: {}", startTime, endTime); LOG_DEBUG("update screen duration: {}ns", endTime - startTime); } void MainWindow::onPageSwitdh(int state) { ProjectManager &projectMgr = AppContext::instance().projectManager(); int canvasCount = projectMgr.canvasCount(); if (canvasCount <= 0) return; int currentIndex = m_pStackedWidget->currentIndex(); int nextIndex = currentIndex; if (state < 0) { // 上一页 nextIndex = (currentIndex - 1 + canvasCount) % canvasCount; LOG_INFO("page up: {}", nextIndex); } else if (state > 0) { // 下一页 nextIndex = (currentIndex + 1) % canvasCount; LOG_INFO("page down: {}", nextIndex); } else { return; // state == 0 不翻页 } m_pStackedWidget->setCurrentIndex(nextIndex); projectMgr.setCurrentCanvasIndex(nextIndex); QSettings settings("storage/conf/settings.ini", QSettings::IniFormat); settings.setIniCodec("UTF-8"); settings.beginGroup("CANVAS"); settings.setValue("INDEX", nextIndex); settings.endGroup(); } void MainWindow::onConfigureUpdate(const QString &filename) { clear(); QString srcFileName = filename; QString dstFileName = QString("%1/%2").arg(QDir::currentPath(), "conf/monitor.xml"); bool ret; LOG_INFO("begin delete current monitor configure..."); QFile dstFile = QFile(dstFileName); if(dstFile.exists()) { ret = dstFile.remove(); if(ret) { LOG_INFO("remove current monitor configure successfully"); } else { LOG_ERROR("remove current monitor configure failed"); return; } } else { QFileInfo fileInfo(dstFileName); QDir dir = fileInfo.absoluteDir(); if(!dir.exists()) dir.mkpath(dir.path()); } LOG_INFO("begin copy new monitor configure..."); QFile srcFile = QFile(srcFileName); if(srcFile.exists()) { ret = QFile::copy(srcFileName, dstFileName); if(ret) { LOG_INFO("update monitor configure successfully"); } else { LOG_ERROR("update monitor configure failed"); return; } } else { LOG_ERROR("update monitor configure file not exist"); return; } if(reload()) { setCurrentCanvas(true); } LOG_INFO("update: default canvas index is {}", m_pStackedWidget->currentIndex()); QSettings settings("storage/conf/settings.ini", QSettings::IniFormat); settings.setIniCodec("UTF-8"); settings.beginGroup("CANVAS"); settings.setValue("INDEX", m_pStackedWidget->currentIndex()); settings.endGroup(); } void MainWindow::onReloadCanvas() { // reloadCanvas(); clear(); if(reload()) { setCurrentCanvas(); } } void MainWindow::onReport() { ProjectManager &projectMgr = AppContext::instance().projectManager(); QJsonObject obj = AppContext::instance().sysState().sysStateInfo(); obj.insert("curcanvas", projectMgr.currentCanvasIndex()); obj.insert("canvascount", projectMgr.canvasCount()); obj.insert("parametercount", 0); if(projectMgr.canvasCount() > 0) { QWidget *pWidget = m_pStackedWidget->currentWidget(); Canvas *pCanvas = static_cast(pWidget); if(pCanvas) { obj["parametercount"] = pCanvas->parameterCount(); } } m_broadcast.write(obj); }