#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dialogappversion.h" #include "dialogconfig.h" #include "sysinfo.h" #include "textfinder.h" #include "textedit.h" #include "BootGlobal.h" #define ENTITY_COLUMN_NAME 0 #define ENTITY_COLUMN_STATUS 1 #define ENTITY_COLUMN_PID 2 #define ENTITY_COLUMN_VERSION 3 #define ENTITY_COLUMN_BOOTTIME 4 #define MAX_ENTITY_LIST_COLUMN 5 //Mapping to SpBase::FrameworkStateEnum #define FRAMEWORK_STATE_NOTINIT 0 #define FRAMEWORK_STATE_NOCONFIG 1 #define FRAMEWORK_STATE_BOOTING 2 #define FRAMEWORK_STATE_RUNNING 3 #define FRAMEWORK_STATE_SERVING 4 #define FRAMEWORK_STATE_BREAKDOWN 5 #define FRAMEWORK_STATE_REPAIRING 6 #define FRAMEWORK_STATE_UPGRADING 7 #define FRAMEWORK_STATE_ROOLLBACKING 8 #define FRAMEWORK_STATE_RECOVING 9 #define FRAMEWORK_STATE_NOTDISTURB 10 #define STARTUP_SCRIPT "spexplorer.sh" #ifdef DEVOPS_ON_ST /*DevOps流水线编译,ST环境*/ #define RVC_TITLE_STRING "RVC Terminal Application STver." #elif defined(DEVOPS_ON_UAT)/*DevOps流水线编译,UAT环境*/ #define RVC_TITLE_STRING "RVC Terminal Application UATver." #elif defined(DEVOPS_ON_PRD)/*DevOps流水线编译,PRD环境*/ #define RVC_TITLE_STRING "RVC Terminal Application" #elif defined(DEVOPS_ON_DEV)/*DevOps流水线编译,Dev环境*/ #define RVC_TITLE_STRING "RVC Terminal Application DEVver." #else/*本地编译等非DevOps环境编译的版本*/ #define RVC_TITLE_STRING "RVC Terminal Application TESTver." #endif void setRowBackground(const QBrush& brush, QAbstractItemModel* model, int row, const QModelIndex& parent = QModelIndex()) { if (!model || row < 0 || row >= model->rowCount(parent)) return; if (parent.isValid() && parent.model() != model) return; for (int i = 0; i < model->columnCount(parent); ++i) Q_ASSUME(model->setData(model->index(row, i, parent), brush, Qt::BackgroundRole)); } static QString EntityInfoHeaderString() { return QString("实体名称\t状态\t进程号\t版本\t启动时间\t文件句柄数"); } static QString EntityRunInfoToString(const EntityRunInfo& entity) { QString result = QString("%1\t%2\t%3\t%4\t%5\t%6") .arg(entity.entityName) .arg(MappingSatus2String(entity.state)) .arg(entity.pid) .arg(entity.version) .arg(entity.startupTimeStr) .arg(entity.fds); return result; } MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) , ui(new Ui::MainWindow), mSicon(nullptr), mSilent(false) , mIdleEntityCount(0), mTotalEntityCount(0), mFloatWidget(nullptr) { this->Init(RVC_TITLE_STRING); } MainWindow::MainWindow(QString systemInfo, int totalEntityCount, QWidget* parent) : QMainWindow(parent) , ui(new Ui::MainWindow), mSicon(nullptr), mSilent(false) , mIdleEntityCount(0), mTotalEntityCount(0), mFloatWidget(nullptr) { this->Init(systemInfo); } void MainWindow::Init(QString title) { ui->setupUi(this); setWindowIcon(QIcon(":/res/FavIcon.ico")); if (title.startsWith(RVC_TITLE_STRING)) { setWindowTitle(title); } else { setWindowTitle(QString(RVC_TITLE_STRING " [%1]").arg(title)); } QPropertyAnimation* animation = new QPropertyAnimation(this, "windowOpacity"); animation->setDuration(800); animation->setStartValue(0); animation->setEndValue(1); animation->start(); //QTextCodec* codec = QTextCodec::codecForName("GBK"); //QTextCodec::setCodecForLocale(codec); this->setMinimumSize(1068, 720); QDesktopWidget* desk = QApplication::desktop(); //const int curScreenIdx = desk->screenNumber(this); const int curScreenIdx = desk->primaryScreen(); QRect rect = desk->screenGeometry(curScreenIdx); const int wd = rect.width(); const int ht = rect.height(); this->move((wd - width()) / 2, (ht - height()) / 2); ui->splitter->setStretchFactor(0, 1); ui->splitter->setStretchFactor(1, 6); ui->splitter->setStretchFactor(2, 3); InitSystemTrayIcon(); InitEntitiesView(); #ifndef WITH_QT Test_EntityList(); Test_EventLog(); #endif QStringList selections; for (EntityState i = NoStart; i <= All;) { selections << MappingSatus2String(i); i = EntityState(i + 1); } ui->comboBoxStatus->addItems(selections); ui->comboBoxStatus->setCurrentIndex((int)All); connect(ui->comboBoxStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(DisplayEntities())); connect(ui->tableWidgetEntities->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(SortEntityItem(int))); InitMenuAction(); InitStatusBar(); connect(ui->pushButtonEntStart, SIGNAL(clicked()), this, SLOT(StartEntity())); connect(ui->pushButtonEntClose, SIGNAL(clicked()), this, SLOT(TerminateEntity())); connect(ui->pushButtonEntPause, SIGNAL(clicked()), this, SLOT(PauseEntity())); connect(ui->pushButtonEntContinue, SIGNAL(clicked()), this, SLOT(ContinueEntity())); connect(ui->pushButtonEntKill, SIGNAL(clicked()), this, SLOT(KillEntity())); connect(ui->pushButtonEntTest, SIGNAL(clicked()), this, SLOT(TestEntity())); connect(ui->pushButtonEntLogView, SIGNAL(clicked()), this, SLOT(LogView())); connect(ui->pushButtonClearRunCfg, SIGNAL(clicked()), this, SLOT(RemoveEntityRuninfoConfigFile())); SysInfo::instance().init(); QHBoxLayout* cpuLayout = new QHBoxLayout(); cpuLayout->setContentsMargins(0, 0, 0, 0); cpuLayout->setSpacing(0); cpuLayout->setMargin(0); ui->tab4CPU->setLayout(cpuLayout); ui->tab4CPU->layout()->addWidget(&mCpuWidget); QHBoxLayout* memoryLayout = new QHBoxLayout(); memoryLayout->setContentsMargins(0, 0, 0, 0); ui->tab4Memory->setLayout(memoryLayout); ui->tab4Memory->layout()->addWidget(&mMemoryWidget); mPerformWidge = new PerformWidget(this); QHBoxLayout* monitorLayout = new QHBoxLayout(); monitorLayout->setContentsMargins(0, 0, 0, 0); monitorLayout->addWidget(mPerformWidge); ui->tab4Monitor->setLayout(monitorLayout); #if 1//#ifdef WITH_QT QWidget* w = ui->splitterMain->widget(1); if (w != nullptr) { w->setParent(nullptr); w->deleteLater(); } #endif /* QStringList arguments = QApplication::arguments(); if (arguments.contains("--debug") || arguments.contains("-D")) { QTimer* tm = new QTimer(this); connect(tm, SIGNAL(timeout()), this, SLOT(RecordEntitySnapshot())); tm->start(3000); } */ //InitFloatWidget(); } QAction* MainWindow::CreateMenuAction(QString text, QKeySequence keyShot, QString toolTipText, void (MainWindow::* method)()) { QAction* action = new QAction(text, this); action->setShortcut(keyShot); //action->setStatusTip(toolTipText); //connect(clearAct, SIGNAL(triggered()), textViewer, SLOT(clear())); connect(action, &QAction::triggered, this, method); return action; } void MainWindow::ProcessStarted() { qDebug() << "process started! "; } void MainWindow::GetSubProcessMsg() { } void MainWindow::TriggerAdditionMenu(QAction* action) { qDebug() << "menu: " << action->text(); RvcAdditionAction* pAct = reinterpret_cast(action); switch (pAct->userData.type) { case BootEntity: { StartEntityFromCustom(pAct->userData.entityName, pAct->userData.cmdLine); } break; case RunShellScript: break; case CreatesSubProcess: default: { QProcess* process = new QProcess(this); //connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(GetSubProcessMsg())); //connect(process, SIGNAL(started()), this, SLOT(ProcessStarted())); QString appDir = QCoreApplication::applicationDirPath(); #ifdef Q_WS_WIN32 if (appDir.endsWith("\\bin")) { appDir = appDir.left(appDir.length() - QString("\\bin").length()); process->setWorkingDirectory(appDir); } #else if (appDir.endsWith("/bin")) { appDir = appDir.left(appDir.length() - QString("/bin").length()); process->setWorkingDirectory(appDir); } #endif process->setStandardOutputFile(QProcess::nullDevice()); process->setStandardErrorFile(QProcess::nullDevice()); qDebug() << "start process: " << pAct->userData.cmdLine; process->startDetached(pAct->userData.cmdLine); //process->waitForFinished(1000); delete process; } break; } } void MainWindow::InitMenuAction() { QMenu* mainMenu = menuBar()->addMenu(QString::fromUtf8("菜单(&M)")); //mainMenu->addAction(CreateMenuAction(QString::fromUtf8("初始化(&I)"), tr("Alt+I"), QString::fromUtf8("初始化终端") // , &MainWindow::InitializeTerminal)); mainMenu->addAction(CreateMenuAction(QString::fromUtf8("重启当前版本(&T)"), tr("Alt+T"), QString::fromUtf8("重启可视柜台终端应用") , &MainWindow::RestartApp)); mainMenu->addAction(CreateMenuAction(QString::fromUtf8("重启应用(&R)"), tr("Alt+R"), QString::fromUtf8("通过读取 active.txt 重启可视柜台终端应用") , &MainWindow::RestartAppThroughSpShell)); QMenu* sysConfigMenu = mainMenu->addMenu(QString::fromUtf8("关机")); sysConfigMenu->addAction(CreateMenuAction(QString::fromUtf8("重启(&P)"), tr("Alt+P"), QString::fromUtf8("重启操作系统") , &MainWindow::RestartSystem)); sysConfigMenu->addAction(CreateMenuAction(QString::fromUtf8("关机(&D)"), tr("Alt+D"), QString::fromUtf8("关闭计算机") , &MainWindow::ShutdownSystem)); mainMenu->addAction(CreateMenuAction(QString::fromUtf8("退出应用(&Q)"), tr("Alt+Q"), QString::fromUtf8("退出可视柜台终端应用") , &MainWindow::QuitApp)); QMenu* configMenu = menuBar()->addMenu(QString::fromUtf8("配置(&C)")); configMenu->addAction(CreateMenuAction(QString::fromUtf8("加载控件(&L)"), tr("Alt+L"), QString::fromUtf8("动态加载控件") , &MainWindow::LoadCustomPlguins)); QMenu* toolMenu = menuBar()->addMenu(QString::fromUtf8("工具(&T)")); toolMenu->addAction(CreateMenuAction(QString::fromUtf8("选项(&O)"), tr("Alt+O"), QString::fromUtf8("相关选项设置") , &MainWindow::ConfigApp)); toolMenu->addAction(CreateMenuAction(QString::fromUtf8("导出快照(&S)"), tr("Alt+S"), QString::fromUtf8("导出实体即时信息快照") , &MainWindow::ExportEntitySnapshot)); QMenu* addMenu = menuBar()->addMenu(QString::fromUtf8("附加(&A)")); const QString configFileName = getFrameworkConfigPath(); qDebug() << "config file name: " << configFileName; QFileInfo fileInfo(configFileName); if (fileInfo.exists()) { RvcSettings* settings = new RvcSettings(configFileName, QSettings::IniFormat); settings->setIniCodec("UTF-8"); int menuCount = settings->GetConfigData("Menu", "Count").toInt(); qDebug() << "menu count: " << menuCount; int validIdx = 1; for (int i = 1; i <= menuCount; ++i) { QString strIdx = QString::number(i); QString subMenuName = settings->GetConfigData("Menu", strIdx).toString(); QString textName = settings->GetConfigData(subMenuName, "TextName").toString(); const int exeType = settings->GetConfigData(subMenuName, "Type").toInt(); const auto excuteEnum = static_cast(exeType); QString cmdLine = settings->GetConfigData(subMenuName, "CmdLine").toString(); if (cmdLine.isNull() || cmdLine.isEmpty()) { continue; } QString strQuick = QString("Alt+%1").arg(validIdx++); qDebug() << subMenuName << " " << textName << " " << strIdx << " " << cmdLine << " " << strQuick; QString menuName = (!textName.isNull() && !textName.isEmpty()) ? textName : cmdLine; RvcAdditionAction* action = new RvcAdditionAction(menuName, this); action->setShortcut(strQuick); //action->setStatusTip(cmdLine); action->userData.type = excuteEnum; cmdLine = cmdLine.trimmed(); if (excuteEnum == BootEntity && -1 != cmdLine.indexOf('\t')) { const int idx = cmdLine.indexOf('\t'); QStringList params = cmdLine.split("\t"); action->userData.entityName = params.at(0); action->userData.cmdLine = cmdLine.mid(idx + 1); } else if (excuteEnum == BootEntity) { action->userData.entityName = cmdLine; action->userData.cmdLine = ""; } else { action->userData.cmdLine = cmdLine; } addMenu->addAction(action); } if (menuCount > 0) { connect(addMenu, SIGNAL(triggered(QAction*)), this, SLOT(TriggerAdditionMenu(QAction*))); } } QMenu* helpMenu = menuBar()->addMenu(QString::fromUtf8("帮助(&H)")); helpMenu->addAction(CreateMenuAction(QString::fromUtf8("关于应用(&A)"), tr("Alt+A"), QString::fromUtf8("可视柜台终端应用版本更新记录") , &MainWindow::VersionView)); helpMenu->addAction(CreateMenuAction(QString::fromUtf8("错误码对照表(&A)"), tr("Alt+E"), QString::fromUtf8("ErrorCode错误码对照表") , &MainWindow::ErrorCodeView)); } void MainWindow::ConfigApp() { qDebug() << "Enter ConfigApp" << endl; #ifdef WITH_QT std::string path = CSpShellConsole::GetRootConfigPath(); DialogInParam param; param.rootIniPath = path.c_str(); DialogConfig dial(¶m, this); #else DialogInParam param; param.rootIniPath = "D:\\Run\\hardwarecfg\\root.ini"; DialogConfig dial(¶m, this); #endif dial.exec(); } void MainWindow::QuitApp() { qDebug() << "Enter QuitApp" << endl; #ifdef WITH_QT qApp->exit(APP_EXIT_CODE_QUIT); //or exit #else exit(APP_EXIT_CODE_QUIT); #endif qDebug() << "Leave QuitApp" << endl; } static void ClearArguments(const QString& program, QStringList& arguments) { if (arguments.contains(program)) { arguments.removeOne(program); } if (arguments.contains("--restart")) { arguments.removeOne("--restart"); } if (arguments.contains("-R")) { arguments.removeOne("-R"); } if (!arguments.contains("-Rwait")) { arguments.append("-Rwait"); } } void MainWindow::RestartApp() { qDebug() << "Enter RestartApp" << endl; qint64 nextProcID(0); QString program = QApplication::applicationFilePath(); QStringList arguments = QApplication::arguments(); QString workingDirectory = QDir::currentPath(); ClearArguments(program, arguments); qDebug() << "Program: " << program << " " << arguments << " " << workingDirectory << endl; bool result = QProcess::startDetached(program, arguments, workingDirectory, &nextProcID); qDebug() << "Program result: " << result << " " << nextProcID; QApplication::exit(APP_EXIT_CODE_RESTART_CURR); } void MainWindow::RestartSystem() { QString str = "确定要重启系统吗?"; QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (rb == QMessageBox::Yes) { QProcess::startDetached("sudo shutdown -r now"); } } void MainWindow::ShutdownSystem() { QString str = "确定要关机吗?"; QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (rb == QMessageBox::Yes) { QProcess::startDetached("sudo shutdown --poweroff now"); } } /** 该接口暂且放弃使用,因为使用QT创建子进程会继承文件句柄,改用 RestartAppThroughSpShell 与框架重启公用一套接口*/ void MainWindow::RestartAppThroughActive() { qDebug() << "Enter " << __FUNCTION__ << endl; qint64 nextProcID(0); QString program = QApplication::applicationFilePath(); QStringList arguments = QApplication::arguments(); QString workingDirectory = QDir::currentPath(); QString newProgrm = program; QString newWorkingDirectory = workingDirectory; QDir versionDir = QDir::current(); versionDir.cdUp(); #if 0 QString activeFilePath = versionDir.filePath("active.txt"); QFile activeFile(activeFilePath); if (!activeFile.exists()) { QMessageBox::critical(this, "错误", QString("文件 %1 不存在!").arg(activeFilePath)); return; } if (!activeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::critical(this, "错误", QString("打开文件 %1 失败:%2").arg(activeFilePath).arg(activeFile.errorString())); return; } QByteArray versionContent = activeFile.readAll(); versionContent = versionContent.trimmed(); activeFile.close(); if (versionContent.isEmpty() || versionContent.isNull()) { QMessageBox::critical(this, "错误", QString("文件 %1 内容为空!").arg(activeFilePath)); return; } QStringList programPaths = program.split("/"); QString curVersion = programPaths[programPaths.size() - 3]; if (curVersion == QString(versionContent)) { qDebug() << "Detect is the same version: " << (QString)versionContent; } else { qDebug() << "Detect diff version, from " << curVersion << " to " << (QString)versionContent; programPaths.replace(programPaths.size() - 3/*x.y.z/bin/spshell*/, versionContent); newProgrm = programPaths.join("/"); QStringList workingPaths = workingDirectory.split("/"); workingPaths.replace(workingPaths.size() - 1/*/x.y.z*/, versionContent); newWorkingDirectory = workingPaths.join("/"); } #else QString scriptFilePath = versionDir.filePath(STARTUP_SCRIPT); QFile scriptFile(scriptFilePath); if (!scriptFile.exists()) { QMessageBox::critical(this, "错误", QString("启动脚本 %1 不存在!").arg(scriptFilePath)); return; } auto permitt = scriptFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner | QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ExeUser | QFileDevice::ReadGroup | QFileDevice::ReadOther | QFileDevice::ExeGroup | QFileDevice::ExeOther); if (!permitt) { QMessageBox::critical(this, "错误", QString("设置 %1 文件权限失败:%2!").arg(scriptFilePath).arg(scriptFile.errorString())); return; } newProgrm = scriptFilePath; newWorkingDirectory = versionDir.currentPath(); #endif ClearArguments(program, arguments); qunsetenv("LD_LIBRARY_PATH"); qDebug() << "newProgrm: " << newProgrm << " " << arguments << " " << newWorkingDirectory << endl; bool result = QProcess::startDetached(newProgrm, arguments, newWorkingDirectory, &nextProcID); qDebug() << "Program result: " << result << " " << nextProcID; QApplication::exit(); } void MainWindow::RestartAppThroughSpShell() { qDebug() << "Enter " << __FUNCTION__ << endl; qint64 nextProcID(0); QString program = QApplication::applicationFilePath(); QStringList arguments = QApplication::arguments(); QString workingDirectory = QDir::currentPath(); QString newProgrm = program; QString newWorkingDirectory = workingDirectory; QDir versionDir = QDir::current(); versionDir.cdUp(); QString scriptFilePath = versionDir.filePath(STARTUP_SCRIPT); QFile scriptFile(scriptFilePath); if (!scriptFile.exists()) { QMessageBox::critical(this, "错误", QString("启动脚本 %1 不存在!").arg(scriptFilePath)); return; } auto permitt = scriptFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner | QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ExeUser | QFileDevice::ReadGroup | QFileDevice::ReadOther | QFileDevice::ExeGroup | QFileDevice::ExeOther); if (!permitt) { QMessageBox::critical(this, "错误", QString("设置 %1 文件权限失败:%2!").arg(scriptFilePath).arg(scriptFile.errorString())); return; } #ifdef WITH_QT int result = CSpShellConsole::RestartApplication(); if (result != 0) { QMessageBox::critical(this, "错误", QString("执行重启请求失败!")); return; } #endif QApplication::exit(APP_EXIT_CODE_RESTART_ACTIVE); } void MainWindow::InitializeTerminal() { LogView(); } void MainWindow::LogView() { qDebug() << "Enter LogView" << endl; auto enti = GetCurrentSelectedEntity(); #ifdef WITH_QT if (!enti.entityName.isEmpty()) { std::string path = CSpShellConsole::GetEntityLogPath(Q2Str(enti.entityName).c_str()); TextFinder textFinder(Str2Q(path), enti.entityName, this); textFinder.exec(); } #endif } void MainWindow::ErrorCodeView() { qDebug() << "Enter ErrorCodeView" << endl; #if 1 DialogAppVersion dial(QLatin1String(":/res/sys_errcode.html"), ("系统错误码对照表"), this); dial.exec(); #else TextEdit mw; QDesktopWidget* desk = QApplication::desktop(); const int curScreenIdx = desk->primaryScreen(); QRect rect = desk->screenGeometry(curScreenIdx); const int wd = rect.width(); const int ht = rect.height(); mw.resize(wd / 2, (ht * 2) / 3); mw.move((wd - mw.width()) / 2, (ht - mw.height()) / 2); mw.setContents(QLatin1String(":/res/sys_errcode.html")); mw.show(); #endif //TextEdit textEdit(this); //textEdit.setContents(":/res/sys_errcode.html"); //textEdit.show(); } void MainWindow::RemoveEntityRuninfoConfigFile() { auto enti = GetCurrentSelectedEntity(); #ifdef WITH_QT if (!enti.entityName.isEmpty()) { std::string path = CSpShellConsole::GetEntityRTPath(Q2Str(enti.entityName).c_str()); if (!path.empty()) { QFile file(path.c_str()); if (file.exists()) { QString str = QString("确定要删除 %1 实体运行时文件?").arg(enti.entityName); QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (rb == QMessageBox::Yes) { if (QFile::remove(path.c_str())) { QMessageBox::information(this, "提示", "删除成功!请重启应用或实体以立即生效!"); } else { QMessageBox::warning(this, "错误", QString("%1: 删除运行时文件 %2 失败!") .arg(enti.entityName).arg(path.c_str())); } } } else { QMessageBox::warning(this, "提示", QString("%1: %2 运行时文件不存在!").arg(enti.entityName).arg(path.c_str())); } } else { QMessageBox::critical(this, "错误", QString("%1: 获取运行时文件路径失败!").arg(enti.entityName)); } } else { QMessageBox::critical(this, "错误", "无法获取实体名称,请选中实体列表所在行!"); } #endif } void MainWindow::VersionView() { qDebug() << "Enter VersionView" << endl; DialogAppVersion dial(QLatin1String(":/res/version_history.html"), ("关于可视柜台终端应用程序"), this); dial.exec(); } void MainWindow::DisplayEntities() { EntityState filterState = EntityState(ui->comboBoxStatus->currentIndex()); QString str = MappingSatus2String(filterState); if (filterState == All) str = ""; auto entities = ui->tableWidgetEntities->findItems(str, Qt::MatchExactly); const int rows = ui->tableWidgetEntities->rowCount(); qDebug() << "Enter DisplayEntities " << str << " " << rows << "!" << endl; for (int i = 0; i < rows; ++i) { const auto strStatus = ui->tableWidgetEntities->item(i, ENTITY_COLUMN_STATUS)->text(); ui->tableWidgetEntities->setRowHidden(i, !str.isEmpty() && strStatus.compare(str) != 0); } } void MainWindow::ResetAllEntityOperateBtnState(bool enable) { ui->pushButtonEntStart->setEnabled(enable); ui->pushButtonEntClose->setEnabled(enable); ui->pushButtonEntPause->setEnabled(enable); ui->pushButtonEntContinue->setEnabled(enable); ui->pushButtonEntKill->setEnabled(enable); ui->pushButtonEntTest->setEnabled(enable); } void MainWindow::StartEntityFromCustom(const QString& entityName, const QString& cmdLine) { qDebug() << "Enter StartEntityFromCustom " << entityName << " " << cmdLine << "!" << endl; const int entityRow = FindEntityRowIndex(entityName); EntityInfo entityInfo = GetEntityInfoByRowIndex(entityRow); if (entityInfo.IsValid()) { const auto curState = entityInfo.state; if (curState != NoStart && curState != Killed && curState != Close) { QString str = QString("%1 实体目前处于运行状态,是否要强制重启?").arg(entityName); QMessageBox::StandardButton rb = QMessageBox::question(this, "确认", str, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); if (rb == QMessageBox::Yes) { const int result = DealWithEntity(entityInfo, Deal_Kill, "", false); if (result != 0) { QMessageBox::critical(this, "错误", QString("终止旧实体例程 %1 失败!").arg(entityInfo.entityName)); return; } } else { return; } } } Threadee* nE = new Threadee(); nE->dealType = Deal_Start; nE->entityName = entityName; nE->cmdLine = cmdLine; OperatThread* ot = new OperatThread(nE, nullptr); connect(ot, &QThread::finished, ot, &QObject::deleteLater); connect(ot, &OperatThread::OperateResult, this, &MainWindow::ReceiveCustomOperatResult); ot->start(); } void MainWindow::UpdateEntityOperateBtnState(EntityState currState) { switch (currState) { case Idle: ResetAllEntityOperateBtnState(); ui->pushButtonEntStart->setEnabled(false); ui->pushButtonEntContinue->setEnabled(false); break; case NoStart: ResetAllEntityOperateBtnState(false); ui->pushButtonEntStart->setEnabled(true); break; case Starting: ResetAllEntityOperateBtnState(false); ui->pushButtonEntKill->setEnabled(true); break; case Busy: ResetAllEntityOperateBtnState(false); ui->pushButtonEntKill->setEnabled(true); break; case Pause: ResetAllEntityOperateBtnState(false); ui->pushButtonEntContinue->setEnabled(true); ui->pushButtonEntKill->setEnabled(true); break; case UnLoading: ResetAllEntityOperateBtnState(false); break; case Lost: ResetAllEntityOperateBtnState(false); ui->pushButtonEntKill->setEnabled(true); break; case Close: case Killed: ResetAllEntityOperateBtnState(false); ui->pushButtonEntStart->setEnabled(true); break; case Passed: case Failed: ResetAllEntityOperateBtnState(); ui->pushButtonEntStart->setEnabled(false); ui->pushButtonEntContinue->setEnabled(false); break; default: ResetAllEntityOperateBtnState(false); } } void MainWindow::EntitySelectionChanged() { const QTableWidgetItem* currentItem = ui->tableWidgetEntities->currentItem(); qDebug() << QString("Enter EntitySelectionChanged: ") << currentItem->text(); //ShowMessage(currentItem->text(), 0); UpdateEntityOperateBtnState(GetCurrentSelectedEntity().state); } void MainWindow::SortEntityItem(int n) { static bool sortStatus[MAX_ENTITY_LIST_COLUMN] = { false }; ui->tableWidgetEntities->sortItems(n, (sortStatus[n] ? Qt::AscendingOrder : Qt::DescendingOrder)); sortStatus[n] = !sortStatus[n]; } QTableWidgetItem* MainWindow::FindEnityWidgetItem(QString entityName) { auto entities = ui->tableWidgetEntities->findItems(entityName, Qt::MatchExactly); if (entities.count() > 0) return entities[0]; return nullptr; } int MainWindow::FindEntityRowIndex(QString entityName) { int result = -1; auto item = FindEnityWidgetItem(entityName); if (item) result = item->row(); return result; } void MainWindow::RemindEntityStateChangeWith(QString entityName, bool bEnd) { const int row = FindEntityRowIndex(entityName); if (row >= 0) { qDebug() << entityName << " " << bEnd << endl; if (bEnd) UpdateItemBackgroundColor(row, MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text())); else UpdateItemBackgroundColor(row, Idle); } } void MainWindow::RemindEntityStateChange(int row, EntityState previousState, EntityState currState) { UpdateItemBackgroundColor(row, currState); #ifndef NDEBUG if (currState == Lost) { QString info("Entity "); QString entity(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text()); info.append(entity); info += " 's State from "; info += MappingSatus2String(previousState); info += " to "; info += MappingSatus2String(currState); Note(info, EntityFire, entity, true); } #endif //NDEBUG (new RichTimer(this, ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text())); } void MainWindow::TriggerEntityState(int row, EntityState state, int pid, bool filcker) { const EntityState previousState = MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()); if (pid == -1/*for entity reset*/ && (previousState != Passed && previousState != Failed)) { return; } ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->setText(MappingSatus2String(state)); if (state == Close || state == NoStart) { ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->setText("0"); } else if (pid > 0) { ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->setText(QString::number(pid)); } if ((state == Idle) && (previousState == NoStart || previousState == Starting || previousState == UnLoading || previousState == Lost || previousState == Close || previousState == Killed )) { QDateTime currentTime = QDateTime::currentDateTime(); QString currentTimeStr = currentTime.toString("MM-dd-hh:mm:ss.zzz"); ui->tableWidgetEntities->item(row, ENTITY_COLUMN_BOOTTIME)->setText(currentTimeStr); } if (state != previousState) { if (state == Idle) { mIdleEntityCount++; } else if (previousState == Idle) { mIdleEntityCount--; } UpdateEntityStatistics(); } if (filcker) { RemindEntityStateChange(row, previousState, state); ui->tableWidgetEntities->setCurrentItem(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)); qDebug() << "emit entity select change." << endl; emit ui->tableWidgetEntities->itemSelectionChanged(); } else { RemindEntityStateChangeWith(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text(), true); } } int MainWindow::TriggerEntityState(QTableWidgetItem* item, EntityState state, int pid, bool flicker) { if (!item) return -1; TriggerEntityState(item->row(), state, pid, flicker); return 0; } int MainWindow::TriggerEntityState(QString entityName, EntityState state, int pid, bool flicker) { const int row = FindEntityRowIndex(entityName); if (row >= 0) { TriggerEntityState(row, state, pid, flicker); } return 0; } int MainWindow::DealWithEntity(const EntityInfo& entity, DealType dealType, QString extendParam, bool multiThread) { qDebug() << "Deal with entity: " << entity.entityName << " with " << QString::number(dealType) << endl; int result = -1; if (!entity.entityName.isEmpty()) { Threadee* nE = new Threadee(); nE->dealType = dealType; nE->entityName = entity.entityName; nE->cmdLine = extendParam; OperatThread* ot = new OperatThread(nE, nullptr); if (multiThread) { if (dealType == Deal_Test) { connect(ot, &OperatThread::OperateResult, this, &MainWindow::ReceiveOperatResult); } connect(ot, &QThread::finished, ot, &QObject::deleteLater); ot->start(); result = -1 /*forbid changing entity state at screen*/; } else { bool ret = ot->doSomething(); result = ret ? 0 : -1; } } return result; } void MainWindow::StartEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Start); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Idle, 8888); } } void MainWindow::PauseEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Pause); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Pause); } } void MainWindow::ContinueEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Continue); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Idle); } } void MainWindow::TerminateEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Close); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Close); } } void MainWindow::KillEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Kill); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Killed); } } void MainWindow::TestEntity() { int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Test); if (optResult == 0) { TriggerEntityState(GetCurrentSelectedEntity().entityName, Passed); } } QString MainWindow::GetPerfStorePath() { #ifdef WITH_QT std::string path = CSpShellConsole::GetTempPath(); #else std::string path = "C:\\rvc\\temp"; #endif if (!path.empty()) { QDir tempDir(path.c_str()); tempDir.mkpath(QString("perf")); if (tempDir.cd("perf")) { return tempDir.absolutePath(); } else { qDebug() << "cd " << tempDir.path() << " failed"; return QString(path.c_str()); } } } QStringList MainWindow::ExecuteShellScripts(QString shellCmd) { QStringList results; QProcess* subScriptsProcess = new QProcess(this); subScriptsProcess->setProcessChannelMode(QProcess::MergedChannels); subScriptsProcess->start("sh", QStringList() << "-c" << shellCmd); subScriptsProcess->waitForFinished(); QString str(subScriptsProcess->readAllStandardOutput()); results << str; results << QString::number(subScriptsProcess->exitCode()); QMessageBox::warning(this, "Run ShellScripts Info", results.join("\t"), QMessageBox::Ok); delete subScriptsProcess; return QStringList() << str; } void MainWindow::RecordEntitySnapshot() { qDebug() << "Enter " << __FUNCTION__; #if 0 QPixmap p = mPerformWidge->grab(); QString filePathName = GetPerfStorePath(); filePathName += "/EntityPerf_"; filePathName += QDateTime::currentDateTime().toString("yyyyMMdd-hhmmsszzz"); filePathName += ".png"; if (!p.save(filePathName, "png")) { qDebug() << "save widget screen failed"; } #endif ExportEntityInfo(false); } void MainWindow::ExportEntityInfo(bool fromBtnClick) { QTableWidget* table = ui->tableWidgetEntities; QString fileName; if (fromBtnClick) { fileName = QFileDialog::getSaveFileName(table, "保存" , QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) , "文本文件(*.txt)"); } else { QDir tempDir(GetPerfStorePath()); QDateTime currTime = QDateTime::currentDateTime(); QString currTimeString = currTime.toString("yyyyMMdd"); QString filePureName = currTimeString + "_EntityInfo.txt"; fileName = tempDir.filePath(filePureName); qDebug() << "entity info file path: " << fileName; } QFile file(fileName); if (!file.open(fromBtnClick ? (QIODevice::ReadWrite | QIODevice::Text) : (QIODevice::ReadWrite | QIODevice::Append))) { if (fromBtnClick) QMessageBox::warning(this, tr("错误"), tr("打开文件失败,数据保存失败!")); else qDebug() << "打开文件失败,数据保存失败! " << file.errorString(); return; } if (!file.isReadable()) { if (fromBtnClick) QMessageBox::warning(this, tr("错误"), tr("该文件不可读,数据保存失败!")); else qDebug() << "该文件不可读,数据保存失败! " << file.errorString(); } else { QTextStream out(&file); // const int colCounts = table->columnCount(); const int rowCounts = table->rowCount(); for (int i = 0; i < rowCounts; ++i) { const EntityInfo entityInfo = GetEntityInfoByRowIndex(i); EntityRunInfo entityRunInfo(entityInfo); entityRunInfo.startupTimeStr = ui->tableWidgetEntities->item(i, ENTITY_COLUMN_BOOTTIME)->text(); entityRunInfo.fds = PerformWidget::GetProcessFds(entityRunInfo.pid); if (i == 0) { QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz"); QString timestamp = QString("\n\nRecord at: %1\n").arg(currentTime); file.write(timestamp.toUtf8()); QString header = EntityInfoHeaderString(); file.write(header.toUtf8()); } QString str = "\n"; str += EntityRunInfoToString(entityRunInfo); file.write(str.toUtf8()); } if (fromBtnClick) QMessageBox::warning(this, tr("信息"), tr("实体信息保存成功!")); else qDebug() << "实体信息保存成功!"; } file.close(); } void MainWindow::ExportEntitySnapshot() { ExportEntityInfo(true); } void MainWindow::Test_EventLog() { { for (int i = 0; i < 100; ++i) { QString str = QString(("我是第%1串字符串字符串字符串字-------符串字符串" "字符串字-------符串字符串字串字-------符符串字符" "串字符串串字-------符字串字符字串字符字串字符字串" "字符字串字符字串字-------符符串字串字-------符符" "串字符串字串字-------符符串字符串字符串")).arg(i); QtMessageInfo info{ (MessageType)(int)(i % int(MsgTypeMax)) , str,0, 0 }; InsertConsole(info); } } } EntityInfo MainWindow::GetEntityInfoByRowIndex(int row) { if (row == -1) return (EntityInfo{ "", Manual, NoStart, 0, "" }); return EntityInfo{ ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text(), MappingString2StartType(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()), MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()), ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->text().toInt(), ui->tableWidgetEntities->item(row, ENTITY_COLUMN_VERSION)->text() }; } EntityInfo MainWindow::GetCurrentSelectedEntity() { const QTableWidgetItem* currentItem = ui->tableWidgetEntities->currentItem(); if (currentItem) { auto item = GetEntityInfoByRowIndex(currentItem->row()); return item; } return GetEntityInfoByRowIndex(-1); } void MainWindow::AddEntityEntry(const EntityInfo& entityInst) { const int currCows = ui->tableWidgetEntities->rowCount(); ui->tableWidgetEntities->insertRow(currCows); ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_NAME, new QTableWidgetItem(entityInst.entityName)); //ui->tableWidgetEntities->setItem(currCows, 1, new QTableWidgetItem(MappingStartType2String(entityInst.startType))); ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_STATUS, new QTableWidgetItem(MappingSatus2String(entityInst.state))); ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_PID, new QTableWidgetItem(QString::number(entityInst.pid))); ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_VERSION, new QTableWidgetItem(entityInst.version)); if (entityInst.state == Starting || entityInst.state == Idle) { QDateTime currentTime = QDateTime::currentDateTime(); QString currentTimeStr = currentTime.toString("MM-dd-hh:mm:ss.zzz"); ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_BOOTTIME, new QTableWidgetItem(currentTimeStr)); } else { ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_BOOTTIME, new QTableWidgetItem("未知")); } mTotalEntityCount++; if (entityInst.state == Idle) mIdleEntityCount++; UpdateEntityStatistics(); UpdateItemBackgroundColor(currCows, entityInst.state); } void MainWindow::UpdateItemBackgroundColor(int row, EntityState state) { const int columnCount = ui->tableWidgetEntities->columnCount(); auto curColor = MappingStatus2Color(state); qDebug() << "uptate row background color" << endl; #if 0 for (int col = 0; col < columnCount; ++col) { QTableWidgetItem* item = ui->tableWidgetEntities->item(row, col); item->setBackground(QBrush(curColor)); //QPalette palette = item->palette(); //palette.setBrush(QPalette::Base, curColor); //item->setPalette(palette); } #else setRowBackground(QBrush(curColor), ui->tableWidgetEntities->model(), row); #endif } void MainWindow::Test_EntityList() { AddEntityEntry(EntityInfo{ "MobileDial", Manual, Idle, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "IEBrowser", Manual, NoStart, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "Browser", Manual, Lost, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "HelloClient", Manual, Starting, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "HelloService", Manual, Busy, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "PortbleScanner", Manual, Pause, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "HealthManager", Manual, UnLoading, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "MediaController", Manual, Close, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "GPIO", Manual, Killed, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "CardIssuer", Manual, Passed, 123, "V1.2.3" }); AddEntityEntry(EntityInfo{ "DeviceSwitch", Manual, Failed, 123, "V1.2.3" }); if (-1 != FindEntityRowIndex("NoExist")) { QMessageBox::warning(this, "", "NoExist", QMessageBox::Ok); } if (1 == FindEntityRowIndex("MobileDial")) { QMessageBox::warning(this, "", "NoExist", QMessageBox::Ok); } } bool MainWindow::LoadPlguins() { return false; } void MainWindow::LoadCustomPlguins() { #ifndef WITH_QT static bool sw = false; if (!sw) { this->setWindowState(Qt::WindowMinimized); } else { this->setWindowState((this->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); } sw = !sw; #else bool result = LoadPlguins(); if (result) { } #endif } void MainWindow::EntityItemContextMenu(QPoint pos) { auto index = ui->tableWidgetEntities->indexAt(pos); if (index.isValid()) { mEntityPopMenu->exec(QCursor::pos()); // 菜单出现的位置为当前鼠标的位置 } } void MainWindow::InitEntitiesView() { ui->labelEntCalculate->setText(""); ui->tableWidgetEntities->setColumnCount(MAX_ENTITY_LIST_COLUMN); QStringList header; header << "名称" << "状态" << "进程号" << "版本" << "最近启动时间"; ui->tableWidgetEntities->setHorizontalHeaderLabels(header); ui->tableWidgetEntities->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->tableWidgetEntities->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->tableWidgetEntities->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tableWidgetEntities->setSelectionMode(QAbstractItemView::SingleSelection); //ui->tableWidgetEntities->setSelectionModel(mEntitySelectedModel); ui->tableWidgetEntities->verticalHeader()->hide(); ui->tableWidgetEntities->resizeColumnToContents(1); ui->tableWidgetEntities->horizontalHeader()->setStretchLastSection(true); ui->tableWidgetEntities->horizontalHeader()->setVisible(true); ui->tableWidgetEntities->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter); ui->tableWidgetEntities->setStyleSheet("selection-background-color:#1E90FF;"); connect(ui->tableWidgetEntities, SIGNAL(itemSelectionChanged()), this, SLOT(EntitySelectionChanged())); /* ui->tableWidgetEntities->setContextMenuPolicy(Qt::CustomContextMenu); mEntityPopMenu = new QMenu(ui->tableWidgetEntities); QAction *actionUpdateInfo = new QAction(); QAction *actionDelInfo = new QAction(); actionUpdateInfo ->setText(QString("修改")); actionDelInfo ->setText(QString("删除")); mEntityPopMenu->addAction(actionUpdateInfo); mEntityPopMenu->addAction(actionDelInfo); connect(ui->tableWidgetEntities, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(EntityItemContextMenu(QPoint))); */ mEntityStateChangeReminder = new QTimer(this); mEntityStateChangeReminder->setSingleShot(true); //connect(mEntityStateChangeReminder, SIGNAL(timeout()),this, SLOT(RemindEntityStateChange())); } void MainWindow::InitStatusBar() { mToolsTip = new QLabel("", this); QFont ft; ft.setPointSize(10); mToolsTip->setFont(ft); QPalette pa; pa.setColor(QPalette::WindowText, QColor(105, 105, 105)); mToolsTip->setPalette(pa); mToolsTip->setStyleSheet("QLabel {padding: 0px 1px 2px 2px;}"); statusBar()->addPermanentWidget(mToolsTip); TimeDateTimer* timer = new TimeDateTimer(this); timer->Start(1000); //mStatusLabel = new MLabel(this); //mStatusLabel->setStyleSheet("QLabel {padding: -10px 2px 2px 1px;}"); //statusBar()->addWidget(mStatusLabel); } void MainWindow::TimeUpdate(const QString& timeStr) { //qDebug() << "enter TimeUpdate" << endl; mToolsTip->setText(timeStr); } void MainWindow::ShowStatusMessage(QString message, int messageType) { Q_UNUSED(messageType); //statusBar()->setStyleSheet("color:green"); QFontMetrics fontMetrics(statusBar()->font()); int fontSize = fontMetrics.width(message); if (fontSize > statusBar()->width()) { message = fontMetrics.elidedText(message, Qt::ElideRight, statusBar()->width()); } statusBar()->showMessage(message); //mStatusLabel->setText(message); } void MainWindow::OnTrayIconActivated(QSystemTrayIcon::ActivationReason activeRson) { switch (activeRson) { // 单击托盘显示窗口 case QSystemTrayIcon::Trigger: { showNormal(); raise(); activateWindow(); break; } // 双击 case QSystemTrayIcon::DoubleClick: { // ... break; } default: break; } } void MainWindow::messageClicked() { #ifndef WITH_QT QMessageBox::information(nullptr, tr("Systray"), tr("Sorry, I already gave what help I could.\n" "Maybe you should try asking a human?")); #endif } void MainWindow::InitSystemTrayIcon() { if (QSystemTrayIcon::supportsMessages() && mSicon == nullptr) { mSicon = new QSystemTrayIcon(this); QMenu* menusystemTray = new QMenu(this); menusystemTray->addAction(tr("Show/Hide")); menusystemTray->addAction(tr("About")); menusystemTray->addAction(tr("Quit")); mSicon->setIcon(QIcon(":/res/FavIcon.ico")); mSicon->setToolTip(QString::fromUtf8("RVC Terminal Manager")); mSicon->setContextMenu(menusystemTray); connect(mSicon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnTrayIconActivated(QSystemTrayIcon::ActivationReason))); connect(mSicon, &QSystemTrayIcon::messageClicked, this, &MainWindow::messageClicked); mSicon->show(); } } void MainWindow::Note(QString info, NoteSrcType srcType, QString srcEntity, bool bForce) { qDebug() << "Note: " << srcEntity << " " << info << endl; #ifdef WITH_QT if (mSicon && (bForce || CanDisturb())) { if (srcEntity.isEmpty()) srcEntity = RVC_TITLE_STRING; int showDelayTime = 10000; if (srcType == BootStage) { showDelayTime = 15000; } QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Critical); mSicon->showMessage(srcEntity, info, msgIcon, showDelayTime); } #endif } void MainWindow::closeEvent(QCloseEvent* event) { showMinimized(); event->ignore(); } namespace { QString CoverWithTimePrefix(QString content) { QDateTime time = QDateTime::currentDateTime(); QString buffer = time.toString("[hh:mm:ss]"); QString result = QString("%1 %2").arg(buffer).arg(content); return result; } } void MainWindow::ReceiveMessage(const QtMessageInfo* message) { if (!InsertConsole(*message)) { QBaseListWidgetItem* item = new QConsoleListWidgetItem(CoverWithTimePrefix(message->content)); item->AppentToWidget(ui->listWidgetEventLog); } } void MainWindow::ReceiveEntityVariant(QVariant info) { QEntityActiveInfo entityInfo = info.value(); int localEntityIndex = -1; for (int i = 0; i < mBootEntitiesInfo.size(); ++i) { if (mBootEntitiesInfo.at(i).entityName == entityInfo.entityName) { localEntityIndex = i; break; } } if (localEntityIndex != -1) { if (mBootEntitiesInfo[localEntityIndex].entityState != entityInfo.entityState) { const auto currState = entityInfo.entityState; mBootEntitiesInfo[localEntityIndex].entityState = currState; TriggerEntityState(entityInfo.entityName, currState, entityInfo.entityPID); } } else { EntityBootInfo newEntityInfo; newEntityInfo.entityName = entityInfo.entityName; newEntityInfo.entityState = entityInfo.entityState; mBootEntitiesInfo.push_back(newEntityInfo); AddEntityEntry(EntityInfo{ entityInfo.entityName, Manual, entityInfo.entityState, entityInfo.entityPID, entityInfo.entityVerStr }); } } void MainWindow::ReceiveCustomOperatResult(int action, int result, const QString& message) { qDebug() << "deal with custom operation result: " << message << " result " << result << endl; } void MainWindow::ReceiveOperatResult(int action, int result, const QString& message) { qDebug() << "deal with operation result: " << message << " result " << result << endl; for (int i = 0; i < mBootEntitiesInfo.size(); ++i) { if (mBootEntitiesInfo.at(i).entityName == message) { const auto& entityInfo = mBootEntitiesInfo.at(i); (new EntityStateRecoverTimer(this, entityInfo.entityName, entityInfo.entityState)); TriggerEntityState(entityInfo.entityName, result == 0 ? Passed : Failed, 0); break; } } } void MainWindow::UpdateEntityStatistics() { QString text = QString("(正在运行%1个模块,其中%2个正常)").arg(mTotalEntityCount).arg(mIdleEntityCount); qDebug() << mTotalEntityCount << " " << mIdleEntityCount; qDebug() << text; ui->labelEntCalculate->setText(text); } void MainWindow::NotifyLogMessage(MessageType type, const QString& title, const QString& message) { QString contentMessage = message; QJsonParseError parseError; QJsonDocument jsonDoc = QJsonDocument::fromJson(message.toUtf8(), &parseError); if (parseError.error == QJsonParseError::NoError) { QJsonObject jsonObject = jsonDoc.object(); if (jsonObject.contains(QStringLiteral("errmsg"))) { contentMessage = jsonObject["errmsg"].toString(); } } if (CanDisturb()) { switch (type) { case TextNotifyInfo: QMessageBox::information(this, title, contentMessage); break; case TextNotifyWarn: QMessageBox::warning(this, title, contentMessage); break; case TextNotifyError: QMessageBox::critical(this, title, contentMessage); break; default: break; } } else { ShowStatusMessage(contentMessage, type); } } static bool GetInterestPointWithRegex(const QString& origin, QString& entiName, QString& content) { QRegExp rx("^\\[(\\D+)\\]\\s{0,1}(E|W|F|I|D|T):\\s{0,1}\\{(.*)\\}\\(sc:(0x[A-Za-z0-9]+),\\s{0,1}uc:(0x[A-Za-z0-9]+)\\)$"); const int pos = rx.indexIn(origin); if (pos > -1) { entiName = rx.cap(1); content = rx.cap(3); QString systemCode = rx.cap(4); QString userCode = rx.cap(5); return true; } return false; } bool MainWindow::InsertConsole(const QtMessageInfo& message) { QString content = message.content; //FakeUnicodeToUnicode(message.content); bool dealed = true; if (message.type == TextNormal || message.type == TextEvent) { QBaseListWidgetItem* item = new QConsoleListWidgetItem(CoverWithTimePrefix(content)); item->AppentToWidget(ui->listWidgetEventLog); } else if (message.type == TextWarn) { QBaseListWidgetItem* item = new QLightWarnListWidgetItem(CoverWithTimePrefix(content)); item->AppentToWidget(ui->listWidgetEventLog); } else if (message.type == TextError) { QBaseListWidgetItem* item = new QLightErrorListWidgetItem(CoverWithTimePrefix(content)); item->AppentToWidget(ui->listWidgetEventLog); } else if (message.type == TextFatal || message.type == TextBlock || (message.type >= TextNotifyInfo && message.type <= TextNotifyError)) { QString entityName; const int existIdx = content.indexOf(":][:"); if (-1 != existIdx) { entityName = content.mid(0, existIdx); content = content.mid(existIdx + QString(":][:").length()); } #ifndef WITH_QT QBaseListWidgetItem* item2 = new QTipErrorListWidgetItem(CoverWithTimePrefix(content)); item2->AppentToWidget(ui->listWidgetFatalLog); #endif if (message.type == TextFatal || message.type == TextBlock) { if (-1 == existIdx) { GetInterestPointWithRegex(content, entityName, content); } #ifndef NDEBUG Note(content, BootStage, entityName, true); #endif //NDEBUG } else { #ifdef WITH_QT NotifyLogMessage(message.type, entityName, content); #endif } } else { dealed = false; } return dealed; } void MainWindow::ReceiveMessageVariant(QVariant info) { QtMessageInfo message = info.value(); if (InsertConsole(message)) { //empty } else if (message.type == ModBootInfo) { //entity boot info if (message.content.length() == 0 || message.param1 > Failed) { return; } int localEntityIndex = -1; for (int i = 0; i < mBootEntitiesInfo.size(); ++i) { if (mBootEntitiesInfo.at(i).entityName == message.content) { localEntityIndex = i; break; } } if (localEntityIndex != -1) { if (mBootEntitiesInfo[localEntityIndex].entityState != message.param1) { // const auto previousState = mBootEntitiesInfo[localEntityIndex].entityState; const auto currState = static_cast(message.param1); mBootEntitiesInfo[localEntityIndex].entityState = currState; TriggerEntityState(message.content, currState, 0); } } else { EntityBootInfo newEntityInfo; newEntityInfo.entityName = message.content; newEntityInfo.entityState = static_cast(message.param1); mBootEntitiesInfo.push_back(newEntityInfo); AddEntityEntry(EntityInfo{ message.content, Manual, static_cast(message.param1), 123, "V1.2.3" }); } } else if (message.type == ModStartupInfo) { //ShowMessage(QString::fromLocal8Bit(message.content), message.type); ShowStatusMessage(message.content, message.type); } else if (message.type == DisplayShow) { this->setWindowState((this->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); } else if (message.type == DisplayHide) { this->setWindowState(Qt::WindowMinimized); } else if (message.type == StageChangeInfo) { const bool oldSilent = mSilent; if (message.param1 == FRAMEWORK_STATE_RUNNING || message.param1 == FRAMEWORK_STATE_SERVING || message.param1 == FRAMEWORK_STATE_NOTDISTURB || message.param1 == FRAMEWORK_STATE_NOCONFIG) { mSilent = true; } else { mSilent = false; } if (mSilent != oldSilent) { OnSilentStateChange(mSilent); } } } bool MainWindow::CanDisturb() const { if (!mSilent) { return true; } Qt::WindowStates states = this->windowState(); if (!(states & Qt::WindowMinimized) && (states & Qt::WindowActive)) { return true; } return false; } void MainWindow::OnSilentStateChange(bool beSilent) { } void MainWindow::InitFloatWidget() { QDesktopWidget* desk = QApplication::desktop(); QRect rect = desk->screenGeometry(desk->primaryScreen()); const int wd = rect.width(); const int ht = rect.height(); mFloatWidget = new Widget(); mFloatWidget->show(); } MainWindow::~MainWindow() { delete ui; } void RichTimer::HandleTimeout(bool toStop) { mTimes++; mWin->RemindEntityStateChangeWith(mEntityName, toStop ? true : !(mTimes % 2)); if (toStop) { killTimer(mTimerID); delete this; } } void EntityStateRecoverTimer::HandleTimeout() { qDebug() << "reset entity state to " << MappingSatus2String(mState) << endl; mWin->TriggerEntityState(mEntityName, mState, -1, false); killTimer(mTimerID); delete this; } void TimeDateTimer::Start(int interval) { mTimer->start(interval); connect(mTimer, SIGNAL(timeout()), this, SLOT(HandleTimeout())); } void TimeDateTimer::Stop() { mTimer->stop(); } void TimeDateTimer::HandleTimeout() { mSeconds++; if (mSeconds == 60) { mMinutes++; mSeconds = 0; } if (mMinutes == 60) { mHours++; mMinutes = 0; } if (mHours == 24) { mDays++; mHours = 0; } mWin->TimeUpdate(GetCurrentRunTimeString()); }