mainwindow.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. #include "mainwindow.h"
  2. #include "database_manager/databasemodule.h"
  3. #include "daemon/daemon_client.h"
  4. #include "daemon/daemon_connection_dialog.h"
  5. #include "daemon/daemon_message_flow_widget.h"
  6. #include "api/SoftBusAPI.h"
  7. #include "settings/settings_dialog.h"
  8. #include "toolbar/toolbar.h"
  9. #include "view_serial/serialmodule.h"
  10. #include "utils/logging.h"
  11. #include <QAction>
  12. #include <QCloseEvent>
  13. #include <QDockWidget>
  14. #include <QHBoxLayout>
  15. #include <QJsonDocument>
  16. #include <QJsonObject>
  17. #include <QLabel>
  18. #include <QMenu>
  19. #include <QMenuBar>
  20. #include <QMessageBox>
  21. #include <QSettings>
  22. #include <QShortcut>
  23. #include <QStackedWidget>
  24. #include <QStatusBar>
  25. #include <QToolBar>
  26. #include <QVBoxLayout>
  27. MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { createUI(); }
  28. void MainWindow::createUI() {
  29. // 创建菜单栏
  30. createMenuBar();
  31. // 创建主布局
  32. QWidget *centralWidget = new QWidget(this);
  33. QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
  34. // 界面设置
  35. setWindowTitle("软件总线");
  36. setWindowIcon(QIcon(":/qrc/icons/ads_icon.svg"));
  37. setUnifiedTitleAndToolBarOnMac(true);
  38. setDockNestingEnabled(true);
  39. setAnimated(true);
  40. setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
  41. setDockOptions(QMainWindow::AllowTabbedDocks | QMainWindow::AnimatedDocks |
  42. QMainWindow::VerticalTabs);
  43. setStatusBar(new QStatusBar(this));
  44. setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
  45. setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
  46. setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  47. setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
  48. setMinimumSize(800, 600);
  49. setMaximumSize(1600, 1200);
  50. // 创建页面堆栈
  51. m_pageStack = new QStackedWidget(this);
  52. mainLayout->addWidget(m_pageStack);
  53. centralWidget->setLayout(mainLayout);
  54. setCentralWidget(centralWidget);
  55. // 先设置守护进程状态(必须在创建模块之前,因为模块可能会初始化 API)
  56. setupDaemonStatus();
  57. // 创建工具栏和页面(在守护进程设置之后)
  58. createHomeToolbar();
  59. createSerialToolbar();
  60. createDatabaseToolbar();
  61. createSettingsToolbar();
  62. createHelpToolbar();
  63. // 默认显示主界面
  64. switchToPage(1);
  65. // 设置快捷键
  66. setupShortcuts();
  67. // 链接信号槽
  68. connectSignals();
  69. // 创建状态栏
  70. this->statusBar()->showMessage("就绪");
  71. }
  72. void MainWindow::createMenuBar() {
  73. // 创建菜单栏
  74. QMenuBar *menuBar = new QMenuBar(this);
  75. setMenuBar(menuBar);
  76. // 视图菜单
  77. QMenu *viewMenu = menuBar->addMenu("视图");
  78. QAction *homeAction =
  79. viewMenu->addAction(QIcon(":/qrc/icons/home.png"), "主界面");
  80. QAction *serialAction =
  81. viewMenu->addAction(QIcon(":/qrc/icons/serial.png"), "串口");
  82. QAction *databaseAction =
  83. viewMenu->addAction(QIcon(":/qrc/icons/grid_on.svg"), "数据库");
  84. QAction *settingsAction =
  85. viewMenu->addAction(QIcon(":/qrc/icons/settings.png"), "设置");
  86. QAction *helpAction =
  87. viewMenu->addAction(QIcon(":/qrc/icons/help.png"), "帮助");
  88. // 连接视图菜单的切换功能
  89. connect(homeAction, &QAction::triggered, this, [this]() { switchToPage(0); });
  90. connect(serialAction, &QAction::triggered, this,
  91. [this]() { switchToPage(1); });
  92. connect(databaseAction, &QAction::triggered, this,
  93. [this]() { switchToPage(2); });
  94. connect(settingsAction, &QAction::triggered, this,
  95. [this]() { switchToPage(3); });
  96. connect(helpAction, &QAction::triggered, this, [this]() { switchToPage(4); });
  97. // 文件菜单
  98. QMenu *fileMenu = menuBar->addMenu("文件");
  99. QAction *newAction =
  100. fileMenu->addAction(QIcon(":/qrc/icons/new.png"), "新建");
  101. QAction *openAction =
  102. fileMenu->addAction(QIcon(":/qrc/icons/open.png"), "打开");
  103. QAction *saveAction =
  104. fileMenu->addAction(QIcon(":/qrc/icons/save.png"), "保存");
  105. fileMenu->addSeparator();
  106. QAction *exitAction =
  107. fileMenu->addAction(QIcon(":/qrc/icons/exit.png"), "退出");
  108. // 编辑菜单
  109. QMenu *editMenu = menuBar->addMenu("编辑");
  110. QAction *undoAction =
  111. editMenu->addAction(QIcon(":/qrc/icons/undo.png"), "撤销");
  112. QAction *redoAction =
  113. editMenu->addAction(QIcon(":/qrc/icons/redo.png"), "重做");
  114. editMenu->addSeparator();
  115. QAction *cutAction =
  116. editMenu->addAction(QIcon(":/qrc/icons/cut.png"), "剪切");
  117. QAction *copyAction =
  118. editMenu->addAction(QIcon(":/qrc/icons/copy.png"), "复制");
  119. QAction *pasteAction =
  120. editMenu->addAction(QIcon(":/qrc/icons/paste.png"), "粘贴");
  121. // 帮助菜单
  122. QMenu *helpMenu = menuBar->addMenu("帮助");
  123. QAction *helpDocAction =
  124. helpMenu->addAction(QIcon(":/qrc/icons/help.png"), "帮助文档");
  125. QAction *aboutAction =
  126. helpMenu->addAction(QIcon(":/qrc/icons/about.png"), "关于");
  127. QAction *updateAction =
  128. helpMenu->addAction(QIcon(":/qrc/icons/update.png"), "检查更新");
  129. connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout);
  130. // 连接退出菜单项,真正退出应用
  131. connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
  132. }
  133. void MainWindow::createHomeToolbar() {
  134. // 创建主界面工具栏
  135. Toolbar *homeToolbar = new Toolbar("主工具栏", this);
  136. addToolBar(Qt::TopToolBarArea, homeToolbar);
  137. homeToolbar->hide();
  138. // 添加按钮
  139. homeToolbar->addAction(QIcon(":/qrc/icons/new.png"), "新建");
  140. homeToolbar->addAction(QIcon(":/qrc/icons/open.png"), "打开");
  141. homeToolbar->addAction(QIcon(":/qrc/icons/save.png"), "保存");
  142. homeToolbar->addAction(QIcon(":/qrc/icons/print.png"), "打印");
  143. // 创建主界面页面
  144. QLabel *homePage = new QLabel("<center><h1>主界面</h1></center>", this);
  145. homePage->setAlignment(Qt::AlignCenter);
  146. // 添加到堆栈
  147. m_toolbars.append(homeToolbar);
  148. m_pageStack->addWidget(homePage);
  149. }
  150. void MainWindow::createSerialToolbar() {
  151. if (!m_serialModule) {
  152. m_serialModule = new SerialModule(this, this);
  153. }
  154. if (Toolbar *serialToolbar = m_serialModule->toolbar()) {
  155. addToolBar(Qt::TopToolBarArea, serialToolbar);
  156. serialToolbar->hide();
  157. m_toolbars.append(serialToolbar);
  158. }
  159. if (QWidget *serialPage = m_serialModule->pageWidget()) {
  160. m_serialPageIndex = m_pageStack->addWidget(serialPage);
  161. }
  162. }
  163. void MainWindow::createDatabaseToolbar() {
  164. if (!m_databaseModule) {
  165. m_databaseModule = new DatabaseModule(this, this);
  166. }
  167. if (Toolbar *databaseToolbar = m_databaseModule->toolbar()) {
  168. addToolBar(Qt::TopToolBarArea, databaseToolbar);
  169. databaseToolbar->hide();
  170. m_toolbars.append(databaseToolbar);
  171. }
  172. if (QWidget *databasePage = m_databaseModule->pageWidget()) {
  173. m_databasePageIndex = m_pageStack->addWidget(databasePage);
  174. }
  175. }
  176. void MainWindow::createSettingsToolbar() {
  177. // 创建设置界面工具栏
  178. Toolbar *settingsToolbar = new Toolbar("设置工具栏", this);
  179. addToolBar(Qt::TopToolBarArea, settingsToolbar);
  180. settingsToolbar->hide();
  181. // 添加按钮
  182. QAction *preferencesAction = settingsToolbar->addAction(QIcon(":/qrc/icons/preferences.png"), "首选项");
  183. connect(preferencesAction, &QAction::triggered, this, &MainWindow::showSettingsDialog);
  184. settingsToolbar->addAction(QIcon(":/qrc/icons/theme.png"), "主题");
  185. settingsToolbar->addAction(QIcon(":/qrc/icons/keyboard.png"), "快捷键");
  186. settingsToolbar->addAction(QIcon(":/qrc/icons/plugins.png"), "插件");
  187. // 创建设置界面页面
  188. QLabel *settingsPage = new QLabel("<center><h1>设置界面</h1><p>点击工具栏中的\"首选项\"按钮打开设置对话框</p></center>", this);
  189. settingsPage->setAlignment(Qt::AlignCenter);
  190. // 添加到堆栈
  191. m_toolbars.append(settingsToolbar);
  192. m_pageStack->addWidget(settingsPage);
  193. }
  194. void MainWindow::createHelpToolbar() {
  195. // 创建帮助界面工具栏
  196. Toolbar *helpToolbar = new Toolbar("帮助工具栏", this);
  197. addToolBar(Qt::TopToolBarArea, helpToolbar);
  198. helpToolbar->hide();
  199. // 添加按钮
  200. helpToolbar->addAction(QIcon(":/qrc/icons/help.png"), "帮助文档");
  201. helpToolbar->addAction(QIcon(":/qrc/icons/about.png"), "关于");
  202. helpToolbar->addAction(QIcon(":/qrc/icons/update.png"), "检查更新");
  203. // 创建帮助界面页面
  204. QLabel *helpPage = new QLabel("<center><h1>帮助界面</h1></center>", this);
  205. helpPage->setAlignment(Qt::AlignCenter);
  206. // 添加到堆栈
  207. m_toolbars.append(helpToolbar);
  208. m_pageStack->addWidget(helpPage);
  209. }
  210. /*
  211. function: 返回指定索引的页面
  212. @author: flower
  213. @date: 2025-10-23
  214. @param index 页面索引
  215. @return 无
  216. */
  217. void MainWindow::switchToPage(int index) {
  218. // 隐藏所有工具栏
  219. for (Toolbar *toolbar : m_toolbars) {
  220. toolbar->hide();
  221. }
  222. // 显示当前工具栏
  223. if (index >= 0 && index < m_toolbars.size()) {
  224. m_toolbars[index]->show();
  225. m_pageStack->setCurrentIndex(index);
  226. }
  227. }
  228. /*
  229. function: 设置快捷键
  230. @author: flower
  231. @date: 2025-10-23
  232. @param
  233. @return 无
  234. */
  235. void MainWindow::setupShortcuts() {
  236. // 创建快捷键
  237. QShortcut *homeShortcut = new QShortcut(QKeySequence("Ctrl+1"), this);
  238. QShortcut *serialShortcut = new QShortcut(QKeySequence("Ctrl+2"), this);
  239. QShortcut *databaseShortcut = new QShortcut(QKeySequence("Ctrl+3"), this);
  240. QShortcut *settingsShortcut = new QShortcut(QKeySequence("Ctrl+4"), this);
  241. QShortcut *helpShortcut = new QShortcut(QKeySequence("Ctrl+5"), this);
  242. // 连接快捷键信号
  243. connect(homeShortcut, &QShortcut::activated, this,
  244. [this]() { switchToPage(0); });
  245. connect(serialShortcut, &QShortcut::activated, this,
  246. [this]() { switchToPage(1); });
  247. connect(databaseShortcut, &QShortcut::activated, this,
  248. [this]() { switchToPage(2); });
  249. connect(settingsShortcut, &QShortcut::activated, this,
  250. [this]() { switchToPage(3); });
  251. connect(helpShortcut, &QShortcut::activated, this,
  252. [this]() { switchToPage(4); });
  253. }
  254. /*
  255. function: 链接信号槽
  256. @author: flower
  257. @date: 2021-10-23
  258. @param
  259. @return 无
  260. */
  261. void MainWindow::connectSignals() {
  262. // 连接信号槽
  263. }
  264. void MainWindow::showAbout() {
  265. QMessageBox::about(this, "关于",
  266. "<h2>基于DoDAF的多源数据融合系统总线</h2>"
  267. "<p> </p>"
  268. "<p>版本: 1.0.0</p>"
  269. "<p>© flower </p>");
  270. }
  271. void MainWindow::setupDaemonStatus()
  272. {
  273. // 创建守护进程客户端
  274. m_daemonClient = new DaemonClient(this);
  275. // 连接信号
  276. connect(m_daemonClient, &DaemonClient::daemonStatusChanged,
  277. this, &MainWindow::onDaemonStatusChanged);
  278. connect(m_daemonClient, &DaemonClient::loadInfoUpdated,
  279. this, &MainWindow::onLoadInfoUpdated);
  280. // 加载设置(在初始化 API 之前)
  281. loadSettings();
  282. // 如果设置中启用了守护进程模式,先尝试连接守护进程
  283. // 注意:默认值应该与 loadSettings() 中的默认值一致
  284. // 默认启用守护进程模式,提供更好的资源管理和权限控制
  285. QSettings settings;
  286. bool useDaemonMode = settings.value("daemon/useDaemonMode", true).toBool();
  287. SoftBusAPI* api = SoftBusAPI::instance();
  288. bool connected = false;
  289. if (useDaemonMode) {
  290. // 先尝试启动守护进程(如果未运行)
  291. LOG_INFO() << "守护进程模式已启用,正在启动守护进程客户端服务...";
  292. bool daemonStarted = m_daemonClient->startDaemon();
  293. if (daemonStarted) {
  294. LOG_INFO() << "守护进程客户端服务启动成功,正在连接守护进程服务...";
  295. } else {
  296. LOG_WARNING() << "守护进程启动失败,可能已经运行或无法启动";
  297. }
  298. // 尝试连接守护进程(connectToDaemon 内部也会尝试启动)
  299. connected = m_daemonClient->connectToDaemon();
  300. if (!connected) {
  301. LOG_WARNING() << "守护进程连接失败,弹出对话框询问用户";
  302. // 连接失败,弹出对话框询问是否切换到本地模式
  303. DaemonConnectionDialog dialog(this);
  304. dialog.setErrorMessage(tr("守护进程服务未运行或无法访问。"));
  305. int result = dialog.exec();
  306. if (result == QDialog::Accepted) {
  307. if (dialog.switchToLocalMode()) {
  308. // 用户选择切换到本地模式
  309. useDaemonMode = false;
  310. settings.setValue("daemon/useDaemonMode", false);
  311. settings.sync();
  312. LOG_INFO() << "用户选择切换到本地模式";
  313. } else {
  314. // 用户选择重试,再次尝试启动和连接
  315. LOG_INFO() << "用户选择重试,正在重新启动守护进程...";
  316. daemonStarted = m_daemonClient->startDaemon();
  317. connected = m_daemonClient->connectToDaemon();
  318. if (!connected) {
  319. // 重试仍然失败,自动切换到本地模式
  320. QMessageBox::warning(this,
  321. tr("连接失败"),
  322. tr("重试启动和连接守护进程仍然失败,已自动切换到本地模式。"));
  323. useDaemonMode = false;
  324. settings.setValue("daemon/useDaemonMode", false);
  325. settings.sync();
  326. LOG_WARNING() << "重试仍然失败,自动切换到本地模式";
  327. } else {
  328. // 重试成功
  329. useDaemonMode = true;
  330. LOG_INFO() << "重试启动和连接守护进程成功";
  331. }
  332. }
  333. } else {
  334. // 用户取消,默认切换到本地模式
  335. useDaemonMode = false;
  336. settings.setValue("daemon/useDaemonMode", false);
  337. settings.sync();
  338. LOG_INFO() << "用户取消对话框,切换到本地模式";
  339. }
  340. } else {
  341. // 连接成功,确保使用守护进程模式
  342. useDaemonMode = true;
  343. LOG_INFO() << "守护进程启动并连接成功";
  344. }
  345. } else {
  346. LOG_INFO() << "设置中未启用守护进程模式,使用本地模式";
  347. }
  348. // 根据最终的模式设置初始化 API
  349. // 注意:必须先设置模式,再初始化 API,这样 Manager 才能知道使用哪种模式
  350. LOG_INFO() << "设置API模式:" << (useDaemonMode ? "守护进程模式" : "本地模式");
  351. api->setUseDaemonMode(useDaemonMode);
  352. // 初始化 API(会根据模式创建相应的 Manager)
  353. LOG_INFO() << "正在初始化 SoftBusAPI...";
  354. if (!api->initialize()) {
  355. LOG_WARNING() << "Failed to initialize SoftBusAPI";
  356. return;
  357. }
  358. LOG_INFO() << "SoftBusAPI 初始化成功";
  359. // 如果使用守护进程模式,设置 DaemonClient 到 SoftBusAPI,让硬件操作通过守护进程
  360. if (useDaemonMode) {
  361. LOG_INFO() << "设置 DaemonClient 到 SoftBusAPI";
  362. api->setDaemonClient(m_daemonClient);
  363. // 守护进程连接成功后,启动设备扫描(由守护进程负责扫描)
  364. // 注意:在守护进程模式下,设备扫描由守护进程负责,这里只是通知可以开始查询设备列表
  365. LOG_INFO() << "启动设备扫描(守护进程模式)";
  366. api->startDeviceDiscovery(5000);
  367. } else {
  368. // 本地模式下,立即启动设备扫描
  369. LOG_INFO() << "启动设备扫描(本地模式)";
  370. api->startDeviceDiscovery(5000);
  371. }
  372. // 在状态栏添加状态标签
  373. QStatusBar* statusBar = this->statusBar();
  374. if (statusBar) {
  375. m_statusLabel = new QLabel("核心服务: 未连接", this);
  376. m_loadLabel = new QLabel("负载: --", this);
  377. statusBar->addPermanentWidget(m_statusLabel);
  378. statusBar->addPermanentWidget(m_loadLabel);
  379. // 初始更新
  380. updateDaemonStatus(false, QString());
  381. }
  382. // 创建信息流列表停靠窗口(在守护进程客户端创建之后)
  383. createMessageFlowDock();
  384. // 设置守护进程客户端到信息流组件
  385. if (m_daemonClient && m_messageFlowWidget) {
  386. m_messageFlowWidget->setDaemonClient(m_daemonClient);
  387. }
  388. }
  389. void MainWindow::onDaemonStatusChanged(bool running, const QString& statusJson)
  390. {
  391. updateDaemonStatus(running, statusJson);
  392. // 信息流组件会自动处理状态更新(通过信号连接)
  393. }
  394. void MainWindow::onLoadInfoUpdated(const QString& loadInfoJson)
  395. {
  396. updateLoadInfo(loadInfoJson);
  397. // 信息流组件会自动处理负载信息更新(通过信号连接)
  398. }
  399. void MainWindow::updateDaemonStatus(bool running, const QString& statusJson)
  400. {
  401. if (!m_statusLabel) return;
  402. QString statusText;
  403. QString style;
  404. if (running) {
  405. statusText = "核心服务: 运行中";
  406. style = "color: green; font-weight: bold;";
  407. // 获取进程ID
  408. if (m_daemonClient) {
  409. qint64 pid = m_daemonClient->getPid();
  410. if (pid > 0) {
  411. statusText += QString(" (PID: %1)").arg(pid);
  412. }
  413. }
  414. // 解析状态 JSON 获取详细信息
  415. if (!statusJson.isEmpty()) {
  416. QJsonDocument doc = QJsonDocument::fromJson(statusJson.toUtf8());
  417. if (doc.isObject()) {
  418. QJsonObject obj = doc.object();
  419. int deviceCount = obj["deviceCount"].toInt(0);
  420. int onlineCount = obj["onlineDeviceCount"].toInt(0);
  421. statusText += QString(" | 设备: %1/%2").arg(onlineCount).arg(deviceCount);
  422. }
  423. }
  424. } else {
  425. statusText = "核心服务: 未运行";
  426. style = "color: red; font-weight: bold;";
  427. }
  428. m_statusLabel->setText(statusText);
  429. m_statusLabel->setStyleSheet(style);
  430. }
  431. void MainWindow::updateLoadInfo(const QString& loadInfoJson)
  432. {
  433. if (!m_loadLabel) return;
  434. if (loadInfoJson.isEmpty()) {
  435. m_loadLabel->setText("负载: --");
  436. return;
  437. }
  438. QJsonDocument doc = QJsonDocument::fromJson(loadInfoJson.toUtf8());
  439. if (!doc.isObject()) {
  440. m_loadLabel->setText("负载: --");
  441. return;
  442. }
  443. QJsonObject obj = doc.object();
  444. double messageRate = obj["messageRate"].toDouble(0.0);
  445. qint64 totalMessages = obj["totalMessages"].toVariant().toLongLong();
  446. QString loadText = QString("消息速率: %1 msg/s | 总计: %2")
  447. .arg(messageRate, 0, 'f', 1)
  448. .arg(totalMessages);
  449. m_loadLabel->setText(loadText);
  450. }
  451. void MainWindow::createMessageFlowDock()
  452. {
  453. // 创建信息流列表组件
  454. m_messageFlowWidget = new DaemonMessageFlowWidget(this);
  455. // 创建停靠窗口
  456. QDockWidget* dockWidget = new QDockWidget("守护进程信息流", this);
  457. dockWidget->setWidget(m_messageFlowWidget);
  458. dockWidget->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
  459. dockWidget->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
  460. // 添加到主窗口
  461. addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
  462. // 设置守护进程客户端
  463. if (m_daemonClient) {
  464. m_messageFlowWidget->setDaemonClient(m_daemonClient);
  465. }
  466. // 默认隐藏,可以通过视图菜单显示
  467. dockWidget->hide();
  468. // 添加到视图菜单
  469. QMenuBar* menuBar = this->menuBar();
  470. if (menuBar) {
  471. QMenu* viewMenu = nullptr;
  472. QList<QAction*> actions = menuBar->actions();
  473. for (QAction* action : actions) {
  474. if (action->text() == "视图") {
  475. viewMenu = qobject_cast<QMenu*>(action->menu());
  476. break;
  477. }
  478. }
  479. if (viewMenu) {
  480. QAction* flowAction = viewMenu->addAction("守护进程信息流");
  481. flowAction->setCheckable(true);
  482. flowAction->setChecked(false);
  483. connect(flowAction, &QAction::toggled, dockWidget, &QDockWidget::setVisible);
  484. }
  485. }
  486. }
  487. void MainWindow::loadSettings() {
  488. QSettings settings;
  489. // 默认启用守护进程模式,提供更好的资源管理和权限控制
  490. bool useDaemonMode = settings.value("daemon/useDaemonMode", true).toBool();
  491. SoftBusAPI* api = SoftBusAPI::instance();
  492. if (api) {
  493. api->setUseDaemonMode(useDaemonMode);
  494. LOG_DEBUG() << "加载设置 - 守护进程模式:" << (useDaemonMode ? "启用" : "禁用");
  495. }
  496. }
  497. void MainWindow::showSettingsDialog() {
  498. if (!m_settingsDialog) {
  499. m_settingsDialog = new SettingsDialog(this);
  500. // 设置守护进程客户端,让设置对话框能检查守护进程状态
  501. m_settingsDialog->setDaemonClient(m_daemonClient);
  502. }
  503. // 加载当前设置
  504. m_settingsDialog->loadSettings();
  505. // 显示对话框
  506. if (m_settingsDialog->exec() == QDialog::Accepted) {
  507. // 用户点击了"确定",应用设置
  508. bool useDaemonMode = m_settingsDialog->useDaemonMode();
  509. SoftBusAPI* api = SoftBusAPI::instance();
  510. if (api) {
  511. api->setUseDaemonMode(useDaemonMode);
  512. LOG_DEBUG() << "设置已更新 - 守护进程模式:" << (useDaemonMode ? "启用" : "禁用");
  513. }
  514. }
  515. }
  516. void MainWindow::closeEvent(QCloseEvent *event) {
  517. // 关闭窗口时只是隐藏窗口,不退出应用
  518. // 这样总线核心可以继续在后台运行
  519. hide();
  520. event->ignore(); // 忽略关闭事件,不真正关闭窗口
  521. // 更新状态栏提示
  522. if (statusBar()) {
  523. statusBar()->showMessage("窗口已隐藏,总线核心继续运行中...", 3000);
  524. }
  525. }