swift
guiapplication.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "gui/guiapplication.h"
5 
6 #include <QAction>
7 #include <QApplication>
8 #include <QCloseEvent>
9 #include <QCommandLineParser>
10 #include <QDesktopServices>
11 #include <QDialogButtonBox>
12 #include <QDir>
13 #include <QEventLoop>
14 #include <QFont>
15 #include <QGuiApplication>
16 #include <QIcon>
17 #include <QKeySequence>
18 #include <QMainWindow>
19 #include <QMenu>
20 #include <QMessageBox>
21 #include <QSettings>
22 #include <QStringBuilder>
23 #include <QStringList>
24 #include <QStyle>
25 #include <QStyleFactory>
26 #include <QTextBrowser>
27 #include <QToolBar>
28 #include <QUrl>
29 #include <QVBoxLayout>
30 #include <QWhatsThis>
31 #include <QWidget>
32 #include <Qt>
33 #include <QtGlobal>
34 
35 #include "config/buildconfig.h"
37 #include "core/data/globalsetup.h"
38 #include "core/db/infodatareader.h"
39 #include "core/setupreader.h"
40 #include "core/webdataservices.h"
45 #include "gui/guiutility.h"
46 #include "gui/registermetadata.h"
47 #include "gui/splashscreen.h"
48 #include "misc/datacache.h"
49 #include "misc/logcategories.h"
50 #include "misc/loghandler.h"
51 #include "misc/logmessage.h"
52 #include "misc/metadatautils.h"
53 #include "misc/settingscache.h"
54 #include "misc/slot.h"
55 #include "misc/stringutils.h"
56 #include "misc/swiftdirectories.h"
57 #include "misc/verify.h"
58 
59 using namespace swift::config;
60 using namespace swift::misc;
61 using namespace swift::misc::db;
62 using namespace swift::misc::network;
63 using namespace swift::gui::components;
64 using namespace swift::core;
65 using namespace swift::core::data;
66 using namespace swift::core::context;
67 
68 swift::gui::CGuiApplication *sGui = nullptr; // set by constructor
69 
70 namespace swift::gui
71 {
72  CGuiApplication *CGuiApplication::instance() { return qobject_cast<CGuiApplication *>(CApplication::instance()); }
73 
74  const QStringList &CGuiApplication::getLogCategories()
75  {
76  static const QStringList l(CApplication::getLogCategories() + QStringList { CLogCategories::guiComponent() });
77  return l;
78  }
79 
80  const QString &CGuiApplication::settingsOrganization()
81  {
82  static const QString o("swift-project.org");
83  return o;
84  }
85 
86  bool CGuiApplication::removeAllWindowsSwiftRegistryEntries()
87  {
88  if (!CBuildConfig::isRunningOnWindowsNtPlatform()) { return false; }
89 
90  // On Windows, NativeFormat settings are stored in the following registry paths:
91  // HKEY_CURRENT_USER\Software\MySoft\Star Runner.
92  // HKEY_CURRENT_USER\Software\MySoft\OrganizationDefaults.
93  // HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner.
94  // HKEY_LOCAL_MACHINE\Software\MySoft\OrganizationDefaults.
95 
96  QSettings s1("HKEY_CURRENT_USER\\Software\\" + settingsOrganization(), QSettings::NativeFormat);
97  s1.remove("");
98 
99  QSettings s2("HKEY_LOCAL_MACHINE\\Software\\" + settingsOrganization(), QSettings::NativeFormat);
100  s2.remove("");
101 
102  return true;
103  }
104 
105  CGuiApplication::CGuiApplication(const QString &applicationName, CApplicationInfo::Application application,
106  const QPixmap &icon)
107  : CApplication(applicationName, application, false)
108  {
109  this->addWindowModeOption();
110  this->addWindowResetSizeOption();
111 
112  // notify when app goes down
114 
115  if (!sGui)
116  {
118  CApplication::init(false); // base class without metadata
119  CGuiApplication::adjustPalette();
121  this->settingsChanged();
122  this->setCurrentFontValues(); // most likely the default font and not any stylesheet font at this time
123  sGui = this;
124 
125  connect(&m_styleSheetUtility, &CStyleSheetUtility::styleSheetsChanged, this,
126  &CGuiApplication::onStyleSheetsChanged, Qt::QueuedConnection);
127  connect(this, &CGuiApplication::startUpCompleted, this, &CGuiApplication::superviseWindowMinSizes,
129  }
130  }
131 
133 
135  {
136  CApplication::registerMetadata();
138  }
139 
141  {
142  m_cmdWindowMode = QCommandLineOption(
143  { "w", "window" }, QCoreApplication::translate("main", "Windows: (n)ormal, (f)rameless, (t)ool."),
144  "windowtype");
145  this->addParserOption(m_cmdWindowMode);
146  }
147 
149  {
150  m_cmdWindowSizeReset = QCommandLineOption(
151  { { "r", "resetsize" }, QCoreApplication::translate("main", "Reset window size (ignore saved values).") });
152  this->addParserOption(m_cmdWindowSizeReset);
153  }
154 
156  {
157  m_cmdWindowStateMinimized = QCommandLineOption(
158  { { "m", "minimized" }, QCoreApplication::translate("main", "Start minimized in system tray.") });
159  this->addParserOption(m_cmdWindowStateMinimized);
160  }
161 
163  {
164  if (m_cmdWindowStateMinimized.valueName() == "empty") { return Qt::WindowNoState; }
165  if (m_parser.isSet(m_cmdWindowStateMinimized)) { return Qt::WindowMinimized; }
166  return Qt::WindowNoState;
167  }
168 
170  {
171  if (this->isParserOptionSet(m_cmdWindowMode))
172  {
173  const QString v(this->getParserValue(m_cmdWindowMode));
175  }
176  else { return CEnableForFramelessWindow::WindowNormal; }
177  }
178 
180  {
181  if (m_splashScreen)
182  {
183  m_splashScreen.reset(); // delete old one
184  }
185 
186  QFont splashFont;
187  splashFont.setFamily("Arial");
188  // splashFont.setBold(true);
189  splashFont.setPointSize(10);
190  splashFont.setStretch(100);
191 
192  m_splashScreen.reset(new CSplashScreen(pixmap.scaled(256, 256), splashFont));
193  m_splashScreen->show();
194  m_splashScreen->showStatusMessage("Version " + CBuildConfig::getVersionString());
195  }
196 
198  {
199  if (this->isShuttingDown()) { return; }
201  }
202 
204 
206  {
208  }
209 
211  {
212  if (this->getGlobalSetup().isSwiftVersionMinimumMappingVersion()) { return true; }
213 
214  const QString msg =
215  QStringLiteral("Your are using swift version: '%1'.\nCreating mappings requires at least '%2'.")
216  .arg(CBuildConfig::getVersionString(), this->getGlobalSetup().getMappingMinimumVersionString());
218  return false;
219  }
220 
222  {
223  return qobject_cast<QMainWindow *>(CGuiApplication::mainApplicationWidget());
224  }
225 
227  {
228  IMainWindowAccess *m = qobject_cast<IMainWindowAccess *>(mainApplicationWidget());
229  return m;
230  }
231 
233  {
234  if (!mainWidget) { return; }
235  if (m_uiSetupCompleted) { return; }
236  m_uiSetupCompleted = true;
237 
238  const QString name = this->setExtraWindowTitle("", mainWidget);
240  mainWidget->setWindowIcon(m_windowIcon);
241  mainWidget->setWindowIconText(name);
244  emit this->uiObjectTreeReady();
245  }
246 
248  {
250  if (maw)
251  {
252  Qt::WindowFlags windowFlags = maw->windowFlags();
253  windowFlags |= flags;
254  maw->setWindowFlags(windowFlags);
255  }
256  else
257  {
258  QPointer<CGuiApplication> myself(this);
259  connectOnce(this, &CGuiApplication::uiObjectTreeReady, this, [=, this] {
260  if (!myself) { return; }
261  this->addWindowFlags(flags);
262  });
263  }
264  }
265 
266  QString CGuiApplication::setExtraWindowTitle(const QString &extraInfo, QWidget *mainWindowWidget) const
267  {
269  if (!extraInfo.isEmpty()) { name = extraInfo % u' ' % name; }
270  if (!mainWindowWidget) { return name; }
271  mainWindowWidget->setWindowTitle(name);
272  return name;
273  }
274 
276  {
277  instance()->m_windowIcon = icon;
279  }
280 
281  void CGuiApplication::exit(int retcode) { CApplication::exit(retcode); }
282 
284  {
286  if (!w) return QGuiApplication::primaryScreen();
287 
288  const QWindow *win = w->windowHandle();
289 
290  if (!win) return QGuiApplication::primaryScreen();
291 
292  QScreen *screen = win->screen();
293 
294  return screen ? screen : QGuiApplication::primaryScreen();
295  }
296 
298  {
299  const QScreen *s = currentScreen();
300  if (s) return s->geometry();
301  return {};
302  }
303 
305  {
306  if (!QGuiApplication::modalWindow()) { return; }
308  }
309 
310  const QString &CGuiApplication::fileForWindowGeometryAndStateSettings()
311  {
312  static const QString filename = [] {
313  QString dir =
314  CFileUtils::appendFilePaths(CSwiftDirectories::normalizedApplicationDataDirectory(), "settings/qgeom");
315  return CFileUtils::appendFilePaths(
316  dir, QFileInfo(QCoreApplication::applicationFilePath()).completeBaseName() + ".ini");
317  }();
318  return filename;
319  }
320 
321  int CGuiApplication::hashForStateSettingsSchema(const QMainWindow *window)
322  {
323  size_t hash = 0;
324  for (auto obj : window->findChildren<QToolBar *>(QString(), Qt::FindDirectChildrenOnly))
325  {
326  hash ^= qHash(obj->objectName());
327  }
328  for (auto obj : window->findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly))
329  {
330  hash ^= qHash(obj->objectName());
331  }
332  return static_cast<int>((hash & 0xffff) ^ (hash >> 16));
333  }
334 
336  {
337  if (!window) { return false; }
338  QSettings settings(fileForWindowGeometryAndStateSettings(), QSettings::IniFormat);
339  settings.setValue("geometry", window->saveGeometry());
340  settings.setValue("windowState", window->saveState(hashForStateSettingsSchema(window)));
341  return true;
342  }
343 
345  {
346  QByteArray ba;
347  QSettings settings(fileForWindowGeometryAndStateSettings(), QSettings::IniFormat);
348  settings.setValue("geometry", ba);
349  settings.setValue("windowState", ba);
350  }
351 
353  {
354  if (!window) { return false; }
355  const QSettings settings(fileForWindowGeometryAndStateSettings(), QSettings::IniFormat);
356  const QString location = settings.fileName();
357  CLogMessage(this).info(u"GUI settings are here: '%1'") << location;
358 
359  const QByteArray g = settings.value("geometry").toByteArray();
360  const QByteArray s = settings.value("windowState").toByteArray();
361  if (g.isEmpty() || s.isEmpty()) { return false; }
362 
363  // block for subscriber
364  {
365  const auto pattern = CLogPattern().withSeverity(CStatusMessage::SeverityError);
366  const QString parameter = m_cmdWindowSizeReset.names().first();
367  CLogSubscriber logSub(this, [&](const CStatusMessage &message) {
368  // handles an error in restoreGeometry/State
369  const int ret =
371  QStringLiteral("Restoring the window state/geometry failed!\n"
372  "You need to reset the window size (command -%1).\n\n"
373  "Original msg: %2\n\n"
374  "We can try to reset the values and restart\n"
375  "Do you want to try?")
376  .arg(parameter, message.getMessage()),
378  if (ret == QMessageBox::Yes)
379  {
381  this->restartApplication();
382  }
383  // most likely crashing if we do nothing
384  });
385  logSub.changeSubscription(pattern);
386 
387  window->restoreGeometry(g);
388  window->restoreState(s, hashForStateSettingsSchema(window));
389  }
390  return true;
391  }
392 
394  {
395  CApplication::onStartUpCompleted();
396  this->setCurrentFontValues();
397 
398  const QString metricInfo = CGuiUtility::metricsInfo();
399  CLogMessage(this).info(metricInfo);
400 
401  // window size
402  if (m_minWidthChars > 0 || m_minHeightChars > 0)
403  {
404  const QSizeF fontMetricEstSize = CGuiUtility::fontMetricsEstimateSize(m_minWidthChars, m_minHeightChars);
406  if (mw)
407  {
408  // setMinimumSizeInCharacters sets m_minHeightChars/m_minWidthChars
409  QSize cs = mw->size();
410  if (m_minWidthChars > 0) { cs.setWidth(qRound(fontMetricEstSize.width())); }
411  if (m_minHeightChars > 0) { cs.setHeight(qRound(fontMetricEstSize.height())); }
412  mw->resize(cs);
413  }
414  }
415  if (m_saveMainWidgetState && !this->isSet(m_cmdWindowSizeReset))
416  {
418  const bool shiftAlt = km.testFlag(Qt::ShiftModifier) && km.testFlag(Qt::AltModifier);
419  if (!shiftAlt) { this->restoreWindowGeometryAndState(); }
420  }
421 
422  if (m_splashScreen)
423  {
424  m_splashScreen->close(); // GUI
425  m_splashScreen.reset();
426  }
427  }
428 
429  void CGuiApplication::cmdLineErrorMessage(const QString &text, const QString &informativeText) const
430  {
432  if (informativeText.length() < 300)
433  errorBox.setInformativeText(informativeText);
434  else
435  errorBox.setDetailedText(informativeText);
436 
437  errorBox.addButton(QMessageBox::Abort);
438 
439  errorBox.exec();
440  }
441 
443  {
444  if (msgs.isEmpty()) { return; }
445  if (!msgs.hasErrorMessages()) { return; }
446  static const CPropertyIndexList propertiesSingle({ CStatusMessage::IndexMessage });
447  static const CPropertyIndexList propertiesMulti(
448  { CStatusMessage::IndexSeverityAsString, CStatusMessage::IndexMessage });
449  const QString msgsHtml = msgs.toHtml(msgs.size() > 1 ? propertiesMulti : propertiesSingle);
451  "<html><head><body>" + msgsHtml + "</body></html>", QMessageBox::Abort,
453  }
454 
455  bool CGuiApplication::isCmdWindowSizeResetSet() const { return this->isParserOptionSet(m_cmdWindowSizeReset); }
456 
458  {
460  SWIFT_VERIFY_X(m, Q_FUNC_INFO, "No access interface");
461  if (!m) { return false; }
462  return m->displayInStatusBar(message);
463  }
464 
465  bool CGuiApplication::displayInOverlayWindow(const CStatusMessage &message, std::chrono::milliseconds timeout)
466  {
467  if (message.isEmpty()) { return false; }
469  SWIFT_VERIFY_X(m, Q_FUNC_INFO, "No access interface");
470  if (!m) { return IMainWindowAccess::displayInOverlayWindow(message, timeout); }
471  return m->displayInOverlayWindow(message, timeout);
472  }
473 
474  bool CGuiApplication::displayInOverlayWindow(const CStatusMessageList &messages, std::chrono::milliseconds timeout)
475  {
476  if (messages.isEmpty()) { return false; }
478  SWIFT_VERIFY_X(m, Q_FUNC_INFO, "No access interface");
479  if (!m) { return IMainWindowAccess::displayInOverlayWindow(messages, timeout); }
480  return m->displayInOverlayWindow(messages, timeout);
481  }
482 
483  bool CGuiApplication::displayInOverlayWindow(const QString &html, std::chrono::milliseconds timeout)
484  {
485  if (html.isEmpty()) { return false; }
487  SWIFT_VERIFY_X(m, Q_FUNC_INFO, "No access interface");
488  if (!m) { return IMainWindowAccess::displayInOverlayWindow(html, timeout); }
489  return m->displayInOverlayWindow(html, timeout);
490  }
491 
493  {
494  QMenu *sm = menu.addMenu(CIcons::appSettings16(), "Settings");
495  sm->setIcon(CIcons::appSettings16());
496  QAction *a = sm->addAction(CIcons::disk16(), "Settings directory");
497  bool c = connect(a, &QAction::triggered, this, [=]() {
498  if (!sGui || sGui->isShuttingDown()) { return; }
499  const QString path(QDir::toNativeSeparators(CSettingsCache::persistentStore()));
500  if (QDir(path).exists()) { QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }
501  });
502  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
503 
504  a = sm->addAction("Reset settings");
505  c = connect(a, &QAction::triggered, this, [=, this] {
506  if (!sGui || sGui->isShuttingDown()) { return; }
507  CSettingsCache::instance()->clearAllValues();
508  CLogMessage(this).info(u"Cleared all settings!");
509  });
510  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
511 
512  a = sm->addAction("List settings files");
513  c = connect(a, &QAction::triggered, this, [=, this]() {
514  if (!sGui || sGui->isShuttingDown()) { return; }
515  const QStringList files(CSettingsCache::instance()->enumerateStore());
516  CLogMessage(this).info(files.join("\n"));
517  });
518  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
519 
520  sm = menu.addMenu("Cache");
521  sm->setIcon(CIcons::appSettings16());
522  a = sm->addAction(CIcons::disk16(), "Cache directory");
523  c = connect(a, &QAction::triggered, this, [=]() {
524  const QString path(QDir::toNativeSeparators(CDataCache::persistentStore()));
525  if (QDir(path).exists()) { QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }
526  });
527  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
528 
529  a = sm->addAction("Reset cache");
530  c = connect(a, &QAction::triggered, this, [=, this]() {
531  if (!sGui || sGui->isShuttingDown()) { return; }
532  const QStringList files = CApplication::clearCaches();
533  CLogMessage(this).info(u"Cleared caches! " % QString::number(files.size()) + " files");
534  });
535  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
536 
537  a = sm->addAction("List cache files");
538  c = connect(a, &QAction::triggered, this, [=, this]() {
539  if (!sGui || sGui->isShuttingDown()) { return; }
540  const QStringList files(CDataCache::instance()->enumerateStore());
541  CLogMessage(this).info(files.join("\n"));
542  });
543  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
544 
545  a = menu.addAction(CIcons::disk16(), "Log directory");
546  c = connect(a, &QAction::triggered, this, [=, this]() {
547  if (!sGui || sGui->isShuttingDown()) { return; }
548  this->openStandardLogDirectory();
549  });
550  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
551 
552  a = menu.addAction(CIcons::disk16(), "Crash dumps directory");
553  c = connect(a, &QAction::triggered, this, [=, this]() {
554  if (!sGui || sGui->isShuttingDown()) { return; }
555  this->openStandardCrashDumpDirectory();
556  });
557  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
558 
559  a = menu.addAction(CIcons::swift24(), "Check for updates");
560  c = connect(a, &QAction::triggered, this, &CGuiApplication::checkNewVersionMenu);
561  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
562  Q_UNUSED(c)
563  }
564 
566  {
567  QMenu *sm = menu.addMenu("Style sheet");
568  QAction *aReload = sm->addAction(CIcons::refresh16(), "Reload");
569  bool c = connect(aReload, &QAction::triggered, this, [=, this]() {
570  if (!sGui || sGui->isShuttingDown()) { return; }
571  this->reloadStyleSheets();
572  });
573  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
574 
575  QAction *aOpen = sm->addAction(CIcons::text16(), "Open qss file");
576  c = connect(aOpen, &QAction::triggered, this, [=, this]() {
577  if (!sGui || sGui->isShuttingDown()) { return; }
578  this->openStandardWidgetStyleSheet();
579  });
580  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
581  Q_UNUSED(c)
582  }
583 
585  {
587  addMenuForStyleSheets(menu);
588  QAction *a = nullptr;
589  bool c = false;
590 
591  menu.addSeparator();
592  a = menu.addAction("E&xit");
593  // a->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); // avoid accidentally closing
594  c = connect(
595  a, &QAction::triggered, this,
596  [=]() {
597  // a close event might already trigger a shutdown
598  if (!sGui || sGui->isShuttingDown()) { return; }
599  if (!CGuiApplication::mainApplicationWidget()) { return; }
601 
602  // T596, do not shutdown here, as close can be canceled
603  // if shutdown is called, there is no way back
604  // this->gracefulShutdown();
605  },
607  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
608  Q_UNUSED(c)
609  }
610 
612  {
613  QMenu *sm = menu.addMenu("JSON files/Templates");
614  QAction *a = sm->addAction("JSON bootstrap");
615  bool c = connect(
616  a, &QAction::triggered, this,
617  [=, this]() {
618  if (!sGui || sGui->isShuttingDown()) { return; }
619  const CGlobalSetup s = this->getGlobalSetup();
620  CLogMessage(this).info(s.toJsonString());
621  },
623  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
624 
625  a = sm->addAction("JSON version update info (for info only)");
626  c = connect(
627  a, &QAction::triggered, this,
628  [=, this]() {
629  if (!sGui || sGui->isShuttingDown()) { return; }
630  const CUpdateInfo info = this->getUpdateInfo();
631  CLogMessage(this).info(info.toJsonString());
632  },
634  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
635 
636  if (this->hasWebDataServices())
637  {
638  a = menu.addAction("Services log.(console)");
639  c = connect(
640  a, &QAction::triggered, this,
641  [=, this]() {
642  if (!sGui || sGui->isShuttingDown()) { return; }
643  CLogMessage(this).info(this->getWebDataServices()->getReadersLog());
644  },
646  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
647 
648  a = sm->addAction("JSON DB info (for info only)");
649  c = connect(
650  a, &QAction::triggered, this,
651  [=, this]() {
652  if (!sGui || sGui->isShuttingDown()) { return; }
653  if (!this->getWebDataServices()->getDbInfoDataReader()) { return; }
655  CLogMessage(this).info(u"DB info:\n" % info.toJsonString());
656  },
658  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
659 
660  a = sm->addAction("JSON shared info (for info only)");
661  c = connect(
662  a, &QAction::triggered, this,
663  [=, this]() {
664  if (!sGui || sGui->isShuttingDown()) { return; }
665  if (!this->getWebDataServices()->getDbInfoDataReader()) { return; }
667  CLogMessage(this).info(u"Shared info:\n" % info.toJsonString());
668  },
670  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
671  }
672 
673  a = menu.addAction("Metadata (slow)");
674  c = connect(
675  a, &QAction::triggered, this,
676  [=, this]() {
677  if (!sGui || sGui->isShuttingDown()) { return; }
679  },
681  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
682  Q_UNUSED(c)
683  }
684 
686  {
688  if (!w) { return; }
689  const QSize iconSize = CIcons::empty16().size();
690  static QPixmap iconEmpty;
691 
692  QPixmap icon = w->style()->standardIcon(QStyle::SP_TitleBarMaxButton).pixmap(iconSize);
693  QAction *a = menu.addAction(icon.isNull() ? iconEmpty : icon.scaled(iconSize), "Fullscreen");
694  bool c = connect(a, &QAction::triggered, this, [=]() {
695  if (!w) { return; }
696  w->showFullScreen();
697  });
698  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
699 
700  icon = w->style()->standardIcon(QStyle::SP_TitleBarMinButton).pixmap(iconSize);
701  a = menu.addAction(icon.isNull() ? iconEmpty : icon.scaled(iconSize), "Minimize");
702  c = connect(a, &QAction::triggered, this, [=]() {
703  if (!w) { return; }
704  w->showMinimized();
705  });
706  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
707 
708  icon = w->style()->standardIcon(QStyle::SP_TitleBarNormalButton).pixmap(iconSize);
709  a = menu.addAction(icon.isNull() ? iconEmpty : icon.scaled(iconSize), "Normal");
710  c = connect(a, &QAction::triggered, this, [=]() {
711  if (!w) { return; }
712  w->showNormal();
713  });
714  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
715 
716  a = menu.addAction("Toggle stay on top");
717  c = connect(a, &QAction::triggered, this, [=, this]() {
718  if (!w) { return; }
719  this->toggleStayOnTop();
720  });
721  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
722 
723  a = menu.addAction("Toggle to front or back");
725  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed");
726 
727  a = menu.addAction("Window to front");
729  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed");
730 
731  a = menu.addAction("Window to back");
733  Q_ASSERT_X(c, Q_FUNC_INFO, "connect failed");
734 
735  a = menu.addAction("Toggle normal or minimized");
736  c = connect(a, &QAction::triggered, this, [=, this]() {
737  if (!w) { return; }
739  });
740  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
741  Q_UNUSED(c)
742  }
743 
745  {
746  if (url.isEmpty() || this->isShuttingDown()) { return; }
748  }
749 
751  {
753  if (!w) { return; }
754  QAction *a = menu.addAction(w->style()->standardIcon(QStyle::SP_TitleBarContextHelpButton), "Online help");
755 
756  bool c = connect(a, &QAction::triggered, this, [=, this]() {
757  if (!sGui || sGui->isShuttingDown()) { return; }
758  this->showHelp();
759  });
760  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
761 
762  a = menu.addAction(QApplication::windowIcon(), "About swift");
763  c = connect(a, &QAction::triggered, this, [=]() {
764  if (!w) { return; }
765  CAboutDialog dialog(w);
766  dialog.exec();
767  });
768  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
769  Q_UNUSED(c)
770 
771  a = menu.addAction(QApplication::windowIcon(), "Changelog");
772  c = connect(a, &QAction::triggered, this, [=, this]() { this->showChangelog(); });
773  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
774  Q_UNUSED(c)
775 
776  // https://joekuan.wordpress.com/2015/09/23/list-of-qt-icons/
777  a = menu.addAction(QApplication::style()->standardIcon(QStyle::SP_TitleBarMenuButton), "About Qt");
778  c = connect(a, &QAction::triggered, this, []() { QApplication::aboutQt(); });
779  Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed");
780  Q_UNUSED(c)
781  }
782 
783  void CGuiApplication::showHelp(const QString &subpath) const
784  {
785  if (this->isShuttingDown()) { return; }
786  const CGlobalSetup gs = this->getGlobalSetup();
787  const CUrl helpPage = gs.getHelpPageUrl().withAppendedPath(subpath);
788  QDesktopServices::openUrl(helpPage);
789  }
790 
792  {
793  if (this->isShuttingDown()) { return; }
794 
796  if (!parent) { return; }
797 
798  const QString changelogPath = CFileUtils::appendFilePaths(CSwiftDirectories::shareDirectory(), "CHANGELOG.md");
799  const QString changelog = CFileUtils::readFileToString(changelogPath);
800  if (changelog.isEmpty())
801  {
803  QStringLiteral("Unable to load changelog from %1").arg(changelogPath));
804  return;
805  }
806 
807  QDialog dialog(parent);
808  dialog.setWindowTitle(QStringLiteral("Changelog"));
810 
811  auto *layout = new QVBoxLayout(&dialog);
812  auto *browser = new QTextBrowser(&dialog);
813  browser->setMarkdown(changelog);
814  browser->setOpenExternalLinks(true);
815  layout->addWidget(browser);
816 
817  auto *buttons = new QDialogButtonBox(QDialogButtonBox::Ok, &dialog);
818  connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
819  layout->addWidget(buttons);
820 
821  dialog.resize(900, 700);
822  dialog.exec();
823  }
824 
825  const CStyleSheetUtility &CGuiApplication::getStyleSheetUtility() const { return m_styleSheetUtility; }
826 
828  {
829  QString currentWidgetStyle(QApplication::style()->metaObject()->className());
830  if (currentWidgetStyle.startsWith('Q')) { currentWidgetStyle.remove(0, 1); }
831  return currentWidgetStyle.replace("Style", "");
832  }
833 
834  bool CGuiApplication::reloadStyleSheets() { return m_styleSheetUtility.read(); }
835 
837  {
840  }
841 
843  {
844  const QString path(QDir::toNativeSeparators(CSwiftDirectories::logDirectory()));
845  if (!QDir(path).exists()) { return false; }
847  }
848 
850  {
851  const QString path(QDir::toNativeSeparators(CSwiftDirectories::crashpadDatabaseDirectory()));
852  if (!QDir(path).exists()) { return false; }
854  }
855 
856  bool CGuiApplication::updateFont(const QString &fontFamily, const QString &fontSize, const QString &fontStyle,
857  const QString &fontWeight, const QString &fontColor)
858  {
859  return m_styleSheetUtility.updateFont(fontFamily, fontSize, fontStyle, fontWeight, fontColor);
860  }
861 
862  bool CGuiApplication::updateFont(const QString &qss) { return m_styleSheetUtility.updateFont(qss); }
863 
864  bool CGuiApplication::resetFont() { return m_styleSheetUtility.resetFont(); }
865 
866  void CGuiApplication::setMinimumSizeInCharacters(int widthChars, int heightChars)
867  {
868  m_minWidthChars = widthChars;
869  m_minHeightChars = heightChars;
870  }
871 
873  {
874  if (msgs.hasErrorMessages())
875  {
877  if (sGui)
878  {
879  static const QString style = sGui->getStyleSheetUtility().styles(
881  dialog.setStyleSheet(style);
882  }
883 
884  dialog.exec();
885  }
886  }
887 
889  {
890  this->saveSettingsOnShutdown(false); // saving itself will be handled in dialog
891  const bool needsDialog = this->hasUnsavedSettings();
892  if (!needsDialog) { return QDialog::Accepted; }
893  if (!m_closeDialog)
894  {
895  m_closeDialog = new CApplicationCloseDialog(mainWindow);
896  if (mainWindow && !mainWindow->windowTitle().isEmpty())
897  {
898  m_closeDialog->setWindowTitle(mainWindow->windowTitle());
899  m_closeDialog->setModal(true);
900  }
901  }
902 
903  // dialog will handle the saving
904  const auto c = static_cast<QDialog::DialogCode>(m_closeDialog->exec());
905 
906  // settings already saved when reaching here
907  switch (c)
908  {
909  case QDialog::Rejected:
910  if (closeEvent) { closeEvent->ignore(); }
911  break;
912  default: break;
913  }
914  return c;
915  }
916 
917  bool CGuiApplication::parsingHookIn() { return true; }
918 
920  {
921  // Nothing to do here
922  }
923 
924  void CGuiApplication::checkNewVersion(bool onlyIfNew)
925  {
926  if (!m_updateDialog)
927  {
928  // without parent stylesheet is not inherited
930  }
931 
932  if (onlyIfNew && !m_updateDialog->isNewVersionAvailable()) { return; }
933  const int result = m_updateDialog->exec();
934  if (result != QDialog::Accepted) { return; }
935  }
936 
938  {
940  if (!w) { return QStringLiteral("Font info not available"); }
941  return QStringLiteral("Family: '%1', average width: %2")
942  .arg(w->font().family())
943  .arg(w->fontMetrics().averageCharWidth());
944  }
945 
947  {
949  if (!w) { return false; }
950  const bool onTop = CGuiUtility::toggleStayOnTop(w);
951  CLogMessage(w).info(onTop ? QStringLiteral("Window on top") : QStringLiteral("Window not always on top"));
952  emit this->alwaysOnTop(onTop);
953  m_frontBack = onTop;
954  return onTop;
955  }
956 
958  {
959  if (this->isShuttingDown()) { return; }
961  if (!w) { return; }
962 
963  m_frontBack = true;
964  w->showNormal(); // bring window to top on OSX
965  w->raise(); // bring window from minimized state on OSX
966 
967  // if (!CGuiUtility::staysOnTop(w)) { CGuiUtility::stayOnTop(true, w); emit this->alwaysOnTop(true); }
968  w->activateWindow(); // bring window to front/unminimize on windows
969  }
970 
972  {
973  if (this->isShuttingDown()) { return; }
975  if (!w) { return; }
976 
977  m_frontBack = false;
979  {
980  CGuiUtility::stayOnTop(false, w);
981  emit this->alwaysOnTop(false);
982  }
983  w->lower();
984  }
985 
987  {
988  if (this->isShuttingDown()) { return; }
990  if (!w) { return; }
991  if (w->isMinimized())
992  {
993  this->windowToFront();
994  return;
995  }
996  if (w->isMaximized())
997  {
998  this->windowToBack();
999  return;
1000  }
1001  if (CGuiUtility::staysOnTop(w))
1002  {
1003  this->windowToBack();
1004  return;
1005  }
1006 
1007  if (m_frontBack) { this->windowToBack(); }
1008  else { this->windowToFront(); }
1009  }
1010 
1012  {
1013  if (this->isShuttingDown()) { return; }
1015  if (!w) { return; }
1016  if (m_normalizeMinimize) { w->showMinimized(); }
1017  else
1018  {
1019  // trick here is to minimize first and the normalize from minimized state
1020  w->showMinimized();
1021  w->showNormal();
1022  }
1023  m_normalizeMinimize = !m_normalizeMinimize;
1024  }
1025 
1027  {
1028  if (!m_updateSetting.get()) { return; }
1029  QTimer::singleShot(delayedMs, this, [=, this] {
1030  if (!sGui || sGui->isShuttingDown()) { return; }
1031  if (m_updateDialog) { return; } // already checked elsewhere
1032  this->checkNewVersion(true);
1033  });
1034  }
1035 
1037  {
1038  if (m_shutdown) { return; }
1039  if (m_shutdownInProgress) { return; }
1040 
1041  CLogMessage(this).info(u"Graceful shutdown of GUI application started");
1042  if (m_saveMainWidgetState)
1043  {
1044  CLogMessage(this).info(u"Graceful shutdown, saving geometry");
1046  }
1047 
1048  // shut down whole infrastructure
1049  CApplication::gracefulShutdown();
1050 
1051  // precautions to avoid hanging closing swift
1053  if (modals.count() > 0)
1054  {
1055  // that is a pretty normal situation
1056  CLogMessage(this).info(u"Graceful shutdown, still %1 modal widget(s), closed: %2")
1057  << modals.count() << modals.join(", ");
1058  }
1059 
1062  const QStringList docks =
1064  if (docks.count() > 0)
1065  {
1066  // that should not happen
1067  CLogMessage(this).warning(u"Graceful shutdown, still %1 floating dock widget(s), closed: %2")
1068  << docks.count() << docks.join(", ");
1069  }
1070  }
1071 
1072  void CGuiApplication::settingsChanged()
1073  {
1074  // changing widget style is slow, so I try to prevent setting it when nothing changed
1075  const QString widgetStyle = m_guiSettings.get().getWidgetStyle();
1076  const QString currentWidgetStyle(this->getWidgetStyle());
1077  Q_ASSERT_X(CThreadUtils::thisIsMainThread(), Q_FUNC_INFO, "Wrong thread");
1078  if (!stringCompare(widgetStyle, currentWidgetStyle, Qt::CaseInsensitive))
1079  {
1080  const QStringList availableStyles = QStyleFactory::keys();
1081  if (availableStyles.contains(widgetStyle))
1082  {
1083  // changing style freezes the application, so it must not be done in flight mode
1084  if (this->getIContextNetwork() && this->getIContextNetwork()->isConnected())
1085  {
1086  CLogMessage(this).validationError(u"Cannot change style while connected to network");
1087  }
1088  else
1089  {
1090  // QStyle *style = QApplication::setStyle(widgetStyle);
1091  QStyle *style = QStyleFactory::create(widgetStyle);
1092  // That can crash
1093  QApplication::setStyle(style); // subject of crash
1094  if (style)
1095  {
1096  CLogMessage(this).info(u"Changed style to '%1', req.: '%2'")
1097  << style->objectName() << widgetStyle;
1098  }
1099  else { CLogMessage(this).error(u"Unable to set requested style '%1'") << widgetStyle; }
1100  }
1101  } // valid style
1102  }
1103  }
1104 
1105  void CGuiApplication::checkNewVersionMenu() { this->checkNewVersion(false); }
1106 
1107  void CGuiApplication::adjustPalette()
1108  {
1109  // only way to change link color
1110  // https://stackoverflow.com/q/5497799/356726
1111  // Ref T84
1112  QPalette newPalette(qApp->palette());
1113  const QColor linkColor(135, 206, 250);
1114  newPalette.setColor(QPalette::Link, linkColor);
1115  newPalette.setColor(QPalette::LinkVisited, linkColor);
1116  qApp->setPalette(newPalette);
1117  }
1118 
1119  void CGuiApplication::onStyleSheetsChanged()
1120  {
1121  const QFont f = CGuiUtility::currentFont();
1122  if (f.pointSize() != m_fontPointSize || f.family() != m_fontFamily)
1123  {
1124  emit this->fontChanged();
1125  CLogMessage(this).info(this->getFontInfo());
1126  }
1127  emit this->styleSheetsChanged();
1128  }
1129 
1130  void CGuiApplication::setCurrentFontValues()
1131  {
1132  const QFont font = CGuiUtility::currentFont();
1133  m_fontFamily = font.family();
1134  m_fontPointSize = font.pointSize();
1135  }
1136 
1137  void CGuiApplication::superviseWindowMinSizes() { CGuiUtility::superviseMainWindowMinSizes(); }
1138 } // namespace swift::gui
static constexpr bool isRunningOnWindowsNtPlatform()
Running on Windows NT platform?
QString getParserValue(const QString &option) const
Delegates to QCommandLineParser::value.
std::atomic_bool m_shutdown
Is being shutdown?
Definition: application.h:579
void restartApplication(const QStringList &newArguments={}, const QStringList &removeArguments={})
Stop and restart application.
bool isParserOptionSet(const QString &option) const
Delegates to QCommandLineParser::isSet.
data::CGlobalSetup getGlobalSetup() const
Global setup.
QCommandLineParser m_parser
cmd parser
Definition: application.h:568
bool hasUnsavedSettings() const
Unsaved settings.
bool hasWebDataServices() const
Web data services available?
const context::IContextNetwork * getIContextNetwork() const
Direct access to contexts if a CCoreFacade has been initialized.
bool addParserOption(const QCommandLineOption &option)
bool isShuttingDown() const
Is application shutting down?
bool isSet(const QCommandLineOption &option) const
Flag set or explicitly set to true.
std::atomic_bool m_shutdownInProgress
shutdown in progress?
Definition: application.h:581
const QString & getApplicationNameVersionDetailed() const
Version, name beta and dev info.
CWebDataServices * getWebDataServices() const
Get the web data services.
const QString & getApplicationNameAndVersion() const
Application name and version.
void saveSettingsOnShutdown(bool saveSettings)
Save settings on shutdown.
void startUpCompleted(bool success)
Startup has been completed Will be triggered shortly before starting the event loop.
swift::core::db::CInfoDataReader * getDbInfoDataReader() const
DB info data reader.
swift::core::db::CInfoDataReader * getSharedInfoDataReader() const
Shared info data reader.
Global settings for readers, debug flags, etc.
Definition: globalsetup.h:31
swift::misc::network::CUrl getHelpPageUrl() const
Help page URL.
Definition: globalsetup.cpp:44
swift::misc::db::CDbInfoList getInfoObjects() const
Get info list (either shared or from DB)
static WindowMode stringToWindowMode(const QString &s)
String to window mode.
GUI application, a specialized version of swift::core::CApplication for GUI applications.
bool openStandardWidgetStyleSheet()
Opens the standard stylesheet.
static void modalWindowToFront()
Bring any modal dialog to front.
bool isCmdWindowSizeResetSet() const
Window size reset mode set.
QString setExtraWindowTitle(const QString &extraInfo, QWidget *mainWindowWidget=mainApplicationWidget()) const
Set window title.
QString getFontInfo() const
Info about font.
static swift::gui::IMainWindowAccess * mainWindowAccess()
Main window access interface.
void onCoreFacadeStarted()
Called when facade/contexts have been started.
void registerMainApplicationWidget(QWidget *mainWidget)
Register main application window widget if this is known.
void addWindowResetSizeOption()
CMD line arguments (reset size store)
void addWindowStateOption()
CMD line arguments.
void processEventsToRefreshGui() const
Allow the GUI to refresh by processing events, call the event loop.
Qt::WindowState getWindowState() const
Window state.
bool hasMinimumMappingVersion() const
Minimum mapping version check.
void addWindowModeOption()
CMD line arguments.
static QRect currentScreenGeometry()
Current screen resolution.
void triggerNewVersionCheck(int delayedMs)
Trigger new version check.
bool openStandardCrashDumpDirectory()
Opens the standard dumps directory.
static CGuiApplication * instance()
Similar to.
void windowToFront()
Window to front/back.
CEnableForFramelessWindow::WindowMode getWindowMode() const
Window mode (window flags)
void addMenuHelp(QMenu &menu)
Help operations.
void addMenuForStyleSheets(QMenu &menu)
Add menu for style sheets.
bool reloadStyleSheets()
Reload style sheets.
void cmdLineErrorMessage(const QString &text, const QString &informativeText) const
print messages generated during parsing / cmd handling
static void exit(int retcode=0)
Exit application, perform graceful shutdown and exit.
void addMenuFile(QMenu &menu)
File menu.
void addMenuInternals(QMenu &menu)
Internals menu.
bool displayInOverlayWindow(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
direct access to main application window
void checkNewVersion(bool onlyIfNew)
Check for a new version (update)
void splashScreen(const QPixmap &pixmap)
Add a splash screen based on resource, empty means remove splash screen.
bool restoreWindowGeometryAndState(QMainWindow *window=CGuiApplication::mainApplicationWindow())
Restore widget's geometry and state.
void fontChanged()
Font has been changed.
const CStyleSheetUtility & getStyleSheetUtility() const
Style sheet handling.
bool saveWindowGeometryAndState(const QMainWindow *window=CGuiApplication::mainApplicationWindow()) const
Save widget's geometry and state.
QDialog::DialogCode showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent)
Show close dialog.
void windowToBack()
Window to front/back.
void gracefulShutdown()
Graceful shutdown.
void onStartUpCompleted()
Startup completed.
bool toggleStayOnTop()
Toggle stay on top.
void windowToFrontBackToggle()
Window to front/back.
static void registerMetadata()
Register metadata.
static void setWindowIcon(const QPixmap &icon)
Set icon.
bool resetFont()
Reset the font to default.
void displaySetupLoadFailure(swift::misc::CStatusMessageList msgs)
Display the failures caused by loading the setup file.
void windowMinimizeNormalToggle()
Window minimize/normalize.
void addMenuForSettingsAndCache(QMenu &menu)
Add menu items for settings and cache.
bool updateFont(const QString &fontFamily, const QString &fontSize, const QString &fontStyle, const QString &fontWeight, const QString &fontColor)
Update the fonts.
void showHelp(const QString &subpath={}) const
Show help page (online help)
bool displayInStatusBar(const swift::misc::CStatusMessage &message)
direct access to main application window
void alwaysOnTop(bool onTop)
always on top
static QWidget * mainApplicationWidget()
Main application window widget.
static QMainWindow * mainApplicationWindow()
Main application window.
bool parsingHookIn()
Handle parsing of special GUI cmd arguments.
void uiObjectTreeReady()
Object tree ready (means ui->setupUi() completed)
void openUrl(const swift::misc::network::CUrl &url)
Open a given URL.
bool openStandardLogDirectory()
Opens the standard log directory.
void addMenuWindow(QMenu &menu)
Window operations.
void initMainApplicationWidget(QWidget *mainWidget)
Init the main application window based on information in this application.
static QScreen * currentScreen()
Current screen.
void addWindowFlags(Qt::WindowFlags flags)
Set window flag on main application window.
QString getWidgetStyle() const
Current widget style.
void showChangelog() const
Show changelog popup.
void styleSheetsChanged()
Style sheet changed.
void setMinimumSizeInCharacters(int widthChars, int heightChars)
Set minimum width/height in characters.
void resetWindowGeometryAndState()
Reset the saved values.
static bool stayOnTop(bool onTop, QWidget *widget)
Window flags / stay on top.
Definition: guiutility.cpp:592
static QStringList deleteLaterAllDockWidgetsGetTitles(QWidget *parent, bool floatingOnly)
"deleteLater" all dock widgets
static bool staysOnTop(QWidget *widget)
Window on top?
Definition: guiutility.cpp:552
static void registerMainApplicationWidget(QWidget *mainWidget)
Register main application window widget if this is known.
Definition: guiutility.cpp:87
static QSizeF fontMetricsEstimateSize(int xCharacters, int yCharacters, bool withRatio=false)
Estimate size based on current font.
Definition: guiutility.cpp:756
static void superviseMainWindowMinSizes(qreal wRatio=0.85, qreal hRatio=0.85)
Make sure that the min.sizes to not exceed the screen resolution.
Definition: guiutility.cpp:816
static QString metricsInfo()
Some info about font metrics.
Definition: guiutility.cpp:791
static QWidget * mainApplicationWidget()
Main application window widget.
Definition: guiutility.cpp:92
static QStringList closeAllModalWidgetsGetTitles()
Close all modal widgets and get titles.
static QFont currentFont()
Main window font or default font.
Definition: guiutility.cpp:729
static bool toggleStayOnTop(QWidget *widget)
Toggle window flags / stay on top.
Definition: guiutility.cpp:573
Own splash screen.
Definition: splashscreen.h:22
Reads and provides style sheets.
static const QString & fileNameStandardWidget()
File name for standard widgets.
bool updateFont(const QFont &font)
Update the fonts.
static void setQSysInfoProperties(QWidget *widget, bool withChildWidgets)
Set QSysInfo properties for given widget (which can be used in stylesheet)
bool read()
Read the *.qss files.
static const QString & fileNameAndPathStandardWidget()
Full file path and name for standard widgets.
void styleSheetsChanged()
Sheets have been changed.
QString styles(const QStringList &fileNames) const
Multiple styles concatenated.
static const QString & fileNameFonts()
File name fonts.qss.
Direct acccess to main window`s status bar, info bar and such.
virtual bool displayInOverlayWindow(const swift::misc::CStatusMessage &message, std::chrono::milliseconds timeout=std::chrono::milliseconds(0))
Display in overlay window.
virtual bool displayInStatusBar(const swift::misc::CStatusMessage &message)
Display in status bar.
Setup dialog, if loading the boostrap file fails.
bool isNewVersionAvailable() const
A new version existing?
Application
Enumeration of application roles.
QString toJsonString(QJsonDocument::JsonFormat format=QJsonDocument::Indented) const
Convenience function JSON as string.
Class for emitting a log message.
Definition: logmessage.h:27
Value class for matching log messages based on their categories.
Definition: logpattern.h:49
CLogPattern withSeverity(CStatusMessage::StatusSeverity severity) const
Returns a CLogPattern which will match the same messages as this one, but only with a given severity.
Definition: logpattern.cpp:130
A helper class for subscribing to log messages matching a particular pattern, with the ability to cha...
Definition: loghandler.h:220
void changeSubscription(const CLogPattern &pattern)
Change the pattern which you want to subscribe to.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
bool isEmpty() const
Message empty.
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, providing a format string, and adding the validation category.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Value object encapsulating a list of property indexes.
size_type size() const
Returns number of elements in the sequence.
Definition: sequence.h:273
bool isEmpty() const
Synonym for empty.
Definition: sequence.h:285
Streamable status message, e.g.
QString getMessage() const
Message.
Status messages, e.g. from Core -> GUI.
QString toHtml(const CPropertyIndexList &indexes=simpleHtmlOutput()) const
Specialized version to convert to HTML.
bool hasErrorMessages() const
Error messages.
Value object encapsulating a list of info objects.
Definition: dbinfolist.h:27
Update info, i.e. artifacts and distributions.
Definition: updateinfo.h:24
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
Definition: url.h:27
bool isEmpty() const
Empty.
Definition: url.cpp:54
CUrl withAppendedPath(const QString &path) const
Append path.
Definition: url.cpp:115
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
size_t qHash(const std::string &key, uint seed)
std::string qHash
Definition: metaclass.h:84
Core data traits (aka cached values) and classes.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:14
GUI related classes.
void registerMetadata()
Register metadata for GUI.
Free functions in swift::misc.
QString getAllUserMetatypesTypes(const QString &separator)
Get all user metatypes.
QMetaObject::Connection connectOnce(T *sender, F signal, U *receiver, G &&slot, Qt::ConnectionType type=Qt::AutoConnection)
Wrapper around QObject::connect which disconnects after the signal has been emitted once.
Definition: slot.h:27
SWIFT_MISC_EXPORT bool stringCompare(const QString &c1, const QString &c2, Qt::CaseSensitivity cs)
String compare.
QString className(const QObject *object)
Class name as from QMetaObject::className with namespace.
QString applicationName()
Get application name.
Definition: filelogger.cpp:24
void triggered(bool checked)
void aboutQt()
QStyle * setStyle(const QString &style)
QStyle * style()
bool isEmpty() const const
QStringList names() const const
QString valueName() const const
bool isSet(const QCommandLineOption &option) const const
QString applicationFilePath()
void processEvents(QEventLoop::ProcessEventsFlags flags)
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
bool openUrl(const QUrl &url)
virtual void accept()
virtual int exec()
void setModal(bool modal)
QString toNativeSeparators(const QString &pathName)
void ignore()
QString family() const const
int pointSize() const const
void setFamily(const QString &family)
void setPointSize(int pointSize)
void setStretch(int factor)
int averageCharWidth() const const
void lastWindowClosed()
QWindow * modalWindow()
Qt::KeyboardModifiers queryKeyboardModifiers()
void setWindowIcon(const QIcon &icon)
qsizetype count() const const
T & first()
bool restoreState(const QByteArray &state, int version)
QByteArray saveState(int version) const const
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
QAction * addMenu(QMenu *menu)
QAction * addSeparator()
void setIcon(const QIcon &icon)
QPushButton * addButton(QMessageBox::StandardButton button)
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void setDetailedText(const QString &text)
virtual int exec() override
void setInformativeText(const QString &text)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QList< T > findChildren(QAnyStringView name, Qt::FindChildOptions options) const const
virtual const QMetaObject * metaObject() const const
QObject * parent() const const
void setObjectName(QAnyStringView name)
bool isNull() const const
QPixmap scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
QString fileName() const const
void remove(QAnyStringView key)
void setValue(QAnyStringView key, const QVariant &value)
QVariant value(QAnyStringView key) const const
void setHeight(int height)
void setWidth(int width)
qreal height() const const
qreal width() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
qsizetype length() const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
SP_TitleBarMaxButton
QStyle * create(const QString &key)
QStringList keys()
CaseInsensitive
QueuedConnection
FindDirectChildrenOnly
typedef KeyboardModifiers
WindowState
typedef WindowFlags
QUrl fromLocalFile(const QString &localFile)
QByteArray toByteArray() const const
void setWindowIconText(const QString &)
void activateWindow()
bool close()
QFontMetrics fontMetrics() const const
void lower()
bool isMaximized() const const
bool isMinimized() const const
void raise()
bool restoreGeometry(const QByteArray &geometry)
QByteArray saveGeometry() const const
void showMinimized()
void showNormal()
void setStyleSheet(const QString &styleSheet)
QWindow * windowHandle() const const
void setWindowIcon(const QIcon &icon)
void setWindowTitle(const QString &)
void raise()
QScreen * screen() const const
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26