6 #include <QAbstractItemModel>
7 #include <QApplication>
10 #include <QGraphicsOpacityEffect>
11 #include <QJsonDocument>
12 #include <QJsonObject>
16 #include <QLayoutItem>
19 #include <QMainWindow>
24 #include <QPropertyAnimation>
25 #include <QRegularExpression>
27 #include <QStringBuilder>
29 #include <QThreadStorage>
53 QWidget *CGuiUtility::s_mainApplicationWidget =
nullptr;
57 const QWidgetList tlw = topLevelApplicationWidgetsWithName();
58 for (QWidget *w : tlw)
62 if (!mw) {
continue; }
70 QWidget *mainApplicationWidgetSearch()
76 const QWidgetList tlw = CGuiUtility::topLevelApplicationWidgetsWithName();
77 for (QWidget *w : tlw)
79 QMainWindow *qmw = qobject_cast<QMainWindow *>(w);
80 if (!qmw) {
continue; }
81 if (!qmw->parentWidget()) {
return qmw; }
87 void CGuiUtility::registerMainApplicationWidget(QWidget *mainWidget)
89 CGuiUtility::s_mainApplicationWidget = mainWidget;
92 QWidget *CGuiUtility::mainApplicationWidget()
94 if (!CGuiUtility::s_mainApplicationWidget)
96 CGuiUtility::s_mainApplicationWidget = Private::mainApplicationWidgetSearch();
98 return CGuiUtility::s_mainApplicationWidget;
101 qreal CGuiUtility::mainApplicationWidgetPixelRatio()
103 const QWidget *mw = CGuiUtility::mainApplicationWidget();
104 if (mw) {
return mw->devicePixelRatio(); }
108 QSize CGuiUtility::desktopSize()
110 const QWidget *mw = CGuiUtility::mainApplicationWidget();
111 if (!mw)
return QGuiApplication::primaryScreen()->size();
113 const QWindow *win = mw->windowHandle();
114 if (!win)
return QGuiApplication::primaryScreen()->size();
122 QSize windowsGetDesktopResolution()
140 const HWND hDesktop = GetDesktopWindow();
141 HMONITOR monitor = MonitorFromWindow(hDesktop, MONITOR_DEFAULTTONEAREST);
143 info.cbSize =
sizeof(MONITORINFO);
144 GetMonitorInfo(monitor, &info);
151 const int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
152 const int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;
153 return QSize(monitor_height, monitor_width);
165 QSize CGuiUtility::physicalScreenSizeOs()
168 return Private::windowsGetDesktopResolution();
169 #elif defined(Q_OS_MAC)
171 #elif defined(Q_OS_LINUX)
178 bool CGuiUtility::isMainWindowFrameless()
184 QString CGuiUtility::screenInformation(
const QString &separator)
186 const QSize ps = physicalScreenSizeOs();
187 QString i = u
"Number of screens: " % QString::number(QGuiApplication::screens().size()) % separator %
188 u
"Primary screen: " % QGuiApplication::primaryScreen()->name() % separator %
189 u
"QT_AUTO_SCREEN_SCALE_FACTOR: " % qgetenv(
"QT_AUTO_SCREEN_SCALE_FACTOR") % separator %
190 u
"QT_SCALE_FACTOR: " % qgetenv(
"QT_SCALE_FACTOR") % separator % u
"QT_ENABLE_HIGHDPI_SCALING: " %
191 qgetenv(
"QT_ENABLE_HIGHDPI_SCALING") % separator % u
"QT_SCALE_FACTOR_ROUNDING_POLICY: " %
192 qgetenv(
"QT_SCALE_FACTOR_ROUNDING_POLICY") % separator % u
"QT_SCREEN_SCALE_FACTORS: " %
193 qgetenv(
"QT_SCREEN_SCALE_FACTORS") % separator % u
"OS screen res." % QString::number(ps.width()) %
194 u
"/" % QString::number(ps.height()) % separator;
196 for (
const QScreen *screen : QGuiApplication::screens())
198 i += separator % u
"Information for screen: " % screen->name() % separator % u
"Available geometry: " %
199 rectAsString(screen->availableGeometry()) % separator % u
"Available size: " %
200 sizeAsString(screen->availableSize()) % separator % u
"Available virtual geometry: " %
201 rectAsString(screen->availableVirtualGeometry()) % separator % u
"Available virtual size: " %
202 sizeAsString(screen->availableVirtualSize()) % separator % u
"Device ratio: " %
203 QString::number(screen->devicePixelRatio()) % separator % u
"Depth: " %
204 QString::number(screen->depth()) % u
"bits" % separator % u
"Geometry: " %
205 rectAsString(screen->geometry()) % separator % u
"Logical DPI: " %
206 QString::number(screen->logicalDotsPerInch()) % separator % u
"Logical DPI X: " %
207 QString::number(screen->logicalDotsPerInchX()) % separator % u
"Logical DPI Y: " %
208 QString::number(screen->logicalDotsPerInchY()) % separator % u
"Orientation: " %
209 orientationAsString(screen->orientation()) % separator % u
"Physical DPI: " %
210 QString::number(screen->physicalDotsPerInch()) % separator % u
"Physical DPI X: " %
211 QString::number(screen->physicalDotsPerInchX()) % separator % u
"Physical DPI Y: " %
212 QString::number(screen->physicalDotsPerInchY()) % separator % u
"Physical size: " %
213 sizeAsString(screen->physicalSize()) % u
"mm" % separator % u
"Primary orientation: " %
214 orientationAsString(screen->primaryOrientation()) % separator % u
"Refresh rate: " %
215 QString::number(screen->refreshRate()) % u
"Hz" % u
"Size: " % sizeAsString(screen->size()) % separator %
216 u
"Virtual geometry: " % rectAsString(screen->virtualGeometry()) % separator % u
"Virtual size: " %
217 sizeAsString(screen->virtualSize());
222 const QString &CGuiUtility::orientationAsString(Qt::ScreenOrientation orientation)
224 static const QString pr(
"Primary");
225 static const QString la(
"Landscape");
226 static const QString po(
"Portrait");
227 static const QString il(
"Inverted landscape");
228 static const QString ip(
"Inverted portrait");
232 case Qt::PrimaryOrientation:
return pr;
233 case Qt::LandscapeOrientation:
return la;
234 case Qt::PortraitOrientation:
return po;
235 case Qt::InvertedLandscapeOrientation:
return il;
236 case Qt::InvertedPortraitOrientation:
return ip;
240 static const QString unknown(
"Unknown");
244 QString CGuiUtility::rectAsString(
const QRect &rect)
246 return QStringLiteral(
"x: %1 y: %2 w: %3 h: %4")
253 QString CGuiUtility::rectAsString(
const QRectF &rect)
255 return QStringLiteral(
"x: %1 y: %2 w: %3 h: %4")
262 QString CGuiUtility::sizeAsString(
const QSize &size)
264 return QStringLiteral(
"w: %1 h: %2").arg(size.width()).arg(size.height());
267 QString CGuiUtility::sizeAsString(
const QSizeF &size)
269 return QStringLiteral(
"w: %1 h: %2").arg(size.width()).arg(size.height());
272 static QThreadStorage<QRegularExpression> tsRegex;
274 bool CGuiUtility::lenientTitleComparison(
const QString &title,
const QString &comparison)
276 if (title == comparison) {
return true; }
278 QString t(title.trimmed().toLower().simplified());
279 QString c(comparison.trimmed().toLower().simplified());
283 SWIFT_VERIFY_X(!c.isEmpty(), Q_FUNC_INFO,
"missing comparison value");
284 if (t.isEmpty() || c.isEmpty()) {
return false; }
287 if (t == c) {
return true; }
290 if (!tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression(
"[^a-z0-9\\s]")); }
291 const QRegularExpression ®exp = tsRegex.localData();
292 t = t.remove(regexp);
293 c = c.remove(regexp);
297 bool CGuiUtility::setComboBoxValueByStartingString(QComboBox *box,
const QString &candidate,
298 const QString &unspecified)
300 if (!box) {
return false; }
301 if (!candidate.isEmpty())
303 for (
int i = 0; i < box->count(); i++)
305 const QString t(box->itemText(i));
306 if (t.startsWith(candidate, Qt::CaseInsensitive))
308 box->setCurrentIndex(i);
315 if (unspecified.isEmpty()) {
return false; }
316 for (
int i = 0; i < box->count(); i++)
318 const QString t(box->itemText(i));
319 if (t.startsWith(unspecified, Qt::CaseInsensitive))
321 box->setCurrentIndex(i);
328 bool CGuiUtility::setComboBoxValueByContainingString(QComboBox *box,
const QString &candidate,
329 const QString &unspecified)
331 if (!box) {
return false; }
332 if (!candidate.isEmpty())
334 const int ci = box->currentIndex();
335 for (
int i = 0; i < box->count(); i++)
337 const QString t(box->itemText(i));
338 if (t.contains(candidate, Qt::CaseInsensitive))
340 if (ci == i) {
return true; }
341 box->setCurrentIndex(i);
348 if (unspecified.isEmpty()) {
return false; }
349 const int ci = box->currentIndex();
350 for (
int i = 0; i < box->count(); i++)
352 const QString t(box->itemText(i));
353 if (t.contains(unspecified, Qt::CaseInsensitive))
355 if (ci == i) {
return true; }
356 box->setCurrentIndex(i);
363 bool CGuiUtility::hasSwiftVariantMimeType(
const QMimeData *mime)
365 return mime && mime->hasFormat(swiftJsonDragAndDropMimeType());
368 CVariant CGuiUtility::fromSwiftDragAndDropData(
const QMimeData *mime)
370 if (!hasSwiftVariantMimeType(mime)) {
return CVariant(); }
371 return CGuiUtility::fromSwiftDragAndDropData(mime->data(swiftJsonDragAndDropMimeType()));
374 CVariant CGuiUtility::fromSwiftDragAndDropData(
const QByteArray &utf8Data)
376 if (utf8Data.isEmpty()) {
return CVariant(); }
377 const QJsonDocument jsonDoc(QJsonDocument::fromJson(utf8Data));
378 const QJsonObject jsonObj(jsonDoc.object());
379 const QString typeName(jsonObj.value(
"type").toString());
380 const int typeId = QMetaType::type(qPrintable(typeName));
383 if (typeName.isEmpty() || typeId == QMetaType::UnknownType) {
return CVariant(); }
391 int CGuiUtility::metaTypeIdFromSwiftDragAndDropData(
const QMimeData *mime)
393 constexpr
int Unknown =
static_cast<int>(QMetaType::UnknownType);
395 if (!hasSwiftVariantMimeType(mime)) {
return Unknown; }
396 static const QJsonObject jsonObj(QJsonDocument::fromJson(mime->data(swiftJsonDragAndDropMimeType())).
object());
397 Q_ASSERT_X(!jsonObj.isEmpty(), Q_FUNC_INFO,
"Empty JSON object");
398 const QString typeName(jsonObj.value(
"type").toString());
399 if (typeName.isEmpty()) {
return Unknown; }
400 const int typeId = QMetaType::type(qPrintable(typeName));
404 const QString &CGuiUtility::swiftJsonDragAndDropMimeType()
406 static const QString m(
"text/json/swift");
410 QFileInfo CGuiUtility::representedMimeFile(
const QMimeData *mime)
412 if (!mime->hasText()) {
return QFileInfo(); }
413 const QString candidate = mime->text();
414 if (candidate.isEmpty()) {
return QFileInfo(); }
415 if (!candidate.contains(
"://")) {
return QFileInfo(candidate); }
417 const QString localFile = url.toLocalFile();
418 return QFileInfo(localFile);
421 bool CGuiUtility::isMimeRepresentingReadableFile(
const QMimeData *mime)
423 const QFileInfo fi = CGuiUtility::representedMimeFile(mime);
424 return fi.isReadable();
427 bool CGuiUtility::isMimeRepresentingReadableJsonFile(
const QMimeData *mime)
429 const QFileInfo fi = CGuiUtility::representedMimeFile(mime);
430 if (!fi.isReadable()) {
return false; }
431 const QString fn = fi.fileName();
432 return fn.endsWith(
"json", Qt::CaseInsensitive);
437 return nextOverlayMessageWidget<COverlayMessagesFrame>(widget, maxLevels);
442 return nextOverlayMessageWidget<COverlayMessagesTabWidget>(widget, maxLevels);
447 return nextOverlayMessageWidget<COverlayMessagesWizardPage>(widget, maxLevels);
450 void CGuiUtility::checkBoxReadOnly(QCheckBox *checkBox,
bool readOnly)
452 static const QCheckBox defaultBox;
454 if (!checkBox) {
return; }
456 static const QString background(
457 "background: rgb(40,40,40)");
460 checkBox->setAttribute(Qt::WA_TransparentForMouseEvents);
461 checkBox->setFocusPolicy(Qt::NoFocus);
465 checkBox->setStyleSheet(background);
469 checkBox->setAttribute(Qt::WA_TransparentForMouseEvents,
470 defaultBox.testAttribute(Qt::WA_TransparentForMouseEvents));
471 checkBox->setFocusPolicy(defaultBox.focusPolicy());
472 checkBox->setStyleSheet(
"");
476 void CGuiUtility::checkBoxesReadOnly(QWidget *parent,
bool readOnly)
478 if (!parent) {
return; }
479 QList<QCheckBox *> allCheckBoxes = parent->findChildren<QCheckBox *>();
480 for (QCheckBox *cb : allCheckBoxes) { CGuiUtility::checkBoxReadOnly(cb, readOnly); }
483 void CGuiUtility::tempUnhidePassword(QLineEdit *lineEdit,
int unhideMs)
485 if (!lineEdit) {
return; }
486 if (lineEdit->text().isEmpty()) {
return; }
487 if (lineEdit->echoMode() != QLineEdit::Password && lineEdit->echoMode() != QLineEdit::PasswordEchoOnEdit)
491 const QLineEdit::EchoMode mode = lineEdit->echoMode();
492 lineEdit->setEchoMode(QLineEdit::Normal);
493 QPointer<QLineEdit> qpLineEdit(lineEdit);
495 if (qpLineEdit) { qpLineEdit->setEchoMode(mode); }
499 QWidgetList CGuiUtility::topLevelApplicationWidgetsWithName()
501 QWidgetList tlw = QApplication::topLevelWidgets();
503 for (QWidget *w : tlw)
505 if (w->objectName().isEmpty()) {
continue; }
511 QPoint CGuiUtility::mainWidgetGlobalPosition()
513 QWidget *mw = CGuiUtility::mainApplicationWidget();
514 if (mw) {
return mw->pos(); }
518 if (!mfw || !mfw->
getWidget()) {
return QPoint(); }
522 QString CGuiUtility::replaceTabCountValue(
const QString &oldName,
int count)
524 const QString v = QString(
" (").append(QString::number(count)).append(
")");
525 if (oldName.isEmpty()) {
return v; }
526 int index = oldName.lastIndexOf(
'(');
527 if (index == 0) {
return v; }
528 if (index < 0) {
return QString(oldName).trimmed().append(v); }
529 return QString(oldName.left(index)).trimmed().append(v);
532 void CGuiUtility::deleteLayout(QLayout *layout,
bool deleteWidgets)
535 if (!layout) {
return; }
536 QLayoutItem *item {
nullptr };
537 while ((item = layout->takeAt(0)))
539 QLayout *sublayout {
nullptr };
540 QWidget *widget {
nullptr };
541 if ((sublayout = item->layout())) { deleteLayout(sublayout, deleteWidgets); }
542 else if ((widget = item->widget()))
545 if (deleteWidgets) {
delete widget; }
547 else {
delete item; }
554 bool CGuiUtility::staysOnTop(QWidget *widget)
556 if (!widget) {
return false; }
557 const Qt::WindowFlags flags = widget->windowFlags();
558 return Qt::WindowStaysOnTopHint & flags;
561 QTabWidget *CGuiUtility::parentTabWidget(QWidget *widget,
int maxLevels)
565 widget = widget->parentWidget();
566 if (!widget) {
return nullptr; }
567 QTabWidget *tw = qobject_cast<QTabWidget *>(widget);
568 if (tw) {
return tw; }
571 while (level < maxLevels);
575 bool CGuiUtility::toggleStayOnTop(QWidget *widget)
577 if (!widget) {
return false; }
578 Qt::WindowFlags flags = widget->windowFlags();
579 if (Qt::WindowStaysOnTopHint & flags)
581 flags &= ~Qt::WindowStaysOnTopHint;
586 flags &= ~Qt::WindowStaysOnBottomHint;
587 flags |= Qt::WindowStaysOnTopHint;
589 widget->setWindowFlags(flags);
591 return Qt::WindowStaysOnTopHint & flags;
594 bool CGuiUtility::stayOnTop(
bool onTop, QWidget *widget)
596 if (!widget) {
return false; }
597 Qt::WindowFlags flags = widget->windowFlags();
600 flags &= ~Qt::WindowStaysOnBottomHint;
601 flags |= Qt::WindowStaysOnTopHint;
605 flags &= ~Qt::WindowStaysOnTopHint;
608 widget->setWindowFlags(flags);
613 QString CGuiUtility::marginsToString(
const QMargins &margins)
615 return QStringLiteral(
"%1:%2:%3:%4")
618 .arg(margins.right())
619 .arg(margins.bottom());
622 QMargins CGuiUtility::stringToMargins(
const QString &str)
624 const QStringList parts = str.split(
":");
625 Q_ASSERT_X(parts.size() == 4, Q_FUNC_INFO,
"malformed");
627 const int l = parts.at(0).toInt(&ok);
628 Q_ASSERT_X(ok, Q_FUNC_INFO,
"malformed number");
629 const int t = parts.at(1).toInt(&ok);
630 Q_ASSERT_X(ok, Q_FUNC_INFO,
"malformed number");
631 const int r = parts.at(2).toInt(&ok);
632 Q_ASSERT_X(ok, Q_FUNC_INFO,
"malformed number");
633 const int b = parts.at(3).toInt(&ok);
634 Q_ASSERT_X(ok, Q_FUNC_INFO,
"malformed number");
636 return QMargins(l, t, r, b);
639 QList<int> CGuiUtility::indexToUniqueRows(
const QModelIndexList &indexes)
642 for (
const QModelIndex &i : indexes)
644 const int r = i.row();
645 if (rows.contains(r)) {
continue; }
651 int CGuiUtility::clearModel(QAbstractItemModel *model)
653 if (!model) {
return 0; }
654 const int count = model->rowCount();
655 if (count < 1) {
return 0; }
656 model->removeRows(0, count);
660 bool CGuiUtility::isTopLevelWidget(QWidget *widget)
662 if (!widget) {
return false; }
663 return QApplication::topLevelWidgets().contains(widget);
666 bool CGuiUtility::isTopLevelWindow(QWidget *widget)
668 if (!widget) {
return false; }
669 if (!widget->isWindow()) {
return false; }
670 return QApplication::topLevelWidgets().contains(widget);
673 bool CGuiUtility::isQMainWindow(
const QWidget *widget)
675 if (!widget) {
return false; }
676 const QMainWindow *mw = qobject_cast<const QMainWindow *>(widget);
680 bool CGuiUtility::isDialog(
const QWidget *widget)
682 if (!widget) {
return false; }
683 const QDialog *mw = qobject_cast<const QDialog *>(widget);
687 void CGuiUtility::disableMinMaxCloseButtons(QWidget *window)
689 if (!window->windowFlags().testFlag(Qt::CustomizeWindowHint))
691 window->setWindowFlag(Qt::CustomizeWindowHint);
692 window->setWindowFlag(Qt::WindowTitleHint);
694 window->setWindowFlag(Qt::WindowMinMaxButtonsHint,
false);
695 window->setWindowFlag(Qt::WindowCloseButtonHint,
false);
698 QGraphicsOpacityEffect *CGuiUtility::fadeInWidget(
int durationMs, QWidget *widget,
double startValue,
703 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect(widget);
704 widget->setGraphicsEffect(effect);
705 QPropertyAnimation *a =
new QPropertyAnimation(effect,
"opacity");
706 a->setDuration(durationMs);
707 a->setStartValue(startValue);
708 a->setEndValue(endValue);
709 a->setEasingCurve(QEasingCurve::InBack);
710 a->start(QPropertyAnimation::DeleteWhenStopped);
714 QGraphicsOpacityEffect *CGuiUtility::fadeOutWidget(
int durationMs, QWidget *widget,
double startValue,
718 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect(widget);
719 widget->setGraphicsEffect(effect);
720 QPropertyAnimation *a =
new QPropertyAnimation(effect,
"opacity");
721 a->setDuration(durationMs);
722 a->setStartValue(startValue);
723 a->setEndValue(endValue);
724 a->setEasingCurve(QEasingCurve::OutBack);
725 a->start(QPropertyAnimation::DeleteWhenStopped);
729 QFontMetrics CGuiUtility::currentFontMetrics()
731 const QWidget *w = CGuiUtility::mainApplicationWidget();
732 if (w) {
return w->fontMetrics(); }
733 return QApplication::fontMetrics();
736 QFontMetricsF CGuiUtility::currentFontMetricsF() {
return QFontMetricsF(CGuiUtility::currentFontMetrics()); }
738 QFont CGuiUtility::currentFont()
740 const QWidget *w = CGuiUtility::mainApplicationWidget();
741 if (w) {
return w->font(); }
742 return QApplication::font();
745 QSizeF CGuiUtility::fontMetrics80Chars(
bool withRatio)
748 static const QString s(
"01234567890123456789012345678901234567890123456789012345678901234567890123456789");
749 const QFontMetricsF fm = CGuiUtility::currentFontMetricsF();
750 const qreal scale = withRatio ? CGuiUtility::mainApplicationWidgetPixelRatio() : 1.0;
751 const QSizeF size = fm.size(Qt::TextSingleLine, s);
755 QSizeF CGuiUtility::fontMetricsLazyDog43Chars(
bool withRatio)
758 static const QString s(
"The quick brown fox jumps over the lazy dog");
759 const QFontMetricsF fm = CGuiUtility::currentFontMetrics();
760 const qreal scale = withRatio ? CGuiUtility::mainApplicationWidgetPixelRatio() : 1.0;
761 const QSizeF size = fm.size(Qt::TextSingleLine, s);
765 QSizeF CGuiUtility::fontMetricsEstimateSize(
int xCharacters,
int yCharacters,
bool withRatio)
770 const QSizeF s1 = CGuiUtility::fontMetrics80Chars(withRatio);
771 const QSizeF s2 = CGuiUtility::fontMetricsLazyDog43Chars(withRatio);
772 const QSizeF s = s1 + s2;
773 const qreal w = s.width() * xCharacters / 123;
774 const qreal h = s.height() * yCharacters / 2;
778 void CGuiUtility::centerWidget(QWidget *widget)
780 const QPoint point(widget->width() / 2.0, 0);
781 const QScreen *pScreen = QGuiApplication::screenAt(widget->mapToGlobal(point));
782 const QRect screenGeometry = pScreen->availableGeometry();
783 const int x = (screenGeometry.width() - widget->width()) / 2;
784 const int y = (screenGeometry.height() - widget->height()) / 2;
788 void CGuiUtility::centerWidget(QWidget *widget, QWidget *host)
790 if (!host) { host = widget->parentWidget(); }
794 const QRect hostRect = host->geometry();
795 widget->move(hostRect.center() - widget->rect().center());
797 else { CGuiUtility::centerWidget(widget); }
800 QString CGuiUtility::metricsInfo()
802 static const QString s(
"%1 %2 %3 | 80 chars: w%4 h%5 | 43 chars: w%6 h%7");
803 const QSizeF s80 = CGuiUtility::fontMetrics80Chars();
804 const QSizeF s43 = CGuiUtility::fontMetricsLazyDog43Chars();
807 QString desktop(
"-");
809 const QWidget *mainWidget = CGuiUtility::mainApplicationWidget();
812 const QSize sd = QGuiApplication::primaryScreen()->geometry().size();
813 desktop = QStringLiteral(
"Desktop w%1 w%2").arg(sd.width()).arg(sd.height());
814 ratio = QStringLiteral(
"ratio: %1").arg(mainWidget->devicePixelRatioF());
816 return s.arg(desktop)
817 .arg(CGuiUtility::isUsingHighDpiScreenSupport() ?
"hi DPI" :
"-")
825 bool CGuiUtility::isUsingHighDpiScreenSupport()
827 const QByteArray v = qgetenv(
"QT_AUTO_SCREEN_SCALE_FACTOR");
833 void CGuiUtility::forceStyleSheetUpdate(QWidget *widget)
835 if (!widget) {
return; }
836 widget->setStyleSheet(widget->styleSheet());
839 void CGuiUtility::superviseMainWindowMinSizes(qreal wRatio, qreal hRatio)
841 QWidget *w = CGuiUtility::mainApplicationWidget();
843 const QSize s = CGuiUtility::desktopSize();
844 const int minW = qRound(wRatio * s.width());
845 const int minH = qRound(hRatio * s.height());
846 w->setMinimumWidth(qMin(minW, w->minimumWidth()));
847 w->setMinimumHeight(qMin(minH, w->minimumHeight()));
850 QString CGuiUtility::asSimpleHtmlImageWidth(
const CIcon &icon,
int width)
855 if (width < 0) {
return QStringLiteral(
"<img src=\"%1\">").arg(p); }
856 return QStringLiteral(
"<img src=\"%1\" width=%2>").arg(p, QString::number(width));
859 QString CGuiUtility::asSimpleHtmlImageHeight(
const CIcon &icon,
int height)
861 if (height < 0) {
return CGuiUtility::asSimpleHtmlImageWidth(icon); }
865 return QStringLiteral(
"<img src=\"%1\" height=%2>").arg(p, QString::number(height));
868 QDialog *CGuiUtility::findParentDialog(QWidget *widget)
870 if (CGuiUtility::isDialog(widget)) {
return qobject_cast<QDialog *>(widget); }
871 while (widget->parent())
873 widget = widget->parentWidget();
874 if (CGuiUtility::isDialog(widget)) {
return qobject_cast<QDialog *>(widget); }
879 QDialog *CGuiUtility::findParentDialog(QWidget *widget,
int maxLevel)
881 if (CGuiUtility::isDialog(widget)) {
return qobject_cast<QDialog *>(widget); }
883 while (widget->parent())
886 if (level > maxLevel) {
return nullptr; }
887 widget = widget->parentWidget();
888 if (CGuiUtility::isDialog(widget)) {
return qobject_cast<QDialog *>(widget); }
893 void CGuiUtility::setElidedText(QLabel *label,
const QString &text, Qt::TextElideMode mode)
895 if (!label) {
return; }
897 label->setToolTip(text);
898 if (mode == Qt::ElideNone)
900 label->setText(text);
904 const QFontMetrics metrics(label->font());
905 const int width = qMax(label->width() - 2, 0);
906 const QString clippedText = metrics.elidedText(text, mode, width);
907 label->setText(clippedText);
910 void CGuiUtility::setElidedText(QLabel *label,
const QString &shortText,
const QString &longText,
911 Qt::TextElideMode mode)
913 if (!label) {
return; }
914 if (shortText.isEmpty())
916 CGuiUtility::setElidedText(label, longText, mode);
919 if (longText.isEmpty())
921 CGuiUtility::setElidedText(label, shortText, mode);
925 label->setToolTip(longText);
926 const QFontMetrics metrics(label->font());
927 const int width = qMax(label->width() - 2, 0);
928 const int wl = metrics.horizontalAdvance(longText);
931 label->setText(longText);
934 if (qRound(wl * 0.85) > wl)
936 const QString clippedText = metrics.elidedText(longText, mode, width);
937 label->setText(clippedText);
940 const QString clippedText = metrics.elidedText(shortText, mode, width);
941 label->setText(clippedText);
944 void CGuiUtility::setWizardButtonWidths(QWizard *wizard)
946 if (!wizard) {
return; }
948 const int minW = qMax(qRound(CGuiUtility::fontMetricsLazyDog43Chars(
true).width() * 6.0 / 43.0), 80);
949 if (wizard->button(QWizard::BackButton)) { wizard->button(QWizard::BackButton)->setMinimumWidth(minW); }
950 if (wizard->button(QWizard::NextButton)) { wizard->button(QWizard::NextButton)->setMinimumWidth(minW); }
951 if (wizard->button(QWizard::CancelButton)) { wizard->button(QWizard::CancelButton)->setMinimumWidth(minW); }
952 if (wizard->button(QWizard::FinishButton)) { wizard->button(QWizard::FinishButton)->setMinimumWidth(minW); }
953 if (wizard->button(QWizard::CustomButton1)) { wizard->button(QWizard::CustomButton1)->setMinimumWidth(minW); }
954 if (wizard->button(QWizard::CustomButton2)) { wizard->button(QWizard::CustomButton2)->setMinimumWidth(minW); }
955 if (wizard->button(QWizard::CustomButton3)) { wizard->button(QWizard::CustomButton3)->setMinimumWidth(minW); }
958 QWidgetList CGuiUtility::getAllModallWidgets()
960 const QWidgetList widgets = QApplication::topLevelWidgets();
961 QWidgetList openWidgets;
962 for (QWidget *w : widgets)
964 if (w->isModal()) { openWidgets.push_back(w); }
969 QStringList CGuiUtility::getAllWidgetTitles(
const QWidgetList &widgets)
972 for (
const QWidget *w : widgets)
974 if (!w) {
continue; }
975 if (!w->windowTitle().isEmpty()) { titles.push_back(w->windowTitle()); }
976 else { titles.push_back(QStringLiteral(
"name: ") % w->objectName()); }
981 QStringList CGuiUtility::getAllWidgetNames(
const QWidgetList &widgets)
984 for (
const QWidget *w : widgets)
986 if (!w) {
continue; }
987 titles.push_back(QStringLiteral(
"name: ") % w->objectName());
992 QList<QDockWidget *> CGuiUtility::getAllDockWidgets(QWidget *parent,
bool floatingOnly)
994 QList<QDockWidget *> docks;
997 const auto children = parent->findChildren<QDockWidget *>();
998 for (QDockWidget *w : children)
1000 if (!w) {
continue; }
1001 if (!floatingOnly || w->isFloating()) { docks.push_back(w); }
1007 QList<QDockWidget *> CGuiUtility::getAllDockWidgets(QWindow *parent,
bool floatingOnly)
1009 QList<QDockWidget *> docks;
1012 const auto children = parent->findChildren<QDockWidget *>();
1013 for (QDockWidget *w : children)
1015 if (!w) {
continue; }
1016 if (!floatingOnly || w->isFloating()) { docks.push_back(w); }
1022 QWidgetList CGuiUtility::closeAllModalWidgets()
1024 QWidgetList modals = getAllModallWidgets();
1025 for (QWidget *w : modals)
1027 if (!w) {
continue; }
1033 QStringList CGuiUtility::closeAllModalWidgetsGetTitles()
1035 const QWidgetList modals = getAllModallWidgets();
1037 for (QWidget *w : modals)
1039 if (!w) {
continue; }
1040 titles << w->windowTitle();
1046 QList<QDockWidget *> CGuiUtility::closeAllDockWidgets(QWidget *parent,
bool floatingOnly)
1048 QList<QDockWidget *> dws = getAllDockWidgets(parent, floatingOnly);
1049 for (QWidget *w : dws)
1051 if (!w) {
continue; }
1057 QList<QDockWidget *> CGuiUtility::closeAllDockWidgets(QWindow *parent,
bool floatingOnly)
1059 QList<QDockWidget *> dws = getAllDockWidgets(parent, floatingOnly);
1060 for (QWidget *w : dws)
1062 if (!w) {
continue; }
1068 QStringList CGuiUtility::closeAllDockWidgetsGetTitles(QWidget *parent,
bool floatingOnly)
1070 const QList<QDockWidget *> dws = getAllDockWidgets(parent, floatingOnly);
1072 for (QWidget *w : dws)
1074 if (!w) {
continue; }
1075 titles << w->windowTitle();
1081 QStringList CGuiUtility::closeAllDockWidgetsGetTitles(QWindow *parent,
bool floatingOnly)
1083 const QList<QDockWidget *> dws = getAllDockWidgets(parent, floatingOnly);
1085 for (QWidget *w : dws)
1087 if (!w) {
continue; }
1088 titles << w->windowTitle();
1094 QStringList CGuiUtility::deleteLaterAllDockWidgetsGetTitles(QWidget *parent,
bool floatingOnly)
1096 const QList<QDockWidget *> dws = getAllDockWidgets(parent, floatingOnly);
1098 for (QWidget *w : dws)
1100 if (!w) {
continue; }
1101 titles << w->windowTitle();
Main window which can be frameless.
bool isMainApplicationWindow() const
Is main application, explicitly set.
QWidget * getWidget() const
Corresponding QMainWindow.
bool isFrameless() const
Frameless?
Using this class provides a QFrame with the overlay functionality already integrated.
Using this class provides a QWizardPage with the overlay functionality already integrated.
Value object for icons. An icon is stored in the global icon repository and identified by its index....
bool hasFileResourcePath() const
Resource path available?
const QString & getFileResourcePath() const
Resource path if any.
Streamable status message, e.g.
bool isFailure() const
Operation considered unsuccessful.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
CStatusMessage convertFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call convertFromJson, catch any CJsonException that is thrown and return it as CStatusMessage.
Free functions in swift::misc.
SWIFT_MISC_EXPORT bool stringToBool(const QString &boolString)
Convert string to bool.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.