diff options
author | Leander Beernaert <leander.beernaert@qt.io> | 2020-01-22 13:47:08 +0100 |
---|---|---|
committer | Leander Beernaert <leander.beernaert@qt.io> | 2020-01-24 13:17:33 +0100 |
commit | 502d3d6744913899da87acfda5ebdab42c40329e (patch) | |
tree | 16658a328503bfd5a62b4fd5d69ffb66e9854b18 /tests/manual/highdpi | |
parent | d1be8b9ceb2c7b20bbe53a07154c79699540ea3d (diff) | |
parent | 06bb315beb6c2c398223cfe52cbc7f66e14a8557 (diff) |
Merge remote-tracking branch 'origin/dev' into merge-dev
Change-Id: I31b761cfd5ea01373c60d02a5da8c33398d34739
Diffstat (limited to 'tests/manual/highdpi')
-rw-r--r-- | tests/manual/highdpi/dragwidget.cpp | 15 | ||||
-rw-r--r-- | tests/manual/highdpi/dragwidget.h | 5 | ||||
-rw-r--r-- | tests/manual/highdpi/main.cpp | 464 |
3 files changed, 346 insertions, 138 deletions
diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp index 11bbc1d127..8ad3d3ca47 100644 --- a/tests/manual/highdpi/dragwidget.cpp +++ b/tests/manual/highdpi/dragwidget.cpp @@ -42,7 +42,7 @@ public: }; DragWidget::DragWidget(QString text, QWidget *parent) - : QWidget(parent), otherWindow(nullptr) + : QWidget(parent) { int x = 5; int y = 5; @@ -52,9 +52,9 @@ DragWidget::DragWidget(QString text, QWidget *parent) text = "You can drag from this window and drop text here"; QStringList words = text.split(' '); - foreach (QString word, words) { + for (const QString &word : words) { if (!word.isEmpty()) { - FramedLabel *wordLabel = new FramedLabel(word, this); + auto wordLabel = new FramedLabel(word, this); wordLabel->move(x, y); wordLabel->show(); x += wordLabel->width() + 2; @@ -105,7 +105,6 @@ void DragWidget::dragLeaveEvent(QDragLeaveEvent *) update(); } - void DragWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasText()) { @@ -141,9 +140,9 @@ void DragWidget::dropEvent(QDropEvent *event) } else { event->ignore(); } - foreach (QObject *child, children()) { - if (child->inherits("QWidget")) { - QWidget *widget = static_cast<QWidget *>(child); + for (QObject *child : children()) { + if (child->isWidgetType()) { + auto widget = static_cast<QWidget *>(child); if (!widget->isVisible()) widget->deleteLater(); } @@ -170,7 +169,7 @@ void DragWidget::mousePressEvent(QMouseEvent *event) pixmap.setDevicePixelRatio(dpr); child->render(&pixmap); - QDrag *drag = new QDrag(this); + auto drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(hotSpot); diff --git a/tests/manual/highdpi/dragwidget.h b/tests/manual/highdpi/dragwidget.h index 8b67b20410..06663fc74a 100644 --- a/tests/manual/highdpi/dragwidget.h +++ b/tests/manual/highdpi/dragwidget.h @@ -40,7 +40,7 @@ QT_END_NAMESPACE class DragWidget : public QWidget { public: - DragWidget(QString text = QString(), QWidget *parent = 0); + DragWidget(QString text = QString(), QWidget *parent = nullptr); protected: void dragEnterEvent(QDragEnterEvent *event) override; @@ -52,12 +52,13 @@ protected: void timerEvent(QTimerEvent *event) override; void showEvent(QShowEvent *event) override; void hideEvent(QHideEvent *event) override; + private: QPoint dragPos; QPoint dropPos; QBasicTimer dragTimer; QBasicTimer dropTimer; - QWidget *otherWindow; + QWidget *otherWindow = nullptr; }; #endif // DRAGWIDGET_H diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp index 0329e62387..2a9fb6aa0c 100644 --- a/tests/manual/highdpi/main.cpp +++ b/tests/manual/highdpi/main.cpp @@ -30,6 +30,7 @@ #include <QMenuBar> #include <QLabel> #include <QHBoxLayout> +#include <QFormLayout> #include <QApplication> #include <QAction> #include <QStyle> @@ -38,6 +39,7 @@ #include <QButtonGroup> #include <QLineEdit> #include <QPlainTextEdit> +#include <QTabWidget> #include <QScrollBar> #include <QSlider> #include <QSpinBox> @@ -50,38 +52,57 @@ #include <QGraphicsView> #include <QGraphicsTextItem> #include <QFile> +#include <QFontMetrics> #include <QMouseEvent> #include <QTemporaryDir> #include <QTimer> #include <QCommandLineParser> #include <QCommandLineOption> #include <QDebug> +#include <QElapsedTimer> #include <private/qhighdpiscaling_p.h> #include <qpa/qplatformscreen.h> #include "dragwidget.h" +#include <utility> + +static QTextStream &operator<<(QTextStream &str, const QSizeF &s) +{ + str << s.width() << 'x' << s.height(); + return str; +} + static QTextStream &operator<<(QTextStream &str, const QRect &r) { str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign; return str; } +static QString formatWindowTitle(const QString &title) +{ + QString result; + QTextStream(&result) << title << ' ' << QT_VERSION_STR << " (" + << QGuiApplication::platformName() + << '/' << QApplication::style()->objectName() << ')'; + return result; +} + class DemoContainerBase { public: - DemoContainerBase() : m_widget(nullptr) {} - virtual ~DemoContainerBase() {} - QString name() { return option().names().first(); } + DemoContainerBase() = default; + virtual ~DemoContainerBase() = default; + QString name() { return option().names().constFirst(); } virtual QCommandLineOption &option() = 0; virtual void makeVisible(bool visible, QWidget *parent) = 0; - QWidget *widget() { return m_widget; } + QWidget *widget() const { return m_widget; } + protected: - QWidget *m_widget; + QWidget *m_widget = nullptr; }; -typedef QList<DemoContainerBase*> DemoContainerList ; - +using DemoContainerList = QVector<DemoContainerBase*>; template <class T> class DemoContainer : public DemoContainerBase @@ -93,16 +114,25 @@ public: } ~DemoContainer() { delete m_widget; } - QCommandLineOption &option() { return m_option; } + QCommandLineOption &option() override { return m_option; } - void makeVisible(bool visible, QWidget *parent) { + void makeVisible(bool visible, QWidget *parent) override + { if (visible && !m_widget) { m_widget = new T; + if (m_widget->windowTitle().isEmpty()) { + QString title = m_option.description(); + if (title.startsWith("Test ", Qt::CaseInsensitive)) + title.remove(0, 5); + title[0] = title.at(0).toUpper(); + m_widget->setWindowTitle(formatWindowTitle(title)); + } m_widget->installEventFilter(parent); } if (m_widget) m_widget->setVisible(visible); } + private: QCommandLineOption m_option; }; @@ -134,12 +164,15 @@ public: connect(m_slider, &QSlider::sliderMoved, this, &LabelSlider::updateLabel); connect(m_slider, &QSlider::valueChanged, this, &LabelSlider::valueChanged); } - void setValue(int scaleFactor) { + void setValue(int scaleFactor) + { m_slider->setValue(scaleFactor); updateLabel(scaleFactor); } + private slots: - void updateLabel(int scaleFactor) { + void updateLabel(int scaleFactor) + { // slider value is scale factor times ten; qreal scalefactorF = qreal(scaleFactor) / 10.0; @@ -149,8 +182,10 @@ private slots: number.append(".0"); m_label->setText(number); } + signals: void valueChanged(int scaleFactor); + private: QSlider *m_slider; QLabel *m_label; @@ -172,31 +207,35 @@ static inline qreal getGlobalScaleFactor() class DemoController : public QWidget { -Q_OBJECT + Q_OBJECT public: - DemoController(DemoContainerList *demos, QCommandLineParser *parser); + DemoController(DemoContainerList demos, QCommandLineParser *parser); ~DemoController(); + protected: - bool eventFilter(QObject *object, QEvent *event); - void closeEvent(QCloseEvent *) { qApp->quit(); } + bool eventFilter(QObject *object, QEvent *event) override; + void closeEvent(QCloseEvent *) override { QCoreApplication::quit(); } + private slots: void handleButton(int id, bool toggled); + private: - DemoContainerList *m_demos; + DemoContainerList m_demos; QButtonGroup *m_group; }; -DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *parser) - : m_demos(demos) +DemoController::DemoController(DemoContainerList demos, QCommandLineParser *parser) + : m_demos(std::move(demos)) { - setWindowTitle("screen scale factors"); + setWindowTitle(formatWindowTitle("Screen Scale Factors")); setObjectName("controller"); // make WindowScaleFactorSetter skip this window - QGridLayout *layout = new QGridLayout; - setLayout(layout); + auto mainLayout = new QVBoxLayout(this); + auto scaleLayout = new QGridLayout; + mainLayout->addLayout(scaleLayout); int layoutRow = 0; - LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", layout, layoutRow++); + LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", scaleLayout, layoutRow++); globalScaleSlider->setValue(int(getGlobalScaleFactor() * 10)); connect(globalScaleSlider, &LabelSlider::valueChanged, [](int scaleFactor){ // slider value is scale factor times ten; @@ -205,13 +244,13 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par }); // set up one scale control line per screen - QList<QScreen *> screens = QGuiApplication::screens(); - foreach (QScreen *screen, screens) { + const auto screens = QGuiApplication::screens(); + for (QScreen *screen : screens) { // create scale control line QSize screenSize = screen->geometry().size(); QString screenId = screen->name() + QLatin1Char(' ') + QString::number(screenSize.width()) + QLatin1Char(' ') + QString::number(screenSize.height()); - LabelSlider *slider = new LabelSlider(this, screenId, layout, layoutRow++); + LabelSlider *slider = new LabelSlider(this, screenId, scaleLayout, layoutRow++); slider->setValue(getScreenFactorWithoutPixelDensity(screen) * 10); // handle slider value change @@ -228,15 +267,18 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par }); } + auto demoLayout = new QFormLayout; + mainLayout->addLayout(demoLayout); m_group = new QButtonGroup(this); m_group->setExclusive(false); - for (int i = 0; i < m_demos->size(); ++i) { - DemoContainerBase *demo = m_demos->at(i); - QPushButton *button = new QPushButton(demo->name()); - button->setToolTip(demo->option().description()); + for (int i = 0; i < m_demos.size(); ++i) { + DemoContainerBase *demo = m_demos.at(i); + QString name = demo->name(); + name[0] = name.at(0).toUpper(); + auto button = new QPushButton(name); button->setCheckable(true); - layout->addWidget(button, layoutRow++, 0, 1, -1); + demoLayout->addRow(demo->option().description(), button); m_group->addButton(button, i); if (parser->isSet(demo->option())) { @@ -244,19 +286,20 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par button->setChecked(true); } } - connect(m_group, SIGNAL(buttonToggled(int, bool)), this, SLOT(handleButton(int, bool))); + connect(m_group, QOverload<int,bool>::of(&QButtonGroup::buttonToggled), + this, &DemoController::handleButton); } DemoController::~DemoController() { - qDeleteAll(*m_demos); + qDeleteAll(m_demos); } bool DemoController::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::Close) { - for (int i = 0; i < m_demos->size(); ++i) { - DemoContainerBase *demo = m_demos->at(i); + for (int i = 0; i < m_demos.size(); ++i) { + DemoContainerBase *demo = m_demos.at(i); if (demo->widget() == object) { m_group->button(i)->setChecked(false); break; @@ -268,15 +311,17 @@ bool DemoController::eventFilter(QObject *object, QEvent *event) void DemoController::handleButton(int id, bool toggled) { - m_demos->at(id)->makeVisible(toggled, this); + m_demos.at(id)->makeVisible(toggled, this); } class PixmapPainter : public QWidget { public: PixmapPainter(); - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; + +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; @@ -348,12 +393,14 @@ void PixmapPainter::paintEvent(QPaintEvent *) class TiledPixmapPainter : public QWidget { public: + TiledPixmapPainter(); + + void paintEvent(QPaintEvent *event) override; + +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; - - TiledPixmapPainter(); - void paintEvent(QPaintEvent *event); }; TiledPixmapPainter::TiledPixmapPainter() @@ -404,6 +451,7 @@ class Labels : public QWidget public: Labels(); +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; @@ -419,7 +467,7 @@ Labels::Labels() qtIcon.addFile(":/qticon32.png"); qtIcon.addFile(":/qticon32@2x.png"); setWindowIcon(qtIcon); - setWindowTitle("Labels"); + setWindowTitle(formatWindowTitle("Labels")); QLabel *label1x = new QLabel(); label1x->setPixmap(pixmap1X); @@ -454,18 +502,17 @@ private: QIcon qtIcon2x; QToolBar *fileToolBar; - int menuCount; QAction *m_maskAction; + int menuCount = 0; }; MainWindow::MainWindow() - :menuCount(0) { // beware that QIcon auto-loads the @2x versions. qtIcon1x.addFile(":/qticon16.png"); qtIcon2x.addFile(":/qticon32.png"); setWindowIcon(qtIcon); - setWindowTitle("MainWindow"); + setWindowTitle(formatWindowTitle("MainWindow")); fileToolBar = addToolBar(tr("File")); // fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); @@ -484,7 +531,6 @@ MainWindow::MainWindow() addNewMenu("&Help", 2); } - QMenu *MainWindow::addNewMenu(const QString &title, int itemCount) { QMenu *menu = menuBar()->addMenu(title); @@ -516,7 +562,7 @@ void MainWindow::maskActionToggled(bool t) class StandardIcons : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { int x = 10; int y = 10; @@ -538,7 +584,7 @@ public: class Caching : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { QSize layoutSize(75, 75); @@ -576,16 +622,12 @@ public: } }; -class Style : public QWidget { +class Style : public QWidget +{ public: - QPushButton *button; - QLineEdit *lineEdit; - QSlider *slider; - QHBoxLayout *row1; - - Style() { - row1 = new QHBoxLayout(); - setLayout(row1); + Style() + { + row1 = new QHBoxLayout(this); button = new QPushButton(); button->setText("Test Button"); @@ -601,17 +643,23 @@ public: row1->addWidget(new QSpinBox); row1->addWidget(new QScrollBar); - QTabBar *tab = new QTabBar(); + auto tab = new QTabBar(); tab->addTab("Foo"); tab->addTab("Bar"); row1->addWidget(tab); } + +private: + QPushButton *button; + QLineEdit *lineEdit; + QSlider *slider; + QHBoxLayout *row1; }; class Fonts : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { QPainter painter(this); @@ -690,7 +738,7 @@ public: iconNormalDpi.reset(new QIcon(path32_2)); // does not have a 2x version. } - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { int x = 10; int y = 10; @@ -782,7 +830,7 @@ public: tab->move(10, 100); tab->show(); - QToolBar *toolBar = new QToolBar(this); + auto toolBar = new QToolBar(this); toolBar->addAction(QIcon(":/qticon16.png"), "16"); toolBar->addAction(QIcon(":/qticon16@2x.png"), "16@2x"); toolBar->addAction(QIcon(":/qticon32.png"), "32"); @@ -796,11 +844,12 @@ public: class LinePainter : public QWidget { public: - void paintEvent(QPaintEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; +private: QPoint lastMousePoint; QVector<QPoint> linePoints; }; @@ -855,17 +904,15 @@ void LinePainter::mouseMoveEvent(QMouseEvent *event) class CursorTester : public QWidget { public: - CursorTester() - :moveLabel(nullptr), moving(false) - { - } + CursorTester() = default; inline QRect getRect(int idx) const { int h = height() / 2; return QRect(10, 10 + h * (idx - 1), width() - 20, h - 20); } - void paintEvent(QPaintEvent *) + + void paintEvent(QPaintEvent *) override { QPainter p(this); QRect r1 = getRect(1); @@ -899,7 +946,7 @@ public: } } - void mousePressEvent(QMouseEvent *e) + void mousePressEvent(QMouseEvent *e) override { if (moving) return; @@ -923,7 +970,7 @@ public: moveLabel->show(); } - void mouseReleaseEvent(QMouseEvent *) + void mouseReleaseEvent(QMouseEvent *) override { if (moveLabel) moveLabel->hide(); @@ -931,7 +978,7 @@ public: moving = false; } - void mouseMoveEvent(QMouseEvent *e) + void mouseMoveEvent(QMouseEvent *e) override { if (!moving) return; @@ -943,32 +990,32 @@ public: } private: - QLabel *moveLabel; - bool useCursorPos; - bool moving; + QLabel *moveLabel = nullptr; QPoint mousePos; + bool useCursorPos = false; + bool moving = false; }; - class ScreenDisplayer : public QWidget { public: - ScreenDisplayer() - : QWidget(), moveLabel(nullptr), scaleFactor(1.0) - { - } + ScreenDisplayer() = default; - void timerEvent(QTimerEvent *) { + void timerEvent(QTimerEvent *) override + { update(); } - void mousePressEvent(QMouseEvent *) { + void mousePressEvent(QMouseEvent *) override + { if (!moveLabel) moveLabel = new QLabel(this,Qt::BypassWindowManagerHint|Qt::FramelessWindowHint|Qt::Window ); moveLabel->setText("Hello, Qt this is a label\nwith some text"); moveLabel->show(); } - void mouseMoveEvent(QMouseEvent *e) { + + void mouseMoveEvent(QMouseEvent *e) override + { if (!moveLabel) return; moveLabel->move(e->pos() / scaleFactor); @@ -978,23 +1025,30 @@ public: dbg << moveLabel->geometry(); moveLabel->setText(str); } - void mouseReleaseEvent(QMouseEvent *) { + + void mouseReleaseEvent(QMouseEvent *) override + { if (moveLabel) moveLabel->hide(); } - void showEvent(QShowEvent *) { + + void showEvent(QShowEvent *) override + { refreshTimer.start(300, this); } - void hideEvent(QHideEvent *) { + + void hideEvent(QHideEvent *) override + { refreshTimer.stop(); } - void paintEvent(QPaintEvent *) { + + void paintEvent(QPaintEvent *) override + { QPainter p(this); QRectF total; - QList<QScreen*> screens = qApp->screens(); - foreach (QScreen *screen, screens) { + const auto screens = QGuiApplication::screens(); + for (const QScreen *screen : screens) total |= screen->geometry(); - } if (total.isEmpty()) return; @@ -1006,8 +1060,7 @@ public: p.setPen(QPen(Qt::white, 10)); p.setBrush(Qt::gray); - - foreach (QScreen *screen, screens) { + for (const QScreen *screen : screens) { p.drawRect(screen->geometry()); QFont f = font(); f.setPixelSize(screen->geometry().height() / 8); @@ -1015,7 +1068,9 @@ public: p.drawText(screen->geometry(), Qt::AlignCenter, screen->name()); } p.setBrush(QColor(200,220,255,127)); - foreach (QWidget *widget, QApplication::topLevelWidgets()) { + + const auto topLevels = QApplication::topLevelWidgets(); + for (QWidget *widget : topLevels) { if (!widget->isHidden()) p.drawRect(widget->geometry()); } @@ -1028,42 +1083,51 @@ public: cursorShape.translate(QCursor::pos()); p.drawPolygon(cursorShape); } + private: - QLabel *moveLabel; + QLabel *moveLabel = nullptr; + qreal scaleFactor = 1; QBasicTimer refreshTimer; - qreal scaleFactor; }; class PhysicalSizeTest : public QWidget { -Q_OBJECT + Q_OBJECT public: - PhysicalSizeTest() : QWidget(), m_ignoreResize(false) {} - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *) { + PhysicalSizeTest() = default; + + void paintEvent(QPaintEvent *event) override; + + void resizeEvent(QResizeEvent *) override + { qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); QSizeF s = size(); if (!m_ignoreResize) m_physicalSize = s / ppi; } - bool event(QEvent *event) { + + bool event(QEvent *event) override + { if (event->type() == QEvent::ScreenChangeInternal) { // we will get resize events when the scale factor changes m_ignoreResize = true; - QTimer::singleShot(100, this, SLOT(handleScreenChange())); + QTimer::singleShot(100, this, &PhysicalSizeTest::handleScreenChange); } return QWidget::event(event); } + public slots: - void handleScreenChange() { + void handleScreenChange() + { qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); QSizeF newSize = m_physicalSize * ppi; resize(newSize.toSize()); m_ignoreResize = false; } + private: QSizeF m_physicalSize; - bool m_ignoreResize; + bool m_ignoreResize = false; }; void PhysicalSizeTest::paintEvent(QPaintEvent *) @@ -1166,8 +1230,9 @@ void PhysicalSizeTest::paintEvent(QPaintEvent *) class GraphicsViewCaching : public QGraphicsView { public: - GraphicsViewCaching() { - QGraphicsScene *scene = new QGraphicsScene(0, 0, 400, 400); + GraphicsViewCaching() + { + auto scene = new QGraphicsScene(0, 0, 400, 400); QGraphicsTextItem *item = scene->addText("NoCache"); item->setCacheMode(QGraphicsItem::NoCache); @@ -1185,16 +1250,15 @@ public: } }; -class MetricsTest : public QWidget +class MetricsTest : public QTabWidget { - QPlainTextEdit *m_textEdit; - + Q_OBJECT public: MetricsTest() { - qDebug() << R"( -MetricsTest -Relevant environment variables are: + qDebug().noquote().nospace() << "MetricsTest " << QT_VERSION_STR + << ' ' << QGuiApplication::platformName() << '\n' +<< R"(Relevant environment variables are: QT_FONT_DPI=N QT_SCALE_FACTOR=n QT_ENABLE_HIGHDPI_SCALING=0|1 @@ -1203,14 +1267,36 @@ QT_SCREEN_SCALE_FACTORS=N;N;N or QT_SCREEN_SCALE_FACTORS=name:N QT_SCALE_FACTOR_ROUNDING_POLICY=Round|Ceil|Floor|RoundPreferFloor|PassThrough QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; - resize(480, 360); + m_textEdit = addTextPage("Parameters"); + m_logEdit = addTextPage("Screen Change Log"); - QVBoxLayout *layout = new QVBoxLayout(); - setLayout(layout); + const auto screens = QGuiApplication::screens(); + for (auto screen : screens) + connectScreenChangeSignals(screen); + connect(qApp, &QGuiApplication::screenAdded, this, &MetricsTest::slotScreenAdded); + connect(qApp, &QGuiApplication::primaryScreenChanged, this, &MetricsTest::slotPrimaryScreenChanged); + connect(qApp, &QGuiApplication::screenRemoved, this, &MetricsTest::slotScreenRemoved); + + setWindowTitle(formatWindowTitle("Screens")); + m_logTimer.start(); + logMessage(briefFormatScreens()); + + // Resize to roughly match the metrics text. + const auto metrics = QFontMetrics(m_textEdit->font(), m_textEdit); + const int width = 10 + metrics.horizontalAdvance(QStringLiteral("X")) * 50; + const int height = 40 + metrics.height() * (10 + 8 * screens.size()); + resize(width, height); + } - m_textEdit = new QPlainTextEdit; - m_textEdit->setReadOnly(true); - layout->addWidget(m_textEdit); + void setVisible(bool visible) override + { + QWidget::setVisible(visible); + if (visible && !m_screenChangedConnected) { + m_screenChangedConnected = true; + QObject::connect(windowHandle(), &QWindow::screenChanged, + this, &MetricsTest::screenChanged); + updateMetrics(); + } } void updateMetrics() @@ -1254,24 +1340,145 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; m_textEdit->setPlainText(text); } - void paintEvent(QPaintEvent *ev) +private slots: + void screenChanged() { - // We get a paint event on screen change, so this is a convenient place - // to update the metrics, at the possible risk of doing something else - // than painting in a paint event. + const QString message = QLatin1String("screenChanged ") + windowHandle()->screen()->name(); + qInfo("%s", qPrintable(message)); + logMessage(message); updateMetrics(); - QWidget::paintEvent(ev); } + + void slotScreenAdded(QScreen *); + void slotScreenRemoved(QScreen *); + void slotPrimaryScreenChanged(QScreen *); + void slotScreenGeometryChanged(const QRect &geometry) + { logScreenChangeSignal(sender(), "geometry", geometry); } + void slotScreenAvailableGeometryChanged(const QRect &geometry) + { logScreenChangeSignal(sender(), "availableGeometry", geometry); } + void slotScreenPhysicalSizeChanged(const QSizeF &size) + { logScreenChangeSignal(sender(), "physicalSize", size); } + void slotScreenPhysicalDotsPerInchChanged(qreal dpi) + { logScreenChangeSignal(sender(), "physicalDotsPerInch", dpi); } + void slotScreenLogicalDotsPerInchChanged(qreal dpi) + { logScreenChangeSignal(sender(), "logicalDotsPerInch", dpi); } + void slotScreenVirtualGeometryChanged(const QRect &rect) + { logScreenChangeSignal(sender(), "virtualGeometry", rect); } + void slotScreenPrimaryOrientationChanged(Qt::ScreenOrientation orientation) + { logScreenChangeSignal(sender(), "primaryOrientation", orientation); } + void slotScreenOrientationChanged(Qt::ScreenOrientation orientation) + { logScreenChangeSignal(sender(), "orientation", orientation); } + void slotScreenRefreshRateChanged(qreal refreshRate) + { logScreenChangeSignal(sender(), "refreshRate", refreshRate); } + +private: + QPlainTextEdit *addTextPage(const QString &title); + void logMessage(const QString &); + void connectScreenChangeSignals(QScreen *s); + static QString briefFormatScreens(); + template <class T> + void logScreenChangeSignal(const QObject *o, const char *name, const T &value); + + QPlainTextEdit *m_textEdit; + QPlainTextEdit *m_logEdit; + QElapsedTimer m_logTimer; + bool m_screenChangedConnected = false; }; +void MetricsTest::slotScreenAdded(QScreen *screen) +{ + logMessage(QLatin1String("Added ") + screen->name() + QLatin1Char(' ') + + briefFormatScreens()); + connectScreenChangeSignals(screen); +} + +void MetricsTest::slotScreenRemoved(QScreen *screen) +{ + logMessage(QLatin1String("Removed ") + screen->name() + QLatin1Char(' ') + + briefFormatScreens()); +} + +void MetricsTest::slotPrimaryScreenChanged(QScreen *screen) +{ + logMessage(QLatin1String("PrimaryScreenChanged ") + screen->name() + QLatin1Char(' ') + + briefFormatScreens()); +} + +QPlainTextEdit *MetricsTest::addTextPage(const QString &title) +{ + auto result = new QPlainTextEdit(this); + result->setReadOnly(true); + result->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + addTab(result, title); + return result; +} + +void MetricsTest::logMessage(const QString &m) +{ + const QString timeStamp = + QStringLiteral("%1ms: %2").arg(m_logTimer.elapsed(), 6, 10, QLatin1Char('0')).arg(m); + m_logEdit->appendPlainText(timeStamp); +} + +void MetricsTest::connectScreenChangeSignals(QScreen *s) +{ + connect(s, &QScreen::geometryChanged, this, &MetricsTest::slotScreenGeometryChanged); + connect(s, &QScreen::availableGeometryChanged, this, &MetricsTest::slotScreenAvailableGeometryChanged); + connect(s, &QScreen::physicalSizeChanged, this, &MetricsTest::slotScreenPhysicalSizeChanged); + connect(s, &QScreen::physicalDotsPerInchChanged, this, &MetricsTest::slotScreenPhysicalDotsPerInchChanged); + connect(s, &QScreen::logicalDotsPerInchChanged, this, &MetricsTest::slotScreenLogicalDotsPerInchChanged); + connect(s, &QScreen::virtualGeometryChanged, this, &MetricsTest::slotScreenVirtualGeometryChanged); + connect(s, &QScreen::primaryOrientationChanged, this, &MetricsTest::slotScreenPrimaryOrientationChanged); + connect(s, &QScreen::orientationChanged, this, &MetricsTest::slotScreenOrientationChanged); + connect(s, &QScreen::refreshRateChanged, this, &MetricsTest::slotScreenRefreshRateChanged); +} + +QString MetricsTest::briefFormatScreens() +{ + QString message; + QTextStream str(&message); + const auto screens = QGuiApplication::screens(); + for (int i = 0, size = screens.size(); i < size; ++i) { + str << (i ? ", " : "("); + str << screens.at(i)->name() << " " << screens.at(i)->geometry(); + } + str << ')'; + return message; +} + +template <class T> +void MetricsTest::logScreenChangeSignal(const QObject *o, const char *name, const T &value) +{ + auto screen = qobject_cast<const QScreen *>(o); + QString message; + QTextStream(&message) << (screen ? screen->name() : QString()) << ' ' << name << " changed: " << value; + logMessage(message); +} + int main(int argc, char **argv) { +#define NOSCALINGOPTION "noscaling" +#define SCALINGOPTION "scaling" + + qInfo("High DPI tester %s", QT_VERSION_STR); + + int preAppOptionCount = 0; + for (int a = 1; a < argc; ++a) { + if (qstrcmp(argv[a], "--" NOSCALINGOPTION) == 0) { + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); + preAppOptionCount++; + qInfo("AA_DisableHighDpiScaling"); + } else if (qstrcmp(argv[a], "--" SCALINGOPTION) == 0) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + preAppOptionCount++; + qInfo("AA_EnableHighDpiScaling"); + } + } + QApplication app(argc, argv); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setApplicationVersion(QT_VERSION_STR); - int argumentCount = QCoreApplication::arguments().count(); - QCommandLineParser parser; parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n" "test various high-dpi aspects. \n" @@ -1281,7 +1488,8 @@ int main(int argc, char **argv) parser.addVersionOption(); QCommandLineOption controllerOption("interactive", "Show configuration window."); parser.addOption(controllerOption); - + parser.addOption(QCommandLineOption(NOSCALINGOPTION, "Set AA_DisableHighDpiScaling")); + parser.addOption(QCommandLineOption(SCALINGOPTION, "Set AA_EnableHighDpiScaling")); DemoContainerList demoList; demoList << new DemoContainer<PixmapPainter>("pixmap", "Test pixmap painter"); @@ -1300,17 +1508,17 @@ int main(int argc, char **argv) demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning"); demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch"); demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching"); - demoList << new DemoContainer<MetricsTest>("metrics", "Show display metrics"); + demoList << new DemoContainer<MetricsTest>("metrics", "Show screen metrics"); - foreach (DemoContainerBase *demo, demoList) + for (DemoContainerBase *demo : qAsConst(demoList)) parser.addOption(demo->option()); parser.process(app); //controller takes ownership of all demos - DemoController controller(&demoList, &parser); + DemoController controller(demoList, &parser); - if (parser.isSet(controllerOption) || argumentCount <= 1) + if (parser.isSet(controllerOption) || (QCoreApplication::arguments().count() - preAppOptionCount) <= 1) controller.show(); if (QApplication::topLevelWidgets().isEmpty()) |