mainwindow.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QHeaderView>
  4. #include <QDebug>
  5. #include <QMessageBox>
  6. #include <QDate>
  7. #include <QDateTime>
  8. #include <QDir>
  9. #include <QFile>
  10. #include <QFileInfo>
  11. #include <QDesktopWidget>
  12. #include <QTextCodec>
  13. #include <QProcess>
  14. #include <QFileDialog>
  15. #include <QStandardPaths>
  16. #include <QPropertyAnimation>
  17. #include <QJsonDocument>
  18. #include <QJsonObject>
  19. #include <QJsonArray>
  20. #include "dialogappversion.h"
  21. #include "dialogconfig.h"
  22. #include "sysinfo.h"
  23. #include "textfinder.h"
  24. #include "textedit.h"
  25. #include "BootGlobal.h"
  26. #define ENTITY_COLUMN_NAME 0
  27. #define ENTITY_COLUMN_STATUS 1
  28. #define ENTITY_COLUMN_PID 2
  29. #define ENTITY_COLUMN_VERSION 3
  30. #define ENTITY_COLUMN_BOOTTIME 4
  31. #define MAX_ENTITY_LIST_COLUMN 5
  32. //Mapping to SpBase::FrameworkStateEnum
  33. #define FRAMEWORK_STATE_NOTINIT 0
  34. #define FRAMEWORK_STATE_NOCONFIG 1
  35. #define FRAMEWORK_STATE_BOOTING 2
  36. #define FRAMEWORK_STATE_RUNNING 3
  37. #define FRAMEWORK_STATE_SERVING 4
  38. #define FRAMEWORK_STATE_BREAKDOWN 5
  39. #define FRAMEWORK_STATE_REPAIRING 6
  40. #define FRAMEWORK_STATE_UPGRADING 7
  41. #define FRAMEWORK_STATE_ROOLLBACKING 8
  42. #define FRAMEWORK_STATE_RECOVING 9
  43. #define FRAMEWORK_STATE_NOTDISTURB 10
  44. #define STARTUP_SCRIPT "spexplorer.sh"
  45. #ifdef DEVOPS_ON_ST /*DevOps流水线编译,ST环境*/
  46. #define RVC_TITLE_STRING "RVC Terminal Application STver."
  47. #elif defined(DEVOPS_ON_UAT)/*DevOps流水线编译,UAT环境*/
  48. #define RVC_TITLE_STRING "RVC Terminal Application UATver."
  49. #elif defined(DEVOPS_ON_PRD)/*DevOps流水线编译,PRD环境*/
  50. #define RVC_TITLE_STRING "RVC Terminal Application"
  51. #elif defined(DEVOPS_ON_DEV)/*DevOps流水线编译,Dev环境*/
  52. #define RVC_TITLE_STRING "RVC Terminal Application DEVver."
  53. #else/*本地编译等非DevOps环境编译的版本*/
  54. #define RVC_TITLE_STRING "RVC Terminal Application TESTver."
  55. #endif
  56. void setRowBackground(const QBrush& brush, QAbstractItemModel* model, int row, const QModelIndex& parent = QModelIndex())
  57. {
  58. if (!model || row < 0 || row >= model->rowCount(parent))
  59. return;
  60. if (parent.isValid() && parent.model() != model)
  61. return;
  62. for (int i = 0; i < model->columnCount(parent); ++i)
  63. Q_ASSUME(model->setData(model->index(row, i, parent), brush, Qt::BackgroundRole));
  64. }
  65. static QString EntityInfoHeaderString()
  66. {
  67. return QString("实体名称\t状态\t进程号\t版本\t启动时间\t文件句柄数");
  68. }
  69. static QString EntityRunInfoToString(const EntityRunInfo& entity)
  70. {
  71. QString result = QString("%1\t%2\t%3\t%4\t%5\t%6")
  72. .arg(entity.entityName)
  73. .arg(MappingSatus2String(entity.state))
  74. .arg(entity.pid)
  75. .arg(entity.version)
  76. .arg(entity.startupTimeStr)
  77. .arg(entity.fds);
  78. return result;
  79. }
  80. MainWindow::MainWindow(QWidget* parent)
  81. : QMainWindow(parent)
  82. , ui(new Ui::MainWindow), mSicon(nullptr), mSilent(false)
  83. , mIdleEntityCount(0), mTotalEntityCount(0), mFloatWidget(nullptr)
  84. {
  85. this->Init(RVC_TITLE_STRING);
  86. }
  87. MainWindow::MainWindow(QString systemInfo, int totalEntityCount, QWidget* parent)
  88. : QMainWindow(parent)
  89. , ui(new Ui::MainWindow), mSicon(nullptr), mSilent(false)
  90. , mIdleEntityCount(0), mTotalEntityCount(0), mFloatWidget(nullptr)
  91. {
  92. this->Init(systemInfo);
  93. }
  94. void MainWindow::Init(QString title)
  95. {
  96. ui->setupUi(this);
  97. setWindowIcon(QIcon(":/res/FavIcon.ico"));
  98. if (title.startsWith(RVC_TITLE_STRING)) {
  99. setWindowTitle(title);
  100. } else {
  101. setWindowTitle(QString(RVC_TITLE_STRING " [%1]").arg(title));
  102. }
  103. QPropertyAnimation* animation = new QPropertyAnimation(this, "windowOpacity");
  104. animation->setDuration(800);
  105. animation->setStartValue(0);
  106. animation->setEndValue(1);
  107. animation->start();
  108. //QTextCodec* codec = QTextCodec::codecForName("GBK");
  109. //QTextCodec::setCodecForLocale(codec);
  110. this->setMinimumSize(1068, 720);
  111. QDesktopWidget* desk = QApplication::desktop();
  112. //const int curScreenIdx = desk->screenNumber(this);
  113. const int curScreenIdx = desk->primaryScreen();
  114. QRect rect = desk->screenGeometry(curScreenIdx);
  115. const int wd = rect.width();
  116. const int ht = rect.height();
  117. this->move((wd - width()) / 2, (ht - height()) / 2);
  118. ui->splitter->setStretchFactor(0, 1);
  119. ui->splitter->setStretchFactor(1, 6);
  120. ui->splitter->setStretchFactor(2, 3);
  121. InitSystemTrayIcon();
  122. InitEntitiesView();
  123. #ifndef WITH_QT
  124. Test_EntityList();
  125. Test_EventLog();
  126. #endif
  127. QStringList selections;
  128. for (EntityState i = NoStart; i <= All;) {
  129. selections << MappingSatus2String(i);
  130. i = EntityState(i + 1);
  131. }
  132. ui->comboBoxStatus->addItems(selections);
  133. ui->comboBoxStatus->setCurrentIndex((int)All);
  134. connect(ui->comboBoxStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(DisplayEntities()));
  135. connect(ui->tableWidgetEntities->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(SortEntityItem(int)));
  136. InitMenuAction();
  137. InitStatusBar();
  138. connect(ui->pushButtonEntStart, SIGNAL(clicked()), this, SLOT(StartEntity()));
  139. connect(ui->pushButtonEntClose, SIGNAL(clicked()), this, SLOT(TerminateEntity()));
  140. connect(ui->pushButtonEntPause, SIGNAL(clicked()), this, SLOT(PauseEntity()));
  141. connect(ui->pushButtonEntContinue, SIGNAL(clicked()), this, SLOT(ContinueEntity()));
  142. connect(ui->pushButtonEntKill, SIGNAL(clicked()), this, SLOT(KillEntity()));
  143. connect(ui->pushButtonEntTest, SIGNAL(clicked()), this, SLOT(TestEntity()));
  144. connect(ui->pushButtonEntLogView, SIGNAL(clicked()), this, SLOT(LogView()));
  145. connect(ui->pushButtonClearRunCfg, SIGNAL(clicked()), this, SLOT(RemoveEntityRuninfoConfigFile()));
  146. SysInfo::instance().init();
  147. QHBoxLayout* cpuLayout = new QHBoxLayout();
  148. cpuLayout->setContentsMargins(0, 0, 0, 0);
  149. cpuLayout->setSpacing(0);
  150. cpuLayout->setMargin(0);
  151. ui->tab4CPU->setLayout(cpuLayout);
  152. ui->tab4CPU->layout()->addWidget(&mCpuWidget);
  153. QHBoxLayout* memoryLayout = new QHBoxLayout();
  154. memoryLayout->setContentsMargins(0, 0, 0, 0);
  155. ui->tab4Memory->setLayout(memoryLayout);
  156. ui->tab4Memory->layout()->addWidget(&mMemoryWidget);
  157. mPerformWidge = new PerformWidget(this);
  158. QHBoxLayout* monitorLayout = new QHBoxLayout();
  159. monitorLayout->setContentsMargins(0, 0, 0, 0);
  160. monitorLayout->addWidget(mPerformWidge);
  161. ui->tab4Monitor->setLayout(monitorLayout);
  162. #if 1//#ifdef WITH_QT
  163. QWidget* w = ui->splitterMain->widget(1);
  164. if (w != nullptr) {
  165. w->setParent(nullptr);
  166. w->deleteLater();
  167. }
  168. #endif
  169. /*
  170. QStringList arguments = QApplication::arguments();
  171. if (arguments.contains("--debug") || arguments.contains("-D")) {
  172. QTimer* tm = new QTimer(this);
  173. connect(tm, SIGNAL(timeout()), this, SLOT(RecordEntitySnapshot()));
  174. tm->start(3000);
  175. }
  176. */
  177. //InitFloatWidget();
  178. }
  179. QAction* MainWindow::CreateMenuAction(QString text, QKeySequence keyShot, QString toolTipText, void (MainWindow::* method)())
  180. {
  181. QAction* action = new QAction(text, this);
  182. action->setShortcut(keyShot);
  183. //action->setStatusTip(toolTipText);
  184. //connect(clearAct, SIGNAL(triggered()), textViewer, SLOT(clear()));
  185. connect(action, &QAction::triggered, this, method);
  186. return action;
  187. }
  188. void MainWindow::ProcessStarted()
  189. {
  190. qDebug() << "process started! ";
  191. }
  192. void MainWindow::GetSubProcessMsg()
  193. {
  194. }
  195. void MainWindow::TriggerAdditionMenu(QAction* action)
  196. {
  197. qDebug() << "menu: " << action->text();
  198. RvcAdditionAction* pAct = reinterpret_cast<RvcAdditionAction*>(action);
  199. switch (pAct->userData.type) {
  200. case BootEntity:
  201. {
  202. StartEntityFromCustom(pAct->userData.entityName, pAct->userData.cmdLine);
  203. }
  204. break;
  205. case RunShellScript:
  206. break;
  207. case CreatesSubProcess:
  208. default:
  209. {
  210. QProcess* process = new QProcess(this);
  211. //connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(GetSubProcessMsg()));
  212. //connect(process, SIGNAL(started()), this, SLOT(ProcessStarted()));
  213. QString appDir = QCoreApplication::applicationDirPath();
  214. #ifdef Q_WS_WIN32
  215. if (appDir.endsWith("\\bin")) {
  216. appDir = appDir.left(appDir.length() - QString("\\bin").length());
  217. process->setWorkingDirectory(appDir);
  218. }
  219. #else
  220. if (appDir.endsWith("/bin")) {
  221. appDir = appDir.left(appDir.length() - QString("/bin").length());
  222. process->setWorkingDirectory(appDir);
  223. }
  224. #endif
  225. process->setStandardOutputFile(QProcess::nullDevice());
  226. process->setStandardErrorFile(QProcess::nullDevice());
  227. qDebug() << "start process: " << pAct->userData.cmdLine;
  228. process->startDetached(pAct->userData.cmdLine);
  229. //process->waitForFinished(1000);
  230. delete process;
  231. }
  232. break;
  233. }
  234. }
  235. void MainWindow::InitMenuAction()
  236. {
  237. QMenu* mainMenu = menuBar()->addMenu(QString::fromUtf8("菜单(&M)"));
  238. //mainMenu->addAction(CreateMenuAction(QString::fromUtf8("初始化(&I)"), tr("Alt+I"), QString::fromUtf8("初始化终端")
  239. // , &MainWindow::InitializeTerminal));
  240. mainMenu->addAction(CreateMenuAction(QString::fromUtf8("重启当前版本(&T)"), tr("Alt+T"), QString::fromUtf8("重启可视柜台终端应用")
  241. , &MainWindow::RestartApp));
  242. mainMenu->addAction(CreateMenuAction(QString::fromUtf8("重启应用(&R)"), tr("Alt+R"), QString::fromUtf8("通过读取 active.txt 重启可视柜台终端应用")
  243. , &MainWindow::RestartAppThroughSpShell));
  244. QMenu* sysConfigMenu = mainMenu->addMenu(QString::fromUtf8("关机"));
  245. sysConfigMenu->addAction(CreateMenuAction(QString::fromUtf8("重启(&P)"), tr("Alt+P"), QString::fromUtf8("重启操作系统")
  246. , &MainWindow::RestartSystem));
  247. sysConfigMenu->addAction(CreateMenuAction(QString::fromUtf8("关机(&D)"), tr("Alt+D"), QString::fromUtf8("关闭计算机")
  248. , &MainWindow::ShutdownSystem));
  249. mainMenu->addAction(CreateMenuAction(QString::fromUtf8("退出应用(&Q)"), tr("Alt+Q"), QString::fromUtf8("退出可视柜台终端应用")
  250. , &MainWindow::QuitApp));
  251. QMenu* configMenu = menuBar()->addMenu(QString::fromUtf8("配置(&C)"));
  252. configMenu->addAction(CreateMenuAction(QString::fromUtf8("加载控件(&L)"), tr("Alt+L"), QString::fromUtf8("动态加载控件")
  253. , &MainWindow::LoadCustomPlguins));
  254. QMenu* toolMenu = menuBar()->addMenu(QString::fromUtf8("工具(&T)"));
  255. toolMenu->addAction(CreateMenuAction(QString::fromUtf8("选项(&O)"), tr("Alt+O"), QString::fromUtf8("相关选项设置")
  256. , &MainWindow::ConfigApp));
  257. toolMenu->addAction(CreateMenuAction(QString::fromUtf8("导出快照(&S)"), tr("Alt+S"), QString::fromUtf8("导出实体即时信息快照")
  258. , &MainWindow::ExportEntitySnapshot));
  259. QMenu* addMenu = menuBar()->addMenu(QString::fromUtf8("附加(&A)"));
  260. const QString configFileName = getFrameworkConfigPath();
  261. qDebug() << "config file name: " << configFileName;
  262. QFileInfo fileInfo(configFileName);
  263. if (fileInfo.exists()) {
  264. RvcSettings* settings = new RvcSettings(configFileName, QSettings::IniFormat);
  265. settings->setIniCodec("UTF-8");
  266. int menuCount = settings->GetConfigData("Menu", "Count").toInt();
  267. qDebug() << "menu count: " << menuCount;
  268. int validIdx = 1;
  269. for (int i = 1; i <= menuCount; ++i) {
  270. QString strIdx = QString::number(i);
  271. QString subMenuName = settings->GetConfigData("Menu", strIdx).toString();
  272. QString textName = settings->GetConfigData(subMenuName, "TextName").toString();
  273. const int exeType = settings->GetConfigData(subMenuName, "Type").toInt();
  274. const auto excuteEnum = static_cast<ExecuteType>(exeType);
  275. QString cmdLine = settings->GetConfigData(subMenuName, "CmdLine").toString();
  276. if (cmdLine.isNull() || cmdLine.isEmpty()) {
  277. continue;
  278. }
  279. QString strQuick = QString("Alt+%1").arg(validIdx++);
  280. qDebug() << subMenuName << " " << textName << " " << strIdx << " " << cmdLine << " " << strQuick;
  281. QString menuName = (!textName.isNull() && !textName.isEmpty()) ? textName : cmdLine;
  282. RvcAdditionAction* action = new RvcAdditionAction(menuName, this);
  283. action->setShortcut(strQuick);
  284. //action->setStatusTip(cmdLine);
  285. action->userData.type = excuteEnum;
  286. cmdLine = cmdLine.trimmed();
  287. if (excuteEnum == BootEntity && -1 != cmdLine.indexOf('\t')) {
  288. const int idx = cmdLine.indexOf('\t');
  289. QStringList params = cmdLine.split("\t");
  290. action->userData.entityName = params.at(0);
  291. action->userData.cmdLine = cmdLine.mid(idx + 1);
  292. } else if (excuteEnum == BootEntity) {
  293. action->userData.entityName = cmdLine;
  294. action->userData.cmdLine = "";
  295. } else {
  296. action->userData.cmdLine = cmdLine;
  297. }
  298. addMenu->addAction(action);
  299. }
  300. if (menuCount > 0) {
  301. connect(addMenu, SIGNAL(triggered(QAction*)), this, SLOT(TriggerAdditionMenu(QAction*)));
  302. }
  303. }
  304. QMenu* helpMenu = menuBar()->addMenu(QString::fromUtf8("帮助(&H)"));
  305. helpMenu->addAction(CreateMenuAction(QString::fromUtf8("关于应用(&A)"), tr("Alt+A"), QString::fromUtf8("可视柜台终端应用版本更新记录")
  306. , &MainWindow::VersionView));
  307. helpMenu->addAction(CreateMenuAction(QString::fromUtf8("错误码对照表(&A)"), tr("Alt+E"), QString::fromUtf8("ErrorCode错误码对照表")
  308. , &MainWindow::ErrorCodeView));
  309. }
  310. void MainWindow::ConfigApp()
  311. {
  312. qDebug() << "Enter ConfigApp" << endl;
  313. #ifdef WITH_QT
  314. std::string path = CSpShellConsole::GetRootConfigPath();
  315. DialogInParam param;
  316. param.rootIniPath = path.c_str();
  317. DialogConfig dial(&param, this);
  318. #else
  319. DialogInParam param;
  320. param.rootIniPath = "D:\\Run\\hardwarecfg\\root.ini";
  321. DialogConfig dial(&param, this);
  322. #endif
  323. dial.exec();
  324. }
  325. void MainWindow::QuitApp()
  326. {
  327. qDebug() << "Enter QuitApp" << endl;
  328. #ifdef WITH_QT
  329. qApp->exit(APP_EXIT_CODE_QUIT); //or exit
  330. #else
  331. exit(APP_EXIT_CODE_QUIT);
  332. #endif
  333. qDebug() << "Leave QuitApp" << endl;
  334. }
  335. static void ClearArguments(const QString& program, QStringList& arguments)
  336. {
  337. if (arguments.contains(program)) {
  338. arguments.removeOne(program);
  339. }
  340. if (arguments.contains("--restart")) {
  341. arguments.removeOne("--restart");
  342. }
  343. if (arguments.contains("-R")) {
  344. arguments.removeOne("-R");
  345. }
  346. if (!arguments.contains("-Rwait")) {
  347. arguments.append("-Rwait");
  348. }
  349. }
  350. void MainWindow::RestartApp()
  351. {
  352. qDebug() << "Enter RestartApp" << endl;
  353. qint64 nextProcID(0);
  354. QString program = QApplication::applicationFilePath();
  355. QStringList arguments = QApplication::arguments();
  356. QString workingDirectory = QDir::currentPath();
  357. ClearArguments(program, arguments);
  358. qDebug() << "Program: " << program << " " << arguments << " " << workingDirectory << endl;
  359. bool result = QProcess::startDetached(program, arguments, workingDirectory, &nextProcID);
  360. qDebug() << "Program result: " << result << " " << nextProcID;
  361. QApplication::exit(APP_EXIT_CODE_RESTART_CURR);
  362. }
  363. void MainWindow::RestartSystem()
  364. {
  365. QString str = "确定要重启系统吗?";
  366. QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str,
  367. QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
  368. if (rb == QMessageBox::Yes) {
  369. QProcess::startDetached("sudo shutdown -r now");
  370. }
  371. }
  372. void MainWindow::ShutdownSystem()
  373. {
  374. QString str = "确定要关机吗?";
  375. QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str,
  376. QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
  377. if (rb == QMessageBox::Yes) {
  378. QProcess::startDetached("sudo shutdown --poweroff now");
  379. }
  380. }
  381. /** 该接口暂且放弃使用,因为使用QT创建子进程会继承文件句柄,改用 RestartAppThroughSpShell 与框架重启公用一套接口*/
  382. void MainWindow::RestartAppThroughActive()
  383. {
  384. qDebug() << "Enter " << __FUNCTION__ << endl;
  385. qint64 nextProcID(0);
  386. QString program = QApplication::applicationFilePath();
  387. QStringList arguments = QApplication::arguments();
  388. QString workingDirectory = QDir::currentPath();
  389. QString newProgrm = program;
  390. QString newWorkingDirectory = workingDirectory;
  391. QDir versionDir = QDir::current();
  392. versionDir.cdUp();
  393. #if 0
  394. QString activeFilePath = versionDir.filePath("active.txt");
  395. QFile activeFile(activeFilePath);
  396. if (!activeFile.exists()) {
  397. QMessageBox::critical(this, "错误", QString("文件 %1 不存在!").arg(activeFilePath));
  398. return;
  399. }
  400. if (!activeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
  401. QMessageBox::critical(this, "错误", QString("打开文件 %1 失败:%2").arg(activeFilePath).arg(activeFile.errorString()));
  402. return;
  403. }
  404. QByteArray versionContent = activeFile.readAll();
  405. versionContent = versionContent.trimmed();
  406. activeFile.close();
  407. if (versionContent.isEmpty() || versionContent.isNull()) {
  408. QMessageBox::critical(this, "错误", QString("文件 %1 内容为空!").arg(activeFilePath));
  409. return;
  410. }
  411. QStringList programPaths = program.split("/");
  412. QString curVersion = programPaths[programPaths.size() - 3];
  413. if (curVersion == QString(versionContent)) {
  414. qDebug() << "Detect is the same version: " << (QString)versionContent;
  415. } else {
  416. qDebug() << "Detect diff version, from " << curVersion << " to " << (QString)versionContent;
  417. programPaths.replace(programPaths.size() - 3/*x.y.z/bin/spshell*/, versionContent);
  418. newProgrm = programPaths.join("/");
  419. QStringList workingPaths = workingDirectory.split("/");
  420. workingPaths.replace(workingPaths.size() - 1/*/x.y.z*/, versionContent);
  421. newWorkingDirectory = workingPaths.join("/");
  422. }
  423. #else
  424. QString scriptFilePath = versionDir.filePath(STARTUP_SCRIPT);
  425. QFile scriptFile(scriptFilePath);
  426. if (!scriptFile.exists()) {
  427. QMessageBox::critical(this, "错误", QString("启动脚本 %1 不存在!").arg(scriptFilePath));
  428. return;
  429. }
  430. auto permitt = scriptFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner
  431. | QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ExeUser
  432. | QFileDevice::ReadGroup | QFileDevice::ReadOther
  433. | QFileDevice::ExeGroup | QFileDevice::ExeOther);
  434. if (!permitt) {
  435. QMessageBox::critical(this, "错误", QString("设置 %1 文件权限失败:%2!").arg(scriptFilePath).arg(scriptFile.errorString()));
  436. return;
  437. }
  438. newProgrm = scriptFilePath;
  439. newWorkingDirectory = versionDir.currentPath();
  440. #endif
  441. ClearArguments(program, arguments);
  442. qunsetenv("LD_LIBRARY_PATH");
  443. qDebug() << "newProgrm: " << newProgrm << " " << arguments << " " << newWorkingDirectory << endl;
  444. bool result = QProcess::startDetached(newProgrm, arguments, newWorkingDirectory, &nextProcID);
  445. qDebug() << "Program result: " << result << " " << nextProcID;
  446. QApplication::exit();
  447. }
  448. void MainWindow::RestartAppThroughSpShell()
  449. {
  450. qDebug() << "Enter " << __FUNCTION__ << endl;
  451. qint64 nextProcID(0);
  452. QString program = QApplication::applicationFilePath();
  453. QStringList arguments = QApplication::arguments();
  454. QString workingDirectory = QDir::currentPath();
  455. QString newProgrm = program;
  456. QString newWorkingDirectory = workingDirectory;
  457. QDir versionDir = QDir::current();
  458. versionDir.cdUp();
  459. QString scriptFilePath = versionDir.filePath(STARTUP_SCRIPT);
  460. QFile scriptFile(scriptFilePath);
  461. if (!scriptFile.exists()) {
  462. QMessageBox::critical(this, "错误", QString("启动脚本 %1 不存在!").arg(scriptFilePath));
  463. return;
  464. }
  465. auto permitt = scriptFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner
  466. | QFileDevice::ReadUser | QFileDevice::WriteUser | QFileDevice::ExeUser
  467. | QFileDevice::ReadGroup | QFileDevice::ReadOther
  468. | QFileDevice::ExeGroup | QFileDevice::ExeOther);
  469. if (!permitt) {
  470. QMessageBox::critical(this, "错误", QString("设置 %1 文件权限失败:%2!").arg(scriptFilePath).arg(scriptFile.errorString()));
  471. return;
  472. }
  473. #ifdef WITH_QT
  474. int result = CSpShellConsole::RestartApplication();
  475. if (result != 0) {
  476. QMessageBox::critical(this, "错误", QString("执行重启请求失败!"));
  477. return;
  478. }
  479. #endif
  480. QApplication::exit(APP_EXIT_CODE_RESTART_ACTIVE);
  481. }
  482. void MainWindow::InitializeTerminal()
  483. {
  484. LogView();
  485. }
  486. void MainWindow::LogView()
  487. {
  488. qDebug() << "Enter LogView" << endl;
  489. auto enti = GetCurrentSelectedEntity();
  490. #ifdef WITH_QT
  491. if (!enti.entityName.isEmpty()) {
  492. std::string path = CSpShellConsole::GetEntityLogPath(Q2Str(enti.entityName).c_str());
  493. TextFinder textFinder(Str2Q(path), enti.entityName, this);
  494. textFinder.exec();
  495. }
  496. #endif
  497. }
  498. void MainWindow::ErrorCodeView()
  499. {
  500. qDebug() << "Enter ErrorCodeView" << endl;
  501. #if 1
  502. DialogAppVersion dial(QLatin1String(":/res/sys_errcode.html"), ("系统错误码对照表"), this);
  503. dial.exec();
  504. #else
  505. TextEdit mw;
  506. QDesktopWidget* desk = QApplication::desktop();
  507. const int curScreenIdx = desk->primaryScreen();
  508. QRect rect = desk->screenGeometry(curScreenIdx);
  509. const int wd = rect.width();
  510. const int ht = rect.height();
  511. mw.resize(wd / 2, (ht * 2) / 3);
  512. mw.move((wd - mw.width()) / 2,
  513. (ht - mw.height()) / 2);
  514. mw.setContents(QLatin1String(":/res/sys_errcode.html"));
  515. mw.show();
  516. #endif
  517. //TextEdit textEdit(this);
  518. //textEdit.setContents(":/res/sys_errcode.html");
  519. //textEdit.show();
  520. }
  521. void MainWindow::RemoveEntityRuninfoConfigFile()
  522. {
  523. auto enti = GetCurrentSelectedEntity();
  524. #ifdef WITH_QT
  525. if (!enti.entityName.isEmpty()) {
  526. std::string path = CSpShellConsole::GetEntityRTPath(Q2Str(enti.entityName).c_str());
  527. if (!path.empty()) {
  528. QFile file(path.c_str());
  529. if (file.exists()) {
  530. QString str = QString("确定要删除 %1 实体运行时文件?").arg(enti.entityName);
  531. QMessageBox::StandardButton rb = QMessageBox::question(NULL, "Warning", str,
  532. QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
  533. if (rb == QMessageBox::Yes) {
  534. if (QFile::remove(path.c_str())) {
  535. QMessageBox::information(this, "提示", "删除成功!请重启应用或实体以立即生效!");
  536. } else {
  537. QMessageBox::warning(this, "错误", QString("%1: 删除运行时文件 %2 失败!")
  538. .arg(enti.entityName).arg(path.c_str()));
  539. }
  540. }
  541. } else {
  542. QMessageBox::warning(this, "提示", QString("%1: %2 运行时文件不存在!").arg(enti.entityName).arg(path.c_str()));
  543. }
  544. } else {
  545. QMessageBox::critical(this, "错误", QString("%1: 获取运行时文件路径失败!").arg(enti.entityName));
  546. }
  547. } else {
  548. QMessageBox::critical(this, "错误", "无法获取实体名称,请选中实体列表所在行!");
  549. }
  550. #endif
  551. }
  552. void MainWindow::VersionView()
  553. {
  554. qDebug() << "Enter VersionView" << endl;
  555. DialogAppVersion dial(QLatin1String(":/res/version_history.html"), ("关于可视柜台终端应用程序"), this);
  556. dial.exec();
  557. }
  558. void MainWindow::DisplayEntities()
  559. {
  560. EntityState filterState = EntityState(ui->comboBoxStatus->currentIndex());
  561. QString str = MappingSatus2String(filterState);
  562. if (filterState == All)
  563. str = "";
  564. auto entities = ui->tableWidgetEntities->findItems(str, Qt::MatchExactly);
  565. const int rows = ui->tableWidgetEntities->rowCount();
  566. qDebug() << "Enter DisplayEntities " << str << " " << rows << "!" << endl;
  567. for (int i = 0; i < rows; ++i) {
  568. const auto strStatus = ui->tableWidgetEntities->item(i, ENTITY_COLUMN_STATUS)->text();
  569. ui->tableWidgetEntities->setRowHidden(i, !str.isEmpty() && strStatus.compare(str) != 0);
  570. }
  571. }
  572. void MainWindow::ResetAllEntityOperateBtnState(bool enable)
  573. {
  574. ui->pushButtonEntStart->setEnabled(enable);
  575. ui->pushButtonEntClose->setEnabled(enable);
  576. ui->pushButtonEntPause->setEnabled(enable);
  577. ui->pushButtonEntContinue->setEnabled(enable);
  578. ui->pushButtonEntKill->setEnabled(enable);
  579. ui->pushButtonEntTest->setEnabled(enable);
  580. }
  581. void MainWindow::StartEntityFromCustom(const QString& entityName, const QString& cmdLine)
  582. {
  583. qDebug() << "Enter StartEntityFromCustom " << entityName << " " << cmdLine << "!" << endl;
  584. const int entityRow = FindEntityRowIndex(entityName);
  585. EntityInfo entityInfo = GetEntityInfoByRowIndex(entityRow);
  586. if (entityInfo.IsValid()) {
  587. const auto curState = entityInfo.state;
  588. if (curState != NoStart && curState != Killed && curState != Close) {
  589. QString str = QString("%1 实体目前处于运行状态,是否要强制重启?").arg(entityName);
  590. QMessageBox::StandardButton rb = QMessageBox::question(this, "确认", str,
  591. QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
  592. if (rb == QMessageBox::Yes) {
  593. const int result = DealWithEntity(entityInfo, Deal_Kill, "", false);
  594. if (result != 0) {
  595. QMessageBox::critical(this, "错误", QString("终止旧实体例程 %1 失败!").arg(entityInfo.entityName));
  596. return;
  597. }
  598. } else {
  599. return;
  600. }
  601. }
  602. }
  603. Threadee* nE = new Threadee();
  604. nE->dealType = Deal_Start;
  605. nE->entityName = entityName;
  606. nE->cmdLine = cmdLine;
  607. OperatThread* ot = new OperatThread(nE, nullptr);
  608. connect(ot, &QThread::finished, ot, &QObject::deleteLater);
  609. connect(ot, &OperatThread::OperateResult, this, &MainWindow::ReceiveCustomOperatResult);
  610. ot->start();
  611. }
  612. void MainWindow::UpdateEntityOperateBtnState(EntityState currState)
  613. {
  614. switch (currState) {
  615. case Idle:
  616. ResetAllEntityOperateBtnState();
  617. ui->pushButtonEntStart->setEnabled(false);
  618. ui->pushButtonEntContinue->setEnabled(false);
  619. break;
  620. case NoStart:
  621. ResetAllEntityOperateBtnState(false);
  622. ui->pushButtonEntStart->setEnabled(true);
  623. break;
  624. case Starting:
  625. ResetAllEntityOperateBtnState(false);
  626. ui->pushButtonEntKill->setEnabled(true);
  627. break;
  628. case Busy:
  629. ResetAllEntityOperateBtnState(false);
  630. ui->pushButtonEntKill->setEnabled(true);
  631. break;
  632. case Pause:
  633. ResetAllEntityOperateBtnState(false);
  634. ui->pushButtonEntContinue->setEnabled(true);
  635. ui->pushButtonEntKill->setEnabled(true);
  636. break;
  637. case UnLoading:
  638. ResetAllEntityOperateBtnState(false);
  639. break;
  640. case Lost:
  641. ResetAllEntityOperateBtnState(false);
  642. ui->pushButtonEntKill->setEnabled(true);
  643. break;
  644. case Close:
  645. case Killed:
  646. ResetAllEntityOperateBtnState(false);
  647. ui->pushButtonEntStart->setEnabled(true);
  648. break;
  649. case Passed:
  650. case Failed:
  651. ResetAllEntityOperateBtnState();
  652. ui->pushButtonEntStart->setEnabled(false);
  653. ui->pushButtonEntContinue->setEnabled(false);
  654. break;
  655. default:
  656. ResetAllEntityOperateBtnState(false);
  657. }
  658. }
  659. void MainWindow::EntitySelectionChanged()
  660. {
  661. const QTableWidgetItem* currentItem = ui->tableWidgetEntities->currentItem();
  662. qDebug() << QString("Enter EntitySelectionChanged: ") << currentItem->text();
  663. //ShowMessage(currentItem->text(), 0);
  664. UpdateEntityOperateBtnState(GetCurrentSelectedEntity().state);
  665. }
  666. void MainWindow::SortEntityItem(int n)
  667. {
  668. static bool sortStatus[MAX_ENTITY_LIST_COLUMN] = { false };
  669. ui->tableWidgetEntities->sortItems(n, (sortStatus[n] ? Qt::AscendingOrder : Qt::DescendingOrder));
  670. sortStatus[n] = !sortStatus[n];
  671. }
  672. QTableWidgetItem* MainWindow::FindEnityWidgetItem(QString entityName)
  673. {
  674. auto entities = ui->tableWidgetEntities->findItems(entityName, Qt::MatchExactly);
  675. if (entities.count() > 0)
  676. return entities[0];
  677. return nullptr;
  678. }
  679. int MainWindow::FindEntityRowIndex(QString entityName)
  680. {
  681. int result = -1;
  682. auto item = FindEnityWidgetItem(entityName);
  683. if (item)
  684. result = item->row();
  685. return result;
  686. }
  687. void MainWindow::RemindEntityStateChangeWith(QString entityName, bool bEnd)
  688. {
  689. const int row = FindEntityRowIndex(entityName);
  690. if (row >= 0) {
  691. qDebug() << entityName << " " << bEnd << endl;
  692. if (bEnd)
  693. UpdateItemBackgroundColor(row, MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()));
  694. else
  695. UpdateItemBackgroundColor(row, Idle);
  696. }
  697. }
  698. void MainWindow::RemindEntityStateChange(int row, EntityState previousState, EntityState currState)
  699. {
  700. UpdateItemBackgroundColor(row, currState);
  701. #ifndef NDEBUG
  702. if (currState == Lost) {
  703. QString info("Entity ");
  704. QString entity(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text());
  705. info.append(entity);
  706. info += " 's State from ";
  707. info += MappingSatus2String(previousState);
  708. info += " to ";
  709. info += MappingSatus2String(currState);
  710. Note(info, EntityFire, entity, true);
  711. }
  712. #endif //NDEBUG
  713. (new RichTimer(this, ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text()));
  714. }
  715. void MainWindow::TriggerEntityState(int row, EntityState state, int pid, bool filcker)
  716. {
  717. const EntityState previousState = MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text());
  718. if (pid == -1/*for entity reset*/ && (previousState != Passed && previousState != Failed)) {
  719. return;
  720. }
  721. ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->setText(MappingSatus2String(state));
  722. if (state == Close || state == NoStart) {
  723. ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->setText("0");
  724. } else if (pid > 0) {
  725. ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->setText(QString::number(pid));
  726. }
  727. if ((state == Idle) && (previousState == NoStart
  728. || previousState == Starting
  729. || previousState == UnLoading
  730. || previousState == Lost
  731. || previousState == Close
  732. || previousState == Killed
  733. )) {
  734. QDateTime currentTime = QDateTime::currentDateTime();
  735. QString currentTimeStr = currentTime.toString("MM-dd-hh:mm:ss.zzz");
  736. ui->tableWidgetEntities->item(row, ENTITY_COLUMN_BOOTTIME)->setText(currentTimeStr);
  737. }
  738. if (state != previousState) {
  739. if (state == Idle) {
  740. mIdleEntityCount++;
  741. } else if (previousState == Idle) {
  742. mIdleEntityCount--;
  743. }
  744. UpdateEntityStatistics();
  745. }
  746. if (filcker) {
  747. RemindEntityStateChange(row, previousState, state);
  748. ui->tableWidgetEntities->setCurrentItem(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME));
  749. qDebug() << "emit entity select change." << endl;
  750. emit ui->tableWidgetEntities->itemSelectionChanged();
  751. } else {
  752. RemindEntityStateChangeWith(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text(), true);
  753. }
  754. }
  755. int MainWindow::TriggerEntityState(QTableWidgetItem* item, EntityState state, int pid, bool flicker)
  756. {
  757. if (!item)
  758. return -1;
  759. TriggerEntityState(item->row(), state, pid, flicker);
  760. return 0;
  761. }
  762. int MainWindow::TriggerEntityState(QString entityName, EntityState state, int pid, bool flicker)
  763. {
  764. const int row = FindEntityRowIndex(entityName);
  765. if (row >= 0) {
  766. TriggerEntityState(row, state, pid, flicker);
  767. }
  768. return 0;
  769. }
  770. int MainWindow::DealWithEntity(const EntityInfo& entity, DealType dealType, QString extendParam, bool multiThread)
  771. {
  772. qDebug() << "Deal with entity: " << entity.entityName << " with " << QString::number(dealType) << endl;
  773. int result = -1;
  774. if (!entity.entityName.isEmpty()) {
  775. Threadee* nE = new Threadee();
  776. nE->dealType = dealType;
  777. nE->entityName = entity.entityName;
  778. nE->cmdLine = extendParam;
  779. OperatThread* ot = new OperatThread(nE, nullptr);
  780. if (multiThread) {
  781. if (dealType == Deal_Test) {
  782. connect(ot, &OperatThread::OperateResult, this, &MainWindow::ReceiveOperatResult);
  783. }
  784. connect(ot, &QThread::finished, ot, &QObject::deleteLater);
  785. ot->start();
  786. result = -1 /*forbid changing entity state at screen*/;
  787. } else {
  788. bool ret = ot->doSomething();
  789. result = ret ? 0 : -1;
  790. }
  791. }
  792. return result;
  793. }
  794. void MainWindow::StartEntity()
  795. {
  796. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Start);
  797. if (optResult == 0) {
  798. TriggerEntityState(GetCurrentSelectedEntity().entityName, Idle, 8888);
  799. }
  800. }
  801. void MainWindow::PauseEntity()
  802. {
  803. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Pause);
  804. if (optResult == 0) {
  805. TriggerEntityState(GetCurrentSelectedEntity().entityName, Pause);
  806. }
  807. }
  808. void MainWindow::ContinueEntity()
  809. {
  810. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Continue);
  811. if (optResult == 0) {
  812. TriggerEntityState(GetCurrentSelectedEntity().entityName, Idle);
  813. }
  814. }
  815. void MainWindow::TerminateEntity()
  816. {
  817. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Close);
  818. if (optResult == 0) {
  819. TriggerEntityState(GetCurrentSelectedEntity().entityName, Close);
  820. }
  821. }
  822. void MainWindow::KillEntity()
  823. {
  824. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Kill);
  825. if (optResult == 0) {
  826. TriggerEntityState(GetCurrentSelectedEntity().entityName, Killed);
  827. }
  828. }
  829. void MainWindow::TestEntity()
  830. {
  831. int optResult = DealWithEntity(GetCurrentSelectedEntity(), Deal_Test);
  832. if (optResult == 0) {
  833. TriggerEntityState(GetCurrentSelectedEntity().entityName, Passed);
  834. }
  835. }
  836. QString MainWindow::GetPerfStorePath()
  837. {
  838. #ifdef WITH_QT
  839. std::string path = CSpShellConsole::GetTempPath();
  840. #else
  841. std::string path = "C:\\rvc\\temp";
  842. #endif
  843. if (!path.empty()) {
  844. QDir tempDir(path.c_str());
  845. tempDir.mkpath(QString("perf"));
  846. if (tempDir.cd("perf")) {
  847. return tempDir.absolutePath();
  848. } else {
  849. qDebug() << "cd " << tempDir.path() << " failed";
  850. return QString(path.c_str());
  851. }
  852. }
  853. }
  854. QStringList MainWindow::ExecuteShellScripts(QString shellCmd)
  855. {
  856. QStringList results;
  857. QProcess* subScriptsProcess = new QProcess(this);
  858. subScriptsProcess->setProcessChannelMode(QProcess::MergedChannels);
  859. subScriptsProcess->start("sh", QStringList() << "-c" << shellCmd);
  860. subScriptsProcess->waitForFinished();
  861. QString str(subScriptsProcess->readAllStandardOutput());
  862. results << str;
  863. results << QString::number(subScriptsProcess->exitCode());
  864. QMessageBox::warning(this, "Run ShellScripts Info", results.join("\t"), QMessageBox::Ok);
  865. delete subScriptsProcess;
  866. return QStringList() << str;
  867. }
  868. void MainWindow::RecordEntitySnapshot()
  869. {
  870. qDebug() << "Enter " << __FUNCTION__;
  871. #if 0
  872. QPixmap p = mPerformWidge->grab();
  873. QString filePathName = GetPerfStorePath();
  874. filePathName += "/EntityPerf_";
  875. filePathName += QDateTime::currentDateTime().toString("yyyyMMdd-hhmmsszzz");
  876. filePathName += ".png";
  877. if (!p.save(filePathName, "png")) {
  878. qDebug() << "save widget screen failed";
  879. }
  880. #endif
  881. ExportEntityInfo(false);
  882. }
  883. void MainWindow::ExportEntityInfo(bool fromBtnClick)
  884. {
  885. QTableWidget* table = ui->tableWidgetEntities;
  886. QString fileName;
  887. if (fromBtnClick) {
  888. fileName = QFileDialog::getSaveFileName(table,
  889. "保存"
  890. , QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)
  891. , "文本文件(*.txt)");
  892. } else {
  893. QDir tempDir(GetPerfStorePath());
  894. QDateTime currTime = QDateTime::currentDateTime();
  895. QString currTimeString = currTime.toString("yyyyMMdd");
  896. QString filePureName = currTimeString + "_EntityInfo.txt";
  897. fileName = tempDir.filePath(filePureName);
  898. qDebug() << "entity info file path: " << fileName;
  899. }
  900. QFile file(fileName);
  901. if (!file.open(fromBtnClick ? (QIODevice::ReadWrite | QIODevice::Text) : (QIODevice::ReadWrite | QIODevice::Append))) {
  902. if (fromBtnClick) QMessageBox::warning(this, tr("错误"), tr("<font size='12' color='red'>打开文件失败,数据保存失败!</font>"));
  903. else qDebug() << "打开文件失败,数据保存失败! " << file.errorString();
  904. return;
  905. }
  906. if (!file.isReadable()) {
  907. if (fromBtnClick) QMessageBox::warning(this, tr("错误"), tr("<font size='12' color='red'>该文件不可读,数据保存失败!</font>"));
  908. else qDebug() << "该文件不可读,数据保存失败! " << file.errorString();
  909. } else {
  910. QTextStream out(&file);
  911. // const int colCounts = table->columnCount();
  912. const int rowCounts = table->rowCount();
  913. for (int i = 0; i < rowCounts; ++i) {
  914. const EntityInfo entityInfo = GetEntityInfoByRowIndex(i);
  915. EntityRunInfo entityRunInfo(entityInfo);
  916. entityRunInfo.startupTimeStr = ui->tableWidgetEntities->item(i, ENTITY_COLUMN_BOOTTIME)->text();
  917. entityRunInfo.fds = PerformWidget::GetProcessFds(entityRunInfo.pid);
  918. if (i == 0) {
  919. QString currentTime = QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
  920. QString timestamp = QString("\n\nRecord at: %1\n").arg(currentTime);
  921. file.write(timestamp.toUtf8());
  922. QString header = EntityInfoHeaderString();
  923. file.write(header.toUtf8());
  924. }
  925. QString str = "\n";
  926. str += EntityRunInfoToString(entityRunInfo);
  927. file.write(str.toUtf8());
  928. }
  929. if (fromBtnClick) QMessageBox::warning(this, tr("信息"), tr("<font size='12' color='green'>实体信息保存成功!</font>"));
  930. else qDebug() << "实体信息保存成功!";
  931. }
  932. file.close();
  933. }
  934. void MainWindow::ExportEntitySnapshot()
  935. {
  936. ExportEntityInfo(true);
  937. }
  938. void MainWindow::Test_EventLog()
  939. {
  940. {
  941. for (int i = 0; i < 100; ++i) {
  942. QString str = QString(("我是第%1串字符串字符串字符串字-------符串字符串"
  943. "字符串字-------符串字符串字串字-------符符串字符"
  944. "串字符串串字-------符字串字符字串字符字串字符字串"
  945. "字符字串字符字串字-------符符串字串字-------符符"
  946. "串字符串字串字-------符符串字符串字符串")).arg(i);
  947. QtMessageInfo info{ (MessageType)(int)(i % int(MsgTypeMax)) , str,0, 0 };
  948. InsertConsole(info);
  949. }
  950. }
  951. }
  952. EntityInfo MainWindow::GetEntityInfoByRowIndex(int row)
  953. {
  954. if (row == -1)
  955. return (EntityInfo{ "", Manual, NoStart, 0, "" });
  956. return EntityInfo{ ui->tableWidgetEntities->item(row, ENTITY_COLUMN_NAME)->text(), MappingString2StartType(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()),
  957. MappingString2Status(ui->tableWidgetEntities->item(row, ENTITY_COLUMN_STATUS)->text()),
  958. ui->tableWidgetEntities->item(row, ENTITY_COLUMN_PID)->text().toInt(), ui->tableWidgetEntities->item(row, ENTITY_COLUMN_VERSION)->text() };
  959. }
  960. EntityInfo MainWindow::GetCurrentSelectedEntity()
  961. {
  962. const QTableWidgetItem* currentItem = ui->tableWidgetEntities->currentItem();
  963. if (currentItem) {
  964. auto item = GetEntityInfoByRowIndex(currentItem->row());
  965. return item;
  966. }
  967. return GetEntityInfoByRowIndex(-1);
  968. }
  969. void MainWindow::AddEntityEntry(const EntityInfo& entityInst)
  970. {
  971. const int currCows = ui->tableWidgetEntities->rowCount();
  972. ui->tableWidgetEntities->insertRow(currCows);
  973. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_NAME, new QTableWidgetItem(entityInst.entityName));
  974. //ui->tableWidgetEntities->setItem(currCows, 1, new QTableWidgetItem(MappingStartType2String(entityInst.startType)));
  975. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_STATUS, new QTableWidgetItem(MappingSatus2String(entityInst.state)));
  976. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_PID, new QTableWidgetItem(QString::number(entityInst.pid)));
  977. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_VERSION, new QTableWidgetItem(entityInst.version));
  978. if (entityInst.state == Starting || entityInst.state == Idle) {
  979. QDateTime currentTime = QDateTime::currentDateTime();
  980. QString currentTimeStr = currentTime.toString("MM-dd-hh:mm:ss.zzz");
  981. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_BOOTTIME, new QTableWidgetItem(currentTimeStr));
  982. } else {
  983. ui->tableWidgetEntities->setItem(currCows, ENTITY_COLUMN_BOOTTIME, new QTableWidgetItem("未知"));
  984. }
  985. mTotalEntityCount++;
  986. if (entityInst.state == Idle)
  987. mIdleEntityCount++;
  988. UpdateEntityStatistics();
  989. UpdateItemBackgroundColor(currCows, entityInst.state);
  990. }
  991. void MainWindow::UpdateItemBackgroundColor(int row, EntityState state)
  992. {
  993. const int columnCount = ui->tableWidgetEntities->columnCount();
  994. auto curColor = MappingStatus2Color(state);
  995. qDebug() << "uptate row background color" << endl;
  996. #if 0
  997. for (int col = 0; col < columnCount; ++col) {
  998. QTableWidgetItem* item = ui->tableWidgetEntities->item(row, col);
  999. item->setBackground(QBrush(curColor));
  1000. //QPalette palette = item->palette();
  1001. //palette.setBrush(QPalette::Base, curColor);
  1002. //item->setPalette(palette);
  1003. }
  1004. #else
  1005. setRowBackground(QBrush(curColor), ui->tableWidgetEntities->model(), row);
  1006. #endif
  1007. }
  1008. void MainWindow::Test_EntityList()
  1009. {
  1010. AddEntityEntry(EntityInfo{ "MobileDial", Manual, Idle, 123, "V1.2.3" });
  1011. AddEntityEntry(EntityInfo{ "IEBrowser", Manual, NoStart, 123, "V1.2.3" });
  1012. AddEntityEntry(EntityInfo{ "Browser", Manual, Lost, 123, "V1.2.3" });
  1013. AddEntityEntry(EntityInfo{ "HelloClient", Manual, Starting, 123, "V1.2.3" });
  1014. AddEntityEntry(EntityInfo{ "HelloService", Manual, Busy, 123, "V1.2.3" });
  1015. AddEntityEntry(EntityInfo{ "PortbleScanner", Manual, Pause, 123, "V1.2.3" });
  1016. AddEntityEntry(EntityInfo{ "HealthManager", Manual, UnLoading, 123, "V1.2.3" });
  1017. AddEntityEntry(EntityInfo{ "MediaController", Manual, Close, 123, "V1.2.3" });
  1018. AddEntityEntry(EntityInfo{ "GPIO", Manual, Killed, 123, "V1.2.3" });
  1019. AddEntityEntry(EntityInfo{ "CardIssuer", Manual, Passed, 123, "V1.2.3" });
  1020. AddEntityEntry(EntityInfo{ "DeviceSwitch", Manual, Failed, 123, "V1.2.3" });
  1021. if (-1 != FindEntityRowIndex("NoExist")) {
  1022. QMessageBox::warning(this, "", "NoExist", QMessageBox::Ok);
  1023. }
  1024. if (1 == FindEntityRowIndex("MobileDial")) {
  1025. QMessageBox::warning(this, "", "NoExist", QMessageBox::Ok);
  1026. }
  1027. }
  1028. bool MainWindow::LoadPlguins()
  1029. {
  1030. return false;
  1031. }
  1032. void MainWindow::LoadCustomPlguins()
  1033. {
  1034. #ifndef WITH_QT
  1035. static bool sw = false;
  1036. if (!sw) {
  1037. this->setWindowState(Qt::WindowMinimized);
  1038. } else {
  1039. this->setWindowState((this->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
  1040. }
  1041. sw = !sw;
  1042. #else
  1043. bool result = LoadPlguins();
  1044. if (result) {
  1045. }
  1046. #endif
  1047. }
  1048. void MainWindow::EntityItemContextMenu(QPoint pos)
  1049. {
  1050. auto index = ui->tableWidgetEntities->indexAt(pos);
  1051. if (index.isValid()) {
  1052. mEntityPopMenu->exec(QCursor::pos()); // 菜单出现的位置为当前鼠标的位置
  1053. }
  1054. }
  1055. void MainWindow::InitEntitiesView()
  1056. {
  1057. ui->labelEntCalculate->setText("");
  1058. ui->tableWidgetEntities->setColumnCount(MAX_ENTITY_LIST_COLUMN);
  1059. QStringList header;
  1060. header << "名称" << "状态" << "进程号" << "版本" << "最近启动时间";
  1061. ui->tableWidgetEntities->setHorizontalHeaderLabels(header);
  1062. ui->tableWidgetEntities->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
  1063. ui->tableWidgetEntities->setEditTriggers(QAbstractItemView::NoEditTriggers);
  1064. ui->tableWidgetEntities->setSelectionBehavior(QAbstractItemView::SelectRows);
  1065. ui->tableWidgetEntities->setSelectionMode(QAbstractItemView::SingleSelection);
  1066. //ui->tableWidgetEntities->setSelectionModel(mEntitySelectedModel);
  1067. ui->tableWidgetEntities->verticalHeader()->hide();
  1068. ui->tableWidgetEntities->resizeColumnToContents(1);
  1069. ui->tableWidgetEntities->horizontalHeader()->setStretchLastSection(true);
  1070. ui->tableWidgetEntities->horizontalHeader()->setVisible(true);
  1071. ui->tableWidgetEntities->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignVCenter);
  1072. ui->tableWidgetEntities->setStyleSheet("selection-background-color:#1E90FF;");
  1073. connect(ui->tableWidgetEntities, SIGNAL(itemSelectionChanged()), this, SLOT(EntitySelectionChanged()));
  1074. /*
  1075. ui->tableWidgetEntities->setContextMenuPolicy(Qt::CustomContextMenu);
  1076. mEntityPopMenu = new QMenu(ui->tableWidgetEntities);
  1077. QAction *actionUpdateInfo = new QAction();
  1078. QAction *actionDelInfo = new QAction();
  1079. actionUpdateInfo ->setText(QString("修改"));
  1080. actionDelInfo ->setText(QString("删除"));
  1081. mEntityPopMenu->addAction(actionUpdateInfo);
  1082. mEntityPopMenu->addAction(actionDelInfo);
  1083. connect(ui->tableWidgetEntities, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(EntityItemContextMenu(QPoint)));
  1084. */
  1085. mEntityStateChangeReminder = new QTimer(this);
  1086. mEntityStateChangeReminder->setSingleShot(true);
  1087. //connect(mEntityStateChangeReminder, SIGNAL(timeout()),this, SLOT(RemindEntityStateChange()));
  1088. }
  1089. void MainWindow::InitStatusBar()
  1090. {
  1091. mToolsTip = new QLabel("", this);
  1092. QFont ft;
  1093. ft.setPointSize(10);
  1094. mToolsTip->setFont(ft);
  1095. QPalette pa;
  1096. pa.setColor(QPalette::WindowText, QColor(105, 105, 105));
  1097. mToolsTip->setPalette(pa);
  1098. mToolsTip->setStyleSheet("QLabel {padding: 0px 1px 2px 2px;}");
  1099. statusBar()->addPermanentWidget(mToolsTip);
  1100. TimeDateTimer* timer = new TimeDateTimer(this);
  1101. timer->Start(1000);
  1102. //mStatusLabel = new MLabel(this);
  1103. //mStatusLabel->setStyleSheet("QLabel {padding: -10px 2px 2px 1px;}");
  1104. //statusBar()->addWidget(mStatusLabel);
  1105. }
  1106. void MainWindow::TimeUpdate(const QString& timeStr)
  1107. {
  1108. //qDebug() << "enter TimeUpdate" << endl;
  1109. mToolsTip->setText(timeStr);
  1110. }
  1111. void MainWindow::ShowStatusMessage(QString message, int messageType)
  1112. {
  1113. Q_UNUSED(messageType);
  1114. //statusBar()->setStyleSheet("color:green");
  1115. QFontMetrics fontMetrics(statusBar()->font());
  1116. int fontSize = fontMetrics.width(message);
  1117. if (fontSize > statusBar()->width()) {
  1118. message = fontMetrics.elidedText(message, Qt::ElideRight, statusBar()->width());
  1119. }
  1120. statusBar()->showMessage(message);
  1121. //mStatusLabel->setText(message);
  1122. }
  1123. void MainWindow::OnTrayIconActivated(QSystemTrayIcon::ActivationReason activeRson)
  1124. {
  1125. switch (activeRson) {
  1126. // 单击托盘显示窗口
  1127. case QSystemTrayIcon::Trigger:
  1128. {
  1129. showNormal();
  1130. raise();
  1131. activateWindow();
  1132. break;
  1133. }
  1134. // 双击
  1135. case QSystemTrayIcon::DoubleClick:
  1136. {
  1137. // ...
  1138. break;
  1139. }
  1140. default:
  1141. break;
  1142. }
  1143. }
  1144. void MainWindow::messageClicked()
  1145. {
  1146. #ifndef WITH_QT
  1147. QMessageBox::information(nullptr, tr("Systray"),
  1148. tr("Sorry, I already gave what help I could.\n"
  1149. "Maybe you should try asking a human?"));
  1150. #endif
  1151. }
  1152. void MainWindow::InitSystemTrayIcon()
  1153. {
  1154. if (QSystemTrayIcon::supportsMessages() && mSicon == nullptr) {
  1155. mSicon = new QSystemTrayIcon(this);
  1156. QMenu* menusystemTray = new QMenu(this);
  1157. menusystemTray->addAction(tr("Show/Hide"));
  1158. menusystemTray->addAction(tr("About"));
  1159. menusystemTray->addAction(tr("Quit"));
  1160. mSicon->setIcon(QIcon(":/res/FavIcon.ico"));
  1161. mSicon->setToolTip(QString::fromUtf8("RVC Terminal Manager"));
  1162. mSicon->setContextMenu(menusystemTray);
  1163. connect(mSicon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(OnTrayIconActivated(QSystemTrayIcon::ActivationReason)));
  1164. connect(mSicon, &QSystemTrayIcon::messageClicked, this, &MainWindow::messageClicked);
  1165. mSicon->show();
  1166. }
  1167. }
  1168. void MainWindow::Note(QString info, NoteSrcType srcType, QString srcEntity, bool bForce)
  1169. {
  1170. qDebug() << "Note: " << srcEntity << " " << info << endl;
  1171. #ifdef WITH_QT
  1172. if (mSicon && (bForce || CanDisturb())) {
  1173. if (srcEntity.isEmpty()) srcEntity = RVC_TITLE_STRING;
  1174. int showDelayTime = 10000;
  1175. if (srcType == BootStage) {
  1176. showDelayTime = 15000;
  1177. }
  1178. QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Critical);
  1179. mSicon->showMessage(srcEntity, info, msgIcon, showDelayTime);
  1180. }
  1181. #endif
  1182. }
  1183. void MainWindow::closeEvent(QCloseEvent* event)
  1184. {
  1185. showMinimized();
  1186. event->ignore();
  1187. }
  1188. namespace
  1189. {
  1190. QString CoverWithTimePrefix(QString content)
  1191. {
  1192. QDateTime time = QDateTime::currentDateTime();
  1193. QString buffer = time.toString("[hh:mm:ss]");
  1194. QString result = QString("%1 %2").arg(buffer).arg(content);
  1195. return result;
  1196. }
  1197. }
  1198. void MainWindow::ReceiveMessage(const QtMessageInfo* message)
  1199. {
  1200. if (!InsertConsole(*message)) {
  1201. QBaseListWidgetItem* item = new QConsoleListWidgetItem(CoverWithTimePrefix(message->content));
  1202. item->AppentToWidget(ui->listWidgetEventLog);
  1203. }
  1204. }
  1205. void MainWindow::ReceiveEntityVariant(QVariant info)
  1206. {
  1207. QEntityActiveInfo entityInfo = info.value<QEntityActiveInfo>();
  1208. int localEntityIndex = -1;
  1209. for (int i = 0; i < mBootEntitiesInfo.size(); ++i) {
  1210. if (mBootEntitiesInfo.at(i).entityName == entityInfo.entityName) {
  1211. localEntityIndex = i;
  1212. break;
  1213. }
  1214. }
  1215. if (localEntityIndex != -1) {
  1216. if (mBootEntitiesInfo[localEntityIndex].entityState != entityInfo.entityState) {
  1217. const auto currState = entityInfo.entityState;
  1218. mBootEntitiesInfo[localEntityIndex].entityState = currState;
  1219. TriggerEntityState(entityInfo.entityName, currState, entityInfo.entityPID);
  1220. }
  1221. } else {
  1222. EntityBootInfo newEntityInfo;
  1223. newEntityInfo.entityName = entityInfo.entityName;
  1224. newEntityInfo.entityState = entityInfo.entityState;
  1225. mBootEntitiesInfo.push_back(newEntityInfo);
  1226. AddEntityEntry(EntityInfo{ entityInfo.entityName, Manual,
  1227. entityInfo.entityState, entityInfo.entityPID, entityInfo.entityVerStr });
  1228. }
  1229. }
  1230. void MainWindow::ReceiveCustomOperatResult(int action, int result, const QString& message)
  1231. {
  1232. qDebug() << "deal with custom operation result: " << message << " result " << result << endl;
  1233. }
  1234. void MainWindow::ReceiveOperatResult(int action, int result, const QString& message)
  1235. {
  1236. qDebug() << "deal with operation result: " << message << " result " << result << endl;
  1237. for (int i = 0; i < mBootEntitiesInfo.size(); ++i) {
  1238. if (mBootEntitiesInfo.at(i).entityName == message) {
  1239. const auto& entityInfo = mBootEntitiesInfo.at(i);
  1240. (new EntityStateRecoverTimer(this, entityInfo.entityName, entityInfo.entityState));
  1241. TriggerEntityState(entityInfo.entityName, result == 0 ? Passed : Failed, 0);
  1242. break;
  1243. }
  1244. }
  1245. }
  1246. void MainWindow::UpdateEntityStatistics()
  1247. {
  1248. QString text = QString("(正在运行%1个模块,其中%2个正常)").arg(mTotalEntityCount).arg(mIdleEntityCount);
  1249. qDebug() << mTotalEntityCount << " " << mIdleEntityCount;
  1250. qDebug() << text;
  1251. ui->labelEntCalculate->setText(text);
  1252. }
  1253. void MainWindow::NotifyLogMessage(MessageType type, const QString& title, const QString& message)
  1254. {
  1255. QString contentMessage = message;
  1256. QJsonParseError parseError;
  1257. QJsonDocument jsonDoc = QJsonDocument::fromJson(message.toUtf8(), &parseError);
  1258. if (parseError.error == QJsonParseError::NoError) {
  1259. QJsonObject jsonObject = jsonDoc.object();
  1260. if (jsonObject.contains(QStringLiteral("errmsg"))) {
  1261. contentMessage = jsonObject["errmsg"].toString();
  1262. }
  1263. }
  1264. if (CanDisturb()) {
  1265. switch (type) {
  1266. case TextNotifyInfo:
  1267. QMessageBox::information(this, title, contentMessage);
  1268. break;
  1269. case TextNotifyWarn:
  1270. QMessageBox::warning(this, title, contentMessage);
  1271. break;
  1272. case TextNotifyError:
  1273. QMessageBox::critical(this, title, contentMessage);
  1274. break;
  1275. default:
  1276. break;
  1277. }
  1278. } else {
  1279. ShowStatusMessage(contentMessage, type);
  1280. }
  1281. }
  1282. static bool GetInterestPointWithRegex(const QString& origin, QString& entiName, QString& content)
  1283. {
  1284. 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]+)\\)$");
  1285. const int pos = rx.indexIn(origin);
  1286. if (pos > -1) {
  1287. entiName = rx.cap(1);
  1288. content = rx.cap(3);
  1289. QString systemCode = rx.cap(4);
  1290. QString userCode = rx.cap(5);
  1291. return true;
  1292. }
  1293. return false;
  1294. }
  1295. bool MainWindow::InsertConsole(const QtMessageInfo& message)
  1296. {
  1297. QString content = message.content; //FakeUnicodeToUnicode(message.content);
  1298. bool dealed = true;
  1299. if (message.type == TextNormal || message.type == TextEvent) {
  1300. QBaseListWidgetItem* item = new QConsoleListWidgetItem(CoverWithTimePrefix(content));
  1301. item->AppentToWidget(ui->listWidgetEventLog);
  1302. } else if (message.type == TextWarn) {
  1303. QBaseListWidgetItem* item = new QLightWarnListWidgetItem(CoverWithTimePrefix(content));
  1304. item->AppentToWidget(ui->listWidgetEventLog);
  1305. } else if (message.type == TextError) {
  1306. QBaseListWidgetItem* item = new QLightErrorListWidgetItem(CoverWithTimePrefix(content));
  1307. item->AppentToWidget(ui->listWidgetEventLog);
  1308. } else if (message.type == TextFatal || message.type == TextBlock
  1309. || (message.type >= TextNotifyInfo && message.type <= TextNotifyError)) {
  1310. QString entityName;
  1311. const int existIdx = content.indexOf(":][:");
  1312. if (-1 != existIdx) {
  1313. entityName = content.mid(0, existIdx);
  1314. content = content.mid(existIdx + QString(":][:").length());
  1315. }
  1316. #ifndef WITH_QT
  1317. QBaseListWidgetItem* item2 = new QTipErrorListWidgetItem(CoverWithTimePrefix(content));
  1318. item2->AppentToWidget(ui->listWidgetFatalLog);
  1319. #endif
  1320. if (message.type == TextFatal || message.type == TextBlock) {
  1321. if (-1 == existIdx) { GetInterestPointWithRegex(content, entityName, content); }
  1322. #ifndef NDEBUG
  1323. Note(content, BootStage, entityName, true);
  1324. #endif //NDEBUG
  1325. } else {
  1326. #ifdef WITH_QT
  1327. NotifyLogMessage(message.type, entityName, content);
  1328. #endif
  1329. }
  1330. } else {
  1331. dealed = false;
  1332. }
  1333. return dealed;
  1334. }
  1335. void MainWindow::ReceiveMessageVariant(QVariant info)
  1336. {
  1337. QtMessageInfo message = info.value<QtMessageInfo>();
  1338. if (InsertConsole(message)) {
  1339. //empty
  1340. } else if (message.type == ModBootInfo) { //entity boot info
  1341. if (message.content.length() == 0 || message.param1 > Failed) {
  1342. return;
  1343. }
  1344. int localEntityIndex = -1;
  1345. for (int i = 0; i < mBootEntitiesInfo.size(); ++i) {
  1346. if (mBootEntitiesInfo.at(i).entityName == message.content) {
  1347. localEntityIndex = i;
  1348. break;
  1349. }
  1350. }
  1351. if (localEntityIndex != -1) {
  1352. if (mBootEntitiesInfo[localEntityIndex].entityState != message.param1) {
  1353. // const auto previousState = mBootEntitiesInfo[localEntityIndex].entityState;
  1354. const auto currState = static_cast<EntityState>(message.param1);
  1355. mBootEntitiesInfo[localEntityIndex].entityState = currState;
  1356. TriggerEntityState(message.content, currState, 0);
  1357. }
  1358. } else {
  1359. EntityBootInfo newEntityInfo;
  1360. newEntityInfo.entityName = message.content;
  1361. newEntityInfo.entityState = static_cast<EntityState>(message.param1);
  1362. mBootEntitiesInfo.push_back(newEntityInfo);
  1363. AddEntityEntry(EntityInfo{ message.content, Manual, static_cast<EntityState>(message.param1), 123, "V1.2.3" });
  1364. }
  1365. } else if (message.type == ModStartupInfo) {
  1366. //ShowMessage(QString::fromLocal8Bit(message.content), message.type);
  1367. ShowStatusMessage(message.content, message.type);
  1368. } else if (message.type == DisplayShow) {
  1369. this->setWindowState((this->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
  1370. } else if (message.type == DisplayHide) {
  1371. this->setWindowState(Qt::WindowMinimized);
  1372. } else if (message.type == StageChangeInfo) {
  1373. const bool oldSilent = mSilent;
  1374. if (message.param1 == FRAMEWORK_STATE_RUNNING
  1375. || message.param1 == FRAMEWORK_STATE_SERVING
  1376. || message.param1 == FRAMEWORK_STATE_NOTDISTURB
  1377. || message.param1 == FRAMEWORK_STATE_NOCONFIG) {
  1378. mSilent = true;
  1379. } else {
  1380. mSilent = false;
  1381. }
  1382. if (mSilent != oldSilent) {
  1383. OnSilentStateChange(mSilent);
  1384. }
  1385. }
  1386. }
  1387. bool MainWindow::CanDisturb() const
  1388. {
  1389. if (!mSilent) {
  1390. return true;
  1391. }
  1392. Qt::WindowStates states = this->windowState();
  1393. if (!(states & Qt::WindowMinimized) && (states & Qt::WindowActive)) {
  1394. return true;
  1395. }
  1396. return false;
  1397. }
  1398. void MainWindow::OnSilentStateChange(bool beSilent)
  1399. {
  1400. }
  1401. void MainWindow::InitFloatWidget()
  1402. {
  1403. QDesktopWidget* desk = QApplication::desktop();
  1404. QRect rect = desk->screenGeometry(desk->primaryScreen());
  1405. const int wd = rect.width();
  1406. const int ht = rect.height();
  1407. mFloatWidget = new Widget();
  1408. mFloatWidget->show();
  1409. }
  1410. MainWindow::~MainWindow()
  1411. {
  1412. delete ui;
  1413. }
  1414. void RichTimer::HandleTimeout(bool toStop)
  1415. {
  1416. mTimes++;
  1417. mWin->RemindEntityStateChangeWith(mEntityName, toStop ? true : !(mTimes % 2));
  1418. if (toStop) {
  1419. killTimer(mTimerID);
  1420. delete this;
  1421. }
  1422. }
  1423. void EntityStateRecoverTimer::HandleTimeout()
  1424. {
  1425. qDebug() << "reset entity state to " << MappingSatus2String(mState) << endl;
  1426. mWin->TriggerEntityState(mEntityName, mState, -1, false);
  1427. killTimer(mTimerID);
  1428. delete this;
  1429. }
  1430. void TimeDateTimer::Start(int interval)
  1431. {
  1432. mTimer->start(interval);
  1433. connect(mTimer, SIGNAL(timeout()), this, SLOT(HandleTimeout()));
  1434. }
  1435. void TimeDateTimer::Stop()
  1436. {
  1437. mTimer->stop();
  1438. }
  1439. void TimeDateTimer::HandleTimeout()
  1440. {
  1441. mSeconds++;
  1442. if (mSeconds == 60) {
  1443. mMinutes++;
  1444. mSeconds = 0;
  1445. }
  1446. if (mMinutes == 60) {
  1447. mHours++;
  1448. mMinutes = 0;
  1449. }
  1450. if (mHours == 24) {
  1451. mDays++;
  1452. mHours = 0;
  1453. }
  1454. mWin->TimeUpdate(GetCurrentRunTimeString());
  1455. }