Терминальный проект КиберПлат [open source]
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

718 lines
21KB

  1. /* @file Менеджер для работы с новым интерфейсом. */
  2. // Qt
  3. #include <Common/QtHeadersBegin.h>
  4. #include <QtCore/QDir>
  5. #include <QtWidgets/QApplication>
  6. #include <Common/QtHeadersEnd.h>
  7. // SDK
  8. #include <SDK/GUI/IGraphicsBackend.h>
  9. #include <SDK/PaymentProcessor/Core/IEventService.h>
  10. #include <SDK/PaymentProcessor/Core/Event.h>
  11. #include <SDK/PaymentProcessor/Core/EventTypes.h>
  12. #include <SDK/PaymentProcessor/Payment/Step.h>
  13. #include <SDK/PaymentProcessor/Scripting/Core.h>
  14. #include <SysUtils/ISysUtils.h>
  15. // Project
  16. #include "System/IApplication.h"
  17. #include "System/SettingsConstants.h"
  18. #include "Services/ServiceNames.h"
  19. #include "Services/PluginService.h"
  20. #include "Services/TerminalService.h"
  21. #include "Services/GUIService.h"
  22. #include "Services/EventService.h"
  23. #include "Services/IdleScenario.h"
  24. #include "Services/FirmwareUploadScenario.h"
  25. namespace PPSDK = SDK::PaymentProcessor;
  26. namespace CGUIService
  27. {
  28. const int DefaultScreenWidth = 1280;
  29. const int DefaultScreenHeight = 1024;
  30. const int StartDragDistance = 10;
  31. const QString DefaultScenario = "menu";
  32. }
  33. //---------------------------------------------------------------------------
  34. GUIService * GUIService::instance(IApplication * aApplication)
  35. {
  36. try
  37. {
  38. auto core = aApplication->getCore();
  39. if (core->getService(CServices::GUIService))
  40. {
  41. return static_cast<GUIService *>(core->getGUIService());
  42. }
  43. }
  44. catch (PPSDK::ServiceIsNotImplemented)
  45. {
  46. return nullptr;
  47. }
  48. return nullptr;
  49. }
  50. //---------------------------------------------------------------------------
  51. GUIService::GUIService(IApplication * aApplication)
  52. : ILogable(CGUIService::LogName),
  53. mApplication(aApplication),
  54. mPluginService(nullptr),
  55. mEventManager(nullptr),
  56. mScriptingCore(nullptr),
  57. mDisabled(false),
  58. mWidth(0),
  59. mHeight(0)
  60. {
  61. }
  62. //---------------------------------------------------------------------------
  63. GUIService::~GUIService()
  64. {
  65. }
  66. //---------------------------------------------------------------------------
  67. bool GUIService::initialize()
  68. {
  69. // Выводим стандартный заголовок в лог
  70. getLog()->adjustPadding(-99);
  71. getLog()->write(LogLevel::Normal, QString("Initializing GUI Service."));
  72. getLog()->write(LogLevel::Normal, QString("*").repeated(58));
  73. mScriptingCore = new PPSDK::Scripting::Core(mApplication->getCore());
  74. mScriptingCore->setLog(getLog());
  75. mEventManager = mApplication->getCore()->getEventService();
  76. mEventManager->subscribe(this, SLOT(onEvent(const SDK::PaymentProcessor::Event &)));
  77. mCheckTopmostTimer.setInterval(CGUIService::CheckTopmostWindowTimeout);
  78. connect(&mCheckTopmostTimer, SIGNAL(timeout()), this, SLOT(bringToFront()));
  79. // Получаем директорию с файлами интерфейса из настроек.
  80. QString interfacePath = IApplication::toAbsolutePath(mApplication->getSettings().value(CSettings::InterfacePath).toString());
  81. connect(&mGraphicsEngine, SIGNAL(userActivity()), &mScenarioEngine, SLOT(resetTimeout()));
  82. connect(&mGraphicsEngine, SIGNAL(intruderActivity()), SLOT(onIntruderActivity()), Qt::QueuedConnection);
  83. connect(&mGraphicsEngine, SIGNAL(closed()), SLOT(onMainWidgetClosed()));
  84. connect(&mGraphicsEngine, SIGNAL(keyPressed(QString)), SLOT(onKeyPressed(QString)));
  85. mScenarioEngine.injectScriptObject(PPSDK::Scripting::CProxyNames::Core, mScriptingCore);
  86. mScenarioEngine.injectScriptObject<PPSDK::EEventType>(PPSDK::Scripting::CProxyNames::EventType);
  87. mScenarioEngine.injectScriptObject<PPSDK::EPaymentStep>(PPSDK::Scripting::CProxyNames::PaymentStep);
  88. mScenarioEngine.addDirectory(interfacePath);
  89. mScenarioEngine.addDirectory(":/Scenario");
  90. mScenarioEngine.initialize();
  91. mGraphicsEngine.addContentDirectory(interfacePath);
  92. mGraphicsEngine.addContentDirectory(":/GraphicsItems");
  93. mGraphicsEngine.setGraphicsHost(this);
  94. mPluginService = PluginService::instance(mApplication);
  95. loadScriptObjects();
  96. loadBackends();
  97. loadNativeScenarios();
  98. loadAdSources();
  99. QVariantMap unitedSettings;
  100. auto parseIni = [&](const QString & aIniFile)
  101. {
  102. QSettings settings(aIniFile, QSettings::IniFormat);
  103. settings.setIniCodec("UTF-8");
  104. foreach (auto key, settings.allKeys())
  105. {
  106. mConfig.insert(key, settings.value(key));
  107. }
  108. };
  109. // Загружаем настройки интерфейса
  110. parseIni(interfacePath + "/interface.ini");
  111. // Обновляем пользовательскими настройками
  112. parseIni(mApplication->getUserDataPath() + "/user.ini");
  113. mDefaultScenario = mConfig.value("interface/default_scenario").toString();
  114. if (mDefaultScenario.isEmpty())
  115. {
  116. toLog(LogLevel::Warning, QString("Default scenario is not specified. Set scenario name '%1'").arg(CGUIService::DefaultScenario));
  117. mDefaultScenario = CGUIService::DefaultScenario;
  118. }
  119. int display = mConfig.value("interface/display", 0).toInt();
  120. mWidth = mConfig.value("interface/width", CGUIService::DefaultScreenWidth).toInt();
  121. mHeight = mConfig.value("interface/height", CGUIService::DefaultScreenHeight).toInt();
  122. // Установка чувствительности для события mouse drag
  123. qApp->setStartDragDistance(mConfig.value("interface/sensivity", CGUIService::StartDragDistance).toInt());
  124. bool showCursor = mConfig.value("interface/show_mouse_cursor", false).toBool();
  125. bool showDebugInfo = mConfig.value("interface/show_debug_info", false).toBool();
  126. bool useOpengl = mConfig.value("interface/use_opengl", false).toBool();
  127. QVariantMap scenarios = getUiSettings("scenarios");
  128. if (!scenarios.isEmpty())
  129. {
  130. mExternalScenarios.clear();
  131. QStringList handledKeyList;
  132. foreach (QString key, scenarios.keys())
  133. {
  134. mExternalScenarios.insert(scenarios.value(key).toString(), key);
  135. handledKeyList << scenarios.value(key).toString();
  136. }
  137. mGraphicsEngine.addHandledKeys(handledKeyList);
  138. }
  139. if (!mGraphicsEngine.initialize(display, mWidth, mHeight, showCursor, useOpengl, showDebugInfo))
  140. {
  141. LOG(mApplication->getLog(), LogLevel::Error, "Failed to initialize graphics engine.");
  142. // GUI не будет отображаться, но платежная логика продолжит работу.
  143. return true;
  144. }
  145. else
  146. {
  147. // Добавляем сценарий перепрошивки устройств
  148. mScenarioEngine.addScenario(new FirmwareUploadScenario(mApplication));
  149. // Добавляем основной сценарий и запускаем его.
  150. GUI::Scenario * idle = new IdleScenario(mApplication);
  151. mScenarioEngine.addScenario(idle);
  152. #ifndef _DEBUG
  153. // Запускаем проверку окна поверх всех
  154. mCheckTopmostTimer.start();
  155. #endif
  156. mGraphicsEngine.start();
  157. QVariantMap noGui;
  158. noGui.insert("no_gui", mConfig.value("interface/no_gui", false).toBool());
  159. if (!mScenarioEngine.startScenario(idle->getName(), noGui))
  160. {
  161. toLog(LogLevel::Error, "Failed to start idle scenario.");
  162. return false;
  163. }
  164. }
  165. mDisabled = mDisabled || TerminalService::instance(mApplication)->isLocked();
  166. return true;
  167. }
  168. //------------------------------------------------------------------------------
  169. void GUIService::finishInitialize()
  170. {
  171. }
  172. //---------------------------------------------------------------------------
  173. bool GUIService::canShutdown()
  174. {
  175. return mScenarioEngine.canStop();
  176. }
  177. //---------------------------------------------------------------------------
  178. bool GUIService::shutdown()
  179. {
  180. mGraphicsEngine.stop();
  181. mGraphicsEngine.finalize();
  182. mScenarioEngine.finalize();
  183. foreach (SDK::Plugin::IPlugin * plugin, mBackendPluginList)
  184. {
  185. dynamic_cast<SDK::GUI::IGraphicsBackend *>(plugin)->shutdown();
  186. mPluginService->getPluginLoader()->destroyPlugin(plugin);
  187. }
  188. mBackendPluginList.clear();
  189. delete mScriptingCore;
  190. mScriptingCore = nullptr;
  191. mEventManager->unsubscribe(this, SLOT(onEvent(const SDK::PaymentProcessor::Event &)));
  192. disconnect(&mCheckTopmostTimer, SIGNAL(timeout()), this, SLOT(bringToFront()));
  193. disconnect(&mGraphicsEngine, SIGNAL(userActivity()), &mScenarioEngine, SLOT(resetTimeout()));
  194. disconnect(&mGraphicsEngine, SIGNAL(closed()), this, SLOT(onMainWidgetClosed()));
  195. disconnect(&mGraphicsEngine, SIGNAL(keyPressed(const QString &)), this, SLOT(onKeyPressed(const QString &)));
  196. foreach (auto adSource, mAdSourceList)
  197. {
  198. mPluginService->getPluginLoader()->destroyPlugin(dynamic_cast<SDK::Plugin::IPlugin *>(adSource));
  199. }
  200. mAdSourceList.clear();
  201. return true;
  202. }
  203. //---------------------------------------------------------------------------
  204. QString GUIService::getName() const
  205. {
  206. return CServices::GUIService;
  207. }
  208. //---------------------------------------------------------------------------
  209. const QSet<QString> & GUIService::getRequiredServices() const
  210. {
  211. static QSet<QString> requiredServices = QSet<QString>()
  212. << CServices::EventService
  213. << CServices::PluginService
  214. << CServices::FundsService
  215. << CServices::SettingsService
  216. << CServices::TerminalService
  217. << CServices::PrintingService;
  218. return requiredServices;
  219. }
  220. //---------------------------------------------------------------------------
  221. QVariantMap GUIService::getParameters() const
  222. {
  223. return QVariantMap();
  224. }
  225. //---------------------------------------------------------------------------
  226. void GUIService::resetParameters(const QSet<QString> &)
  227. {
  228. }
  229. //---------------------------------------------------------------------------
  230. QStringList GUIService::getInterfacesName() const
  231. {
  232. QStringList result;
  233. result << PPSDK::CInterfaces::ICore
  234. << PPSDK::Scripting::CProxyNames::Core;
  235. result.append(mBackendScenarioObjects.keys());
  236. return result;
  237. }
  238. //---------------------------------------------------------------------------
  239. void * GUIService::getInterface(const QString & aInterface)
  240. {
  241. void * object = nullptr;
  242. if (aInterface == PPSDK::CInterfaces::ICore)
  243. {
  244. object = mApplication->getCore();
  245. }
  246. else if (aInterface == PPSDK::Scripting::CProxyNames::Core)
  247. {
  248. object = mScriptingCore;
  249. }
  250. else if (mBackendScenarioObjects.contains(aInterface))
  251. {
  252. object = mBackendScenarioObjects.value(aInterface).data();
  253. }
  254. return object;
  255. }
  256. //---------------------------------------------------------------------------
  257. void GUIService::onEvent(const SDK::PaymentProcessor::Event & aEvent)
  258. {
  259. switch (aEvent.getType())
  260. {
  261. // Какое-то события сценария.
  262. case PPSDK::EEventType::UpdateScenario:
  263. {
  264. QString signal;
  265. QVariantMap parameters;
  266. if (aEvent.getData().type() == QVariant::String)
  267. {
  268. signal = aEvent.getData().toString();
  269. }
  270. else
  271. {
  272. parameters = aEvent.getData().value<QVariantMap>();
  273. signal = parameters["signal"].toString();
  274. }
  275. // FIXME: нужен другой тип события для попапов.
  276. if (signal == "popup_notify")
  277. {
  278. mGraphicsEngine.popupNotify(signal, parameters);
  279. }
  280. else
  281. {
  282. mScenarioEngine.signalTriggered(signal, parameters);
  283. }
  284. break;
  285. }
  286. case PPSDK::EEventType::StartScenario:
  287. {
  288. // Запуск сценария. Передаем параметрами имя сценария и контекст активации (параметры сценария).
  289. QVariantMap eventData = aEvent.getData().value<QVariantMap>();
  290. if (eventData.contains("name"))
  291. {
  292. QString scenarioName = eventData["name"].toString();
  293. mScenarioEngine.startScenario(scenarioName, eventData);
  294. }
  295. else
  296. {
  297. if (mDefaultScenario != CGUIService::IdleScenarioName)
  298. {
  299. // Пытаемся запустить дефолтный сценарий.
  300. mScenarioEngine.startScenario(mDefaultScenario);
  301. }
  302. else
  303. {
  304. //default_scenario=idle
  305. //idle сценарий уже запущен
  306. }
  307. }
  308. break;
  309. }
  310. case PPSDK::EEventType::StopScenario:
  311. {
  312. mScenarioEngine.stopScenario();
  313. break;
  314. }
  315. case PPSDK::EEventType::StateChanged:
  316. break;
  317. case PPSDK::EEventType::StartGraphics:
  318. #ifndef _DEBUG
  319. // Запускаем проверку окна поверх всех
  320. mCheckTopmostTimer.start();
  321. #endif
  322. mGraphicsEngine.start();
  323. break;
  324. case PPSDK::EEventType::PauseGraphics:
  325. mGraphicsEngine.pause();
  326. mCheckTopmostTimer.stop();
  327. break;
  328. case PPSDK::EEventType::StopGraphics:
  329. mGraphicsEngine.stop();
  330. break;
  331. }
  332. }
  333. //---------------------------------------------------------------------------
  334. void GUIService::onKeyPressed(const QString & aKeyText)
  335. {
  336. QString scenario = mExternalScenarios.value(aKeyText).toString();
  337. if (!scenario.isEmpty())
  338. {
  339. mScenarioEngine.startScenario(scenario);
  340. }
  341. }
  342. //---------------------------------------------------------------------------
  343. void GUIService::disable(bool aDisable)
  344. {
  345. if (mDisabled != aDisable)
  346. {
  347. mDisabled = aDisable;
  348. QVariantMap parameters;
  349. parameters["signal"] = aDisable ? CGUISignals::StopGUI : CGUISignals::StartGUI;
  350. EventService::instance(mApplication)->sendEvent(PPSDK::EEventType::UpdateScenario, parameters);
  351. }
  352. // Каждый раз заново посылаем сигнал на disabled=true, даже если уже заблокирован, т.к. причина блокировки могла измениться
  353. else if (mDisabled)
  354. {
  355. QVariantMap parameters;
  356. parameters["signal"] = CGUISignals::UpdateGUI;
  357. EventService::instance(mApplication)->sendEvent(PPSDK::EEventType::UpdateScenario, parameters);
  358. }
  359. }
  360. //---------------------------------------------------------------------------
  361. void GUIService::onHIDData(const QVariant & aData)
  362. {
  363. // TODO
  364. QVariantMap arguments;
  365. arguments["msisdn"] = aData;
  366. mScenarioEngine.signalTriggered("datapending", arguments);
  367. }
  368. //---------------------------------------------------------------------------
  369. bool GUIService::show(const QString & aScene, const QVariantMap & aParameters)
  370. {
  371. return mGraphicsEngine.show(aScene, aParameters);
  372. }
  373. //---------------------------------------------------------------------------
  374. bool GUIService::showPopup(const QString & aWidget, const QVariantMap & aParameters)
  375. {
  376. return mGraphicsEngine.showPopup(aWidget, aParameters);
  377. }
  378. //---------------------------------------------------------------------------
  379. QVariantMap GUIService::showModal(const QString & aWidget, const QVariantMap & aParameters)
  380. {
  381. return mGraphicsEngine.showModal(aWidget, aParameters);
  382. }
  383. //---------------------------------------------------------------------------
  384. bool GUIService::hidePopup(const QVariantMap & aParameters)
  385. {
  386. return mGraphicsEngine.hidePopup(aParameters);
  387. }
  388. //---------------------------------------------------------------------------
  389. void GUIService::notify(const QString & aEvent, const QVariantMap & aParameters)
  390. {
  391. mGraphicsEngine.notify(aEvent, aParameters);
  392. }
  393. //---------------------------------------------------------------------------
  394. void GUIService::onMainWidgetClosed()
  395. {
  396. mEventManager->sendEvent(PPSDK::Event(PPSDK::EEventType::CloseApplication));
  397. }
  398. //---------------------------------------------------------------------------
  399. void GUIService::onIntruderActivity()
  400. {
  401. auto settings = dynamic_cast<PPSDK::TerminalSettings *>(
  402. mApplication->getCore()->getSettingsService()->getAdapter(PPSDK::CAdapterNames::TerminalAdapter))->getCommonSettings();
  403. auto event = PPSDK::EEventType::OK;
  404. auto message = tr("#penetration_detected");
  405. switch (settings.penetrationEventLevel)
  406. {
  407. case PPSDK::EEventType::Critical:
  408. event = settings.penetrationEventLevel;
  409. message += " #alarm";
  410. if (settings.blockOn(PPSDK::SCommonSettings::Penetration))
  411. {
  412. mEventManager->sendEvent(PPSDK::Event(PPSDK::EEventType::TerminalLock, CGUIService::LogName, message));
  413. }
  414. break;
  415. case PPSDK::EEventType::Warning:
  416. message += " #alarm";
  417. break;
  418. }
  419. mEventManager->sendEvent(PPSDK::Event(event, CGUIService::LogName, message));
  420. }
  421. //---------------------------------------------------------------------------
  422. bool GUIService::isDisabled() const
  423. {
  424. return mDisabled;
  425. }
  426. //---------------------------------------------------------------------------
  427. QRect GUIService::getScreenSize(int aIndex) const
  428. {
  429. return aIndex ? mGraphicsEngine.getDisplayRectangle(aIndex) : QRect(0, 0, mWidth, mHeight);
  430. }
  431. //---------------------------------------------------------------------------
  432. QPixmap GUIService::getScreenshot()
  433. {
  434. return mGraphicsEngine.getScreenshot();
  435. }
  436. //---------------------------------------------------------------------------
  437. QVariantMap GUIService::getUiSettings(const QString & aSection) const
  438. {
  439. QVariantMap result;
  440. foreach (QString key, mConfig.keys())
  441. {
  442. if (!key.contains(aSection))
  443. {
  444. continue;
  445. }
  446. result.insert(key.split("/").last(), mConfig.value(key));
  447. }
  448. return result;
  449. }
  450. //---------------------------------------------------------------------------
  451. void GUIService::loadAdSources()
  452. {
  453. QStringList adSources = mPluginService->getPluginLoader()->getPluginList(QRegExp("PaymentProcessor\\.AdSource\\..*"));
  454. foreach (const QString & source, adSources)
  455. {
  456. auto plugin = mPluginService->getPluginLoader()->createPlugin(source);
  457. auto adSource = dynamic_cast<SDK::GUI::IAdSource *>(plugin);
  458. if (adSource)
  459. {
  460. mAdSourceList << adSource;
  461. }
  462. else
  463. {
  464. mPluginService->getPluginLoader()->destroyPlugin(plugin);
  465. }
  466. }
  467. }
  468. //---------------------------------------------------------------------------
  469. void GUIService::loadNativeScenarios()
  470. {
  471. QStringList scenarios = mPluginService->getPluginLoader()->getPluginList(QRegExp("PaymentProcessor\\.ScenarioFactory\\..*"));
  472. foreach (const QString & scenario, scenarios)
  473. {
  474. auto plugin = mPluginService->getPluginLoader()->createPlugin(scenario);
  475. auto factory = dynamic_cast<SDK::Plugin::IFactory<GUI::Scenario> *>(plugin);
  476. if (factory)
  477. {
  478. // Создаем сценарии.
  479. foreach (auto className, factory->getClassNames())
  480. {
  481. GUI::Scenario * scenarioObject = factory->create(className);
  482. mScenarioEngine.addScenario(scenarioObject);
  483. }
  484. }
  485. else
  486. {
  487. LOG(mApplication->getLog(), LogLevel::Error, QString("Bad scenario plugin %1.").arg(scenario));
  488. }
  489. mPluginService->getPluginLoader()->destroyPlugin(plugin);
  490. }
  491. }
  492. //---------------------------------------------------------------------------
  493. void GUIService::loadBackends()
  494. {
  495. QStringList backends = mPluginService->getPluginLoader()->getPluginList(QRegExp("PaymentProcessor\\.GraphicsBackend\\..*"));
  496. foreach (const QString & backend, backends)
  497. {
  498. SDK::Plugin::IPlugin * plugin = mPluginService->getPluginLoader()->createPlugin(backend);
  499. SDK::GUI::IGraphicsBackend * backendObject = dynamic_cast<SDK::GUI::IGraphicsBackend *>(plugin);
  500. if (backendObject)
  501. {
  502. backendObject->initialize(&mGraphicsEngine);
  503. mGraphicsEngine.addBackend(backendObject);
  504. mBackendPluginList << plugin;
  505. }
  506. else
  507. {
  508. LOG(mApplication->getLog(), LogLevel::Error, QString("Bad backend plugin %1.").arg(backend));
  509. mPluginService->getPluginLoader()->destroyPlugin(plugin);
  510. }
  511. }
  512. }
  513. //---------------------------------------------------------------------------
  514. void GUIService::loadScriptObjects()
  515. {
  516. QStringList scriptObjects = mPluginService->getPluginLoader()->getPluginList(QRegExp("PaymentProcessor\\.ScriptFactory\\..*"));
  517. foreach(const QString & scriptPluginName, scriptObjects)
  518. {
  519. auto plugin = mPluginService->getPluginLoader()->createPlugin(scriptPluginName);
  520. auto factory = dynamic_cast<SDK::Plugin::IFactory<PPSDK::Scripting::IBackendScenarioObject> *>(plugin);
  521. if (factory)
  522. {
  523. foreach(auto className, factory->getClassNames())
  524. {
  525. PPSDK::Scripting::IBackendScenarioObject * scriptObject = factory->create(className);
  526. toLog(LogLevel::Normal, QString("Register scenario backend object '%1' from '%2'.")
  527. .arg(scriptObject->getName()).arg(scriptPluginName));
  528. QString objectName = CGUIService::BackedObjectPrefix + scriptObject->getName();
  529. mScenarioEngine.injectScriptObject(objectName, scriptObject);
  530. // TODO PORT_QT5
  531. //mBackendScenarioObjects.insert(objectName, QWeakPointer<QObject>(scriptObject));
  532. }
  533. }
  534. else
  535. {
  536. LOG(mApplication->getLog(), LogLevel::Error, QString("Bad script object plugin %1.").arg(scriptPluginName));
  537. mPluginService->getPluginLoader()->destroyPlugin(plugin);
  538. }
  539. }
  540. }
  541. //---------------------------------------------------------------------------
  542. SDK::GUI::IAdSource * GUIService::getAdSource() const
  543. {
  544. return mAdSourceList.count() ? mAdSourceList.first() : nullptr;
  545. }
  546. //------------------------------------------------------------------------
  547. QObject * GUIService::getBackendObject(const QString & aName) const
  548. {
  549. QString fullName = CGUIService::BackedObjectPrefix + aName;
  550. return mBackendScenarioObjects.keys().contains(fullName) ? mBackendScenarioObjects.value(fullName).data() : nullptr;
  551. }
  552. //------------------------------------------------------------------------
  553. void GUIService::bringToFront()
  554. {
  555. foreach(QWidget * widget, QApplication::topLevelWidgets())
  556. {
  557. if (!widget->isHidden())
  558. {
  559. ISysUtils::bringWindowToFront(widget->winId());
  560. }
  561. }
  562. auto getTopmostWindowsTitle = [](QSettings & aSettings) -> QStringList {
  563. QStringList topmostWindows;
  564. aSettings.beginGroup("topmost");
  565. foreach(auto const key, aSettings.allKeys())
  566. {
  567. QVariant v = aSettings.value(key);
  568. switch (v.type())
  569. {
  570. case QVariant::StringList:
  571. topmostWindows.append(v.toStringList());
  572. break;
  573. case QVariant::String:
  574. topmostWindows.push_back(v.toString());
  575. break;
  576. }
  577. }
  578. aSettings.endGroup();
  579. return topmostWindows;
  580. };
  581. static QStringList topmostWindows = getTopmostWindowsTitle(mApplication->getSettings());
  582. foreach(auto title, topmostWindows)
  583. {
  584. ISysUtils::bringWindowToFront(title);
  585. }
  586. }
  587. //---------------------------------------------------------------------------