Extend high-DPI manual test
Add several new tests to verify that Qt behaves properly when high-DPI scaling is enabled. Add a generic framework for manual tests for good measure. This could be refactored and used for other manual tests later. Includes tests written by Morten and Friedemann. Task-number: QTBUG-46615 Change-Id: Ib6762ec1454711e71f0c094b19015932b99e8d6d Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
parent
6309062722
commit
62bd4f5852
223
tests/manual/highdpi/dragwidget.cpp
Normal file
223
tests/manual/highdpi/dragwidget.cpp
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QtWidgets>
|
||||||
|
#include "dragwidget.h"
|
||||||
|
|
||||||
|
class FramedLabel : public QLabel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FramedLabel(const QString &text, QWidget *parent)
|
||||||
|
: QLabel(text, parent)
|
||||||
|
{
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
setFrameShape(QFrame::Panel);
|
||||||
|
setFrameShadow(QFrame::Raised);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DragWidget::DragWidget(QString text, QWidget *parent)
|
||||||
|
: QWidget(parent), otherWindow(0)
|
||||||
|
{
|
||||||
|
int x = 5;
|
||||||
|
int y = 5;
|
||||||
|
|
||||||
|
bool createChildWindow = text.isEmpty(); // OK, yes this is a hack...
|
||||||
|
if (text.isEmpty())
|
||||||
|
text = "You can drag from this window and drop text here";
|
||||||
|
|
||||||
|
QStringList words = text.split(' ');
|
||||||
|
foreach (QString word, words) {
|
||||||
|
if (!word.isEmpty()) {
|
||||||
|
FramedLabel *wordLabel = new FramedLabel(word, this);
|
||||||
|
wordLabel->move(x, y);
|
||||||
|
wordLabel->show();
|
||||||
|
x += wordLabel->width() + 2;
|
||||||
|
if (x >= 245) {
|
||||||
|
x = 5;
|
||||||
|
y += wordLabel->height() + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
QPalette newPalette = palette();
|
||||||
|
newPalette.setColor(QPalette::Window, Qt::white);
|
||||||
|
setPalette(newPalette);
|
||||||
|
*/
|
||||||
|
|
||||||
|
setAcceptDrops(true);
|
||||||
|
setMinimumSize(400, qMax(200, y));
|
||||||
|
setWindowTitle(tr("Draggable Text Window %1").arg(createChildWindow ? 1 : 2));
|
||||||
|
if (createChildWindow)
|
||||||
|
otherWindow = new DragWidget("Here is a second window that accepts drops");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||||
|
{
|
||||||
|
if (event->mimeData()->hasText()) {
|
||||||
|
if (event->source() == this) {
|
||||||
|
event->setDropAction(Qt::MoveAction);
|
||||||
|
event->accept();
|
||||||
|
} else {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::dragMoveEvent(QDragMoveEvent * event)
|
||||||
|
{
|
||||||
|
dragPos = event->pos();
|
||||||
|
dragTimer.start(500, this);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::dragLeaveEvent(QDragLeaveEvent *)
|
||||||
|
{
|
||||||
|
dragTimer.stop();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DragWidget::dropEvent(QDropEvent *event)
|
||||||
|
{
|
||||||
|
if (event->mimeData()->hasText()) {
|
||||||
|
const QMimeData *mime = event->mimeData();
|
||||||
|
QStringList pieces = mime->text().split(QRegExp("\\s+"),
|
||||||
|
QString::SkipEmptyParts);
|
||||||
|
QPoint position = event->pos();
|
||||||
|
QPoint hotSpot;
|
||||||
|
|
||||||
|
QList<QByteArray> hotSpotPos = mime->data("application/x-hotspot").split(' ');
|
||||||
|
if (hotSpotPos.size() == 2) {
|
||||||
|
hotSpot.setX(hotSpotPos.first().toInt());
|
||||||
|
hotSpot.setY(hotSpotPos.last().toInt());
|
||||||
|
}
|
||||||
|
dropPos = position - hotSpot;
|
||||||
|
dropTimer.start(500, this);
|
||||||
|
update();
|
||||||
|
|
||||||
|
foreach (QString piece, pieces) {
|
||||||
|
FramedLabel *newLabel = new FramedLabel(piece, this);
|
||||||
|
newLabel->move(position - hotSpot);
|
||||||
|
newLabel->show();
|
||||||
|
|
||||||
|
position += QPoint(newLabel->width(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->source() == this) {
|
||||||
|
event->setDropAction(Qt::MoveAction);
|
||||||
|
event->accept();
|
||||||
|
} else {
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
foreach (QObject *child, children()) {
|
||||||
|
if (child->inherits("QWidget")) {
|
||||||
|
QWidget *widget = static_cast<QWidget *>(child);
|
||||||
|
if (!widget->isVisible())
|
||||||
|
widget->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QLabel *child = static_cast<QLabel*>(childAt(event->pos()));
|
||||||
|
if (!child)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPoint hotSpot = event->pos() - child->pos();
|
||||||
|
|
||||||
|
QMimeData *mimeData = new QMimeData;
|
||||||
|
mimeData->setText(child->text());
|
||||||
|
mimeData->setData("application/x-hotspot",
|
||||||
|
QByteArray::number(hotSpot.x()) + " " + QByteArray::number(hotSpot.y()));
|
||||||
|
|
||||||
|
QPixmap pixmap(child->size());
|
||||||
|
child->render(&pixmap);
|
||||||
|
|
||||||
|
QDrag *drag = new QDrag(this);
|
||||||
|
drag->setMimeData(mimeData);
|
||||||
|
drag->setPixmap(pixmap);
|
||||||
|
drag->setHotSpot(hotSpot);
|
||||||
|
|
||||||
|
Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
|
||||||
|
|
||||||
|
if (dropAction == Qt::MoveAction)
|
||||||
|
child->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::timerEvent(QTimerEvent *e)
|
||||||
|
{
|
||||||
|
if (e->timerId() == dragTimer.timerId())
|
||||||
|
dragTimer.stop();
|
||||||
|
if (e->timerId() == dropTimer.timerId())
|
||||||
|
dropTimer.stop();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
p.fillRect(rect(), Qt::white);
|
||||||
|
|
||||||
|
if (dropTimer.isActive()) {
|
||||||
|
p.setBrush(Qt::red);
|
||||||
|
p.drawEllipse(dropPos, 50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dragTimer.isActive()) {
|
||||||
|
p.setPen(QPen(Qt::blue, 5));
|
||||||
|
QPoint p1 = (rect().topLeft()*3 + rect().bottomRight())/4;
|
||||||
|
QPoint p2 = (rect().topLeft() + rect().bottomRight()*3)/4;
|
||||||
|
p.drawLine(p1, dragPos);
|
||||||
|
p.drawLine(p2, dragPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::showEvent(QShowEvent *)
|
||||||
|
{
|
||||||
|
if (otherWindow)
|
||||||
|
otherWindow->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragWidget::hideEvent(QHideEvent *)
|
||||||
|
{
|
||||||
|
if (otherWindow)
|
||||||
|
otherWindow->hide();
|
||||||
|
}
|
68
tests/manual/highdpi/dragwidget.h
Normal file
68
tests/manual/highdpi/dragwidget.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2015 The Qt Company Ltd.
|
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL21$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see http://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** As a special exception, The Qt Company gives you certain additional
|
||||||
|
** rights. These rights are described in The Qt Company LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DRAGWIDGET_H
|
||||||
|
#define DRAGWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QBasicTimer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QDragEnterEvent;
|
||||||
|
class QDropEvent;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class DragWidget : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DragWidget(QString text = QString(), QWidget *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void dragMoveEvent(QDragMoveEvent * event) Q_DECL_OVERRIDE;
|
||||||
|
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
|
||||||
|
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
void hideEvent(QHideEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
private:
|
||||||
|
QPoint dragPos;
|
||||||
|
QPoint dropPos;
|
||||||
|
QBasicTimer dragTimer;
|
||||||
|
QBasicTimer dropTimer;
|
||||||
|
QWidget *otherWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DRAGWIDGET_H
|
@ -1,10 +1,17 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
TARGET = highdpi
|
TARGET = highdpi
|
||||||
INCLUDEPATH += .
|
INCLUDEPATH += .
|
||||||
QT += widgets
|
QT += widgets gui-private
|
||||||
CONFIG+=console
|
CONFIG +=console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
CONFIG += c++11
|
||||||
# Input
|
# Input
|
||||||
SOURCES += main.cpp
|
SOURCES += \
|
||||||
|
dragwidget.cpp \
|
||||||
|
main.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
dragwidget.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
highdpi.qrc
|
highdpi.qrc
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QMenuBar>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -39,6 +40,7 @@
|
|||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QButtonGroup>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
@ -49,10 +51,219 @@
|
|||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QMouseEvent>
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
#include <QTimer>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QCommandLineOption>
|
#include <QCommandLineOption>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <private/qhighdpiscaling_p.h>
|
||||||
|
|
||||||
|
#include "dragwidget.h"
|
||||||
|
|
||||||
|
class DemoContainerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DemoContainerBase() : m_widget(0) {}
|
||||||
|
virtual ~DemoContainerBase() {}
|
||||||
|
QString name() { return option().names().first(); }
|
||||||
|
virtual QCommandLineOption &option() = 0;
|
||||||
|
virtual void makeVisible(bool visible, QWidget *parent) = 0;
|
||||||
|
QWidget *widget() { return m_widget; }
|
||||||
|
protected:
|
||||||
|
QWidget *m_widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QList<DemoContainerBase*> DemoContainerList ;
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class DemoContainer : public DemoContainerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DemoContainer(const QString &optionName, const QString &description)
|
||||||
|
: m_option(optionName, description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~DemoContainer() { delete m_widget; }
|
||||||
|
|
||||||
|
QCommandLineOption &option() { return m_option; }
|
||||||
|
|
||||||
|
void makeVisible(bool visible, QWidget *parent) {
|
||||||
|
if (visible && !m_widget) {
|
||||||
|
m_widget = new T;
|
||||||
|
m_widget->installEventFilter(parent);
|
||||||
|
}
|
||||||
|
if (m_widget)
|
||||||
|
m_widget->setVisible(visible);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QCommandLineOption m_option;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LabelSlider : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LabelSlider(QObject *parent, const QString &text, QGridLayout *layout, int row)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
QLabel *textLabel = new QLabel(text);
|
||||||
|
m_slider = new QSlider();
|
||||||
|
m_slider->setOrientation(Qt::Horizontal);
|
||||||
|
m_slider->setMinimum(1);
|
||||||
|
m_slider->setMaximum(40);
|
||||||
|
m_slider->setValue(10);
|
||||||
|
m_slider->setTracking(false);
|
||||||
|
m_slider->setTickInterval(5);
|
||||||
|
m_slider->setTickPosition(QSlider::TicksBelow);
|
||||||
|
m_label = new QLabel("1.0");
|
||||||
|
|
||||||
|
// set up layouts
|
||||||
|
layout->addWidget(textLabel, row, 0);
|
||||||
|
layout->addWidget(m_slider, row, 1);
|
||||||
|
layout->addWidget(m_label, row, 2);
|
||||||
|
|
||||||
|
// handle slider position change
|
||||||
|
connect(m_slider, &QSlider::sliderMoved, this, &LabelSlider::updateLabel);
|
||||||
|
connect(m_slider, &QSlider::valueChanged, this, &LabelSlider::valueChanged);
|
||||||
|
}
|
||||||
|
void setValue(int scaleFactor) {
|
||||||
|
m_slider->setValue(scaleFactor);
|
||||||
|
updateLabel(scaleFactor);
|
||||||
|
}
|
||||||
|
private slots:
|
||||||
|
void updateLabel(int scaleFactor) {
|
||||||
|
// slider value is scale factor times ten;
|
||||||
|
qreal scalefactorF = qreal(scaleFactor) / 10.0;
|
||||||
|
|
||||||
|
// update label, add ".0" if needed.
|
||||||
|
QString number = QString::number(scalefactorF);
|
||||||
|
if (!number.contains("."))
|
||||||
|
number.append(".0");
|
||||||
|
m_label->setText(number);
|
||||||
|
}
|
||||||
|
signals:
|
||||||
|
void valueChanged(int scaleFactor);
|
||||||
|
private:
|
||||||
|
QSlider *m_slider;
|
||||||
|
QLabel *m_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
static qreal getScreenFactorWithoutPixelDensity(const QScreen *screen)
|
||||||
|
{
|
||||||
|
// this is a hack that relies on knowing the internals of QHighDpiScaling
|
||||||
|
static const char *scaleFactorProperty = "_q_scaleFactor";
|
||||||
|
QVariant screenFactor = screen->property(scaleFactorProperty);
|
||||||
|
return screenFactor.isValid() ? screenFactor.toReal() : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline qreal getGlobalScaleFactor()
|
||||||
|
{
|
||||||
|
QScreen *noScreen = 0;
|
||||||
|
return QHighDpiScaling::factor(noScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
class DemoController : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DemoController(DemoContainerList *demos, QCommandLineParser *parser);
|
||||||
|
~DemoController();
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *object, QEvent *event);
|
||||||
|
void closeEvent(QCloseEvent *) { qApp->quit(); }
|
||||||
|
private slots:
|
||||||
|
void handleButton(int id, bool toggled);
|
||||||
|
private:
|
||||||
|
DemoContainerList *m_demos;
|
||||||
|
QButtonGroup *m_group;
|
||||||
|
};
|
||||||
|
|
||||||
|
DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *parser)
|
||||||
|
: m_demos(demos)
|
||||||
|
{
|
||||||
|
setWindowTitle("screen scale factors");
|
||||||
|
setObjectName("controller"); // make WindowScaleFactorSetter skip this window
|
||||||
|
|
||||||
|
QGridLayout *layout = new QGridLayout;
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
int layoutRow = 0;
|
||||||
|
LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", layout, layoutRow++);
|
||||||
|
globalScaleSlider->setValue(int(getGlobalScaleFactor() * 10));
|
||||||
|
connect(globalScaleSlider, &LabelSlider::valueChanged, [](int scaleFactor){
|
||||||
|
// slider value is scale factor times ten;
|
||||||
|
qreal scalefactorF = qreal(scaleFactor) / 10.0;
|
||||||
|
QHighDpiScaling::setGlobalFactor(scalefactorF);
|
||||||
|
});
|
||||||
|
|
||||||
|
// set up one scale control line per screen
|
||||||
|
QList<QScreen *> screens = QGuiApplication::screens();
|
||||||
|
foreach (QScreen *screen, screens) {
|
||||||
|
// create scale control line
|
||||||
|
QSize screenSize = screen->geometry().size();
|
||||||
|
QString screenId = screen->name() + " " + QString::number(screenSize.width())
|
||||||
|
+ " " + QString::number(screenSize.height());
|
||||||
|
LabelSlider *slider = new LabelSlider(this, screenId, layout, layoutRow++);
|
||||||
|
slider->setValue(getScreenFactorWithoutPixelDensity(screen) * 10);
|
||||||
|
|
||||||
|
// handle slider value change
|
||||||
|
connect(slider, &LabelSlider::valueChanged, [screen](int scaleFactor){
|
||||||
|
// slider value is scale factor times ten;
|
||||||
|
qreal scalefactorF = qreal(scaleFactor) / 10.0;
|
||||||
|
|
||||||
|
// set scale factor for screen
|
||||||
|
qreal oldFactor = QHighDpiScaling::factor(screen);
|
||||||
|
QHighDpiScaling::setScreenFactor(screen, scalefactorF);
|
||||||
|
qreal newFactor = QHighDpiScaling::factor(screen);
|
||||||
|
|
||||||
|
qDebug() << "factor was / is" << oldFactor << newFactor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
button->setCheckable(true);
|
||||||
|
layout->addWidget(button, layoutRow++, 0, 1, -1);
|
||||||
|
m_group->addButton(button, i);
|
||||||
|
|
||||||
|
if (parser->isSet(demo->option())) {
|
||||||
|
demo->makeVisible(true, this);
|
||||||
|
button->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(m_group, SIGNAL(buttonToggled(int, bool)), this, SLOT(handleButton(int, bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
DemoController::~DemoController()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (demo->widget() == object) {
|
||||||
|
m_group->button(i)->setChecked(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoController::handleButton(int id, bool toggled)
|
||||||
|
{
|
||||||
|
m_demos->at(id)->makeVisible(toggled, this);
|
||||||
|
}
|
||||||
|
|
||||||
class PixmapPainter : public QWidget
|
class PixmapPainter : public QWidget
|
||||||
{
|
{
|
||||||
@ -69,7 +280,6 @@ public:
|
|||||||
QIcon qtIcon;
|
QIcon qtIcon;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PixmapPainter::PixmapPainter()
|
PixmapPainter::PixmapPainter()
|
||||||
{
|
{
|
||||||
pixmap1X = QPixmap(":/qticon32.png");
|
pixmap1X = QPixmap(":/qticon32.png");
|
||||||
@ -172,15 +382,18 @@ class MainWindow : public QMainWindow
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MainWindow();
|
MainWindow();
|
||||||
|
QMenu *addNewMenu(const QString &title, int itemCount = 5);
|
||||||
|
|
||||||
QIcon qtIcon;
|
QIcon qtIcon;
|
||||||
QIcon qtIcon1x;
|
QIcon qtIcon1x;
|
||||||
QIcon qtIcon2x;
|
QIcon qtIcon2x;
|
||||||
|
|
||||||
QToolBar *fileToolBar;
|
QToolBar *fileToolBar;
|
||||||
|
int menuCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
MainWindow::MainWindow()
|
MainWindow::MainWindow()
|
||||||
|
:menuCount(0)
|
||||||
{
|
{
|
||||||
// beware that QIcon auto-loads the @2x versions.
|
// beware that QIcon auto-loads the @2x versions.
|
||||||
qtIcon1x.addFile(":/qticon16.png");
|
qtIcon1x.addFile(":/qticon16.png");
|
||||||
@ -192,8 +405,33 @@ MainWindow::MainWindow()
|
|||||||
// fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
// fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
||||||
fileToolBar->addAction(new QAction(qtIcon1x, QString("1x"), this));
|
fileToolBar->addAction(new QAction(qtIcon1x, QString("1x"), this));
|
||||||
fileToolBar->addAction(new QAction(qtIcon2x, QString("2x"), this));
|
fileToolBar->addAction(new QAction(qtIcon2x, QString("2x"), this));
|
||||||
|
addNewMenu("&Edit");
|
||||||
|
addNewMenu("&Build");
|
||||||
|
addNewMenu("&Debug", 4);
|
||||||
|
addNewMenu("&Transmogrify", 7);
|
||||||
|
addNewMenu("T&ools");
|
||||||
|
addNewMenu("&Help", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QMenu *MainWindow::addNewMenu(const QString &title, int itemCount)
|
||||||
|
{
|
||||||
|
QMenu *menu = menuBar()->addMenu(title);
|
||||||
|
for (int i = 0; i < itemCount; i++) {
|
||||||
|
menuCount++;
|
||||||
|
QString s = "Menu item " + QString::number(menuCount);
|
||||||
|
if (i == 3) {
|
||||||
|
QMenu *subMenu = menu->addMenu(s);
|
||||||
|
for (int j = 1; j < 4; j++)
|
||||||
|
subMenu->addAction(QString::fromLatin1("SubMenu item %1.%2").arg(menuCount).arg(j));
|
||||||
|
} else {
|
||||||
|
menu->addAction(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class StandardIcons : public QWidget
|
class StandardIcons : public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -205,7 +443,7 @@ public:
|
|||||||
int dy = 50;
|
int dy = 50;
|
||||||
int maxX = 500;
|
int maxX = 500;
|
||||||
|
|
||||||
for (int iconIndex = QStyle::SP_TitleBarMenuButton; iconIndex < QStyle::SP_MediaVolumeMuted; ++iconIndex) {
|
for (uint iconIndex = QStyle::SP_TitleBarMenuButton; iconIndex < QStyle::SP_MediaVolumeMuted; ++iconIndex) {
|
||||||
QIcon icon = qApp->style()->standardIcon(QStyle::StandardPixmap(iconIndex));
|
QIcon icon = qApp->style()->standardIcon(QStyle::StandardPixmap(iconIndex));
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
p.drawPixmap(x, y, icon.pixmap(dx - 5, dy - 5));
|
p.drawPixmap(x, y, icon.pixmap(dx - 5, dy - 5));
|
||||||
@ -295,14 +533,27 @@ public:
|
|||||||
void paintEvent(QPaintEvent *)
|
void paintEvent(QPaintEvent *)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
int y = 40;
|
|
||||||
for (int fontSize = 2; fontSize < 18; fontSize += 2) {
|
// Points
|
||||||
|
int y = 10;
|
||||||
|
for (int fontSize = 6; fontSize < 18; fontSize += 2) {
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPointSize(fontSize);
|
font.setPointSize(fontSize);
|
||||||
QString string = QString(QStringLiteral("%1 The quick brown fox jumped over the lazy Doug.")).arg(fontSize);
|
QString string = QString(QStringLiteral("This text is in point size %1")).arg(fontSize);
|
||||||
painter.setFont(font);
|
painter.setFont(font);
|
||||||
|
y += (painter.fontMetrics().lineSpacing());
|
||||||
|
painter.drawText(10, y, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pixels
|
||||||
|
y += painter.fontMetrics().lineSpacing();
|
||||||
|
for (int fontSize = 6; fontSize < 18; fontSize += 2) {
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(fontSize);
|
||||||
|
QString string = QString(QStringLiteral("This text is in pixel size %1")).arg(fontSize);
|
||||||
|
painter.setFont(font);
|
||||||
|
y += (painter.fontMetrics().lineSpacing());
|
||||||
painter.drawText(10, y, string);
|
painter.drawText(10, y, string);
|
||||||
y += (fontSize * 2.5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -461,6 +712,375 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LinePainter : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void paintEvent(QPaintEvent *event);
|
||||||
|
void mousePressEvent(QMouseEvent *event);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event);
|
||||||
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
|
||||||
|
QPoint lastMousePoint;
|
||||||
|
QVector<QPoint> linePoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
void LinePainter::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
p.fillRect(QRect(QPoint(0, 0), size()), QBrush(Qt::gray));
|
||||||
|
|
||||||
|
// Default antialiased line
|
||||||
|
p.setRenderHint(QPainter::Antialiasing);
|
||||||
|
p.drawLines(linePoints);
|
||||||
|
|
||||||
|
// Cosmetic 1 antialiased line
|
||||||
|
QPen pen;
|
||||||
|
pen.setCosmetic(true);
|
||||||
|
pen.setWidth(1);
|
||||||
|
p.setPen(pen);
|
||||||
|
p.translate(3, 3);
|
||||||
|
p.drawLines(linePoints);
|
||||||
|
|
||||||
|
// Aliased cosmetic 1 line
|
||||||
|
p.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
p.translate(3, 3);
|
||||||
|
p.drawLines(linePoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinePainter::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
lastMousePoint = event->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinePainter::mouseReleaseEvent(QMouseEvent *)
|
||||||
|
{
|
||||||
|
lastMousePoint = QPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinePainter::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (lastMousePoint.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPoint newMousePoint = event->pos();
|
||||||
|
if (lastMousePoint == newMousePoint)
|
||||||
|
return;
|
||||||
|
linePoints.append(lastMousePoint);
|
||||||
|
linePoints.append(newMousePoint);
|
||||||
|
lastMousePoint = newMousePoint;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CursorTester : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CursorTester()
|
||||||
|
:moveLabel(0), moving(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QRect getRect(int idx) const
|
||||||
|
{
|
||||||
|
int h = height() / 2;
|
||||||
|
return QRect(10, 10 + h * (idx - 1), width() - 20, h - 20);
|
||||||
|
}
|
||||||
|
void paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
QRect r1 = getRect(1);
|
||||||
|
QRect r2 = getRect(2);
|
||||||
|
p.fillRect(r1, QColor(200, 200, 250));
|
||||||
|
p.drawText(r1, "Drag from here to move a window based on QCursor::pos()");
|
||||||
|
p.fillRect(r2, QColor(250, 200, 200));
|
||||||
|
p.drawText(r2, "Drag from here to move a window based on mouse event position");
|
||||||
|
|
||||||
|
if (moving) {
|
||||||
|
p.setPen(Qt::darkGray);
|
||||||
|
QFont f = font();
|
||||||
|
f.setPointSize(8);
|
||||||
|
p.setFont(f);
|
||||||
|
p.drawEllipse(mousePos, 30,60);
|
||||||
|
QPoint pt = mousePos - QPoint(0, 60);
|
||||||
|
QPoint pt2 = pt - QPoint(30,10);
|
||||||
|
QPoint offs(30, 0);
|
||||||
|
p.drawLine(pt, pt2);
|
||||||
|
p.drawLine(pt2 - offs, pt2 + offs);
|
||||||
|
p.drawText(pt2 - offs, "mouse pos");
|
||||||
|
|
||||||
|
p.setPen(QColor(50,130,70));
|
||||||
|
QPoint cursorPos = mapFromGlobal(QCursor::pos());
|
||||||
|
pt = cursorPos - QPoint(0, 30);
|
||||||
|
pt2 = pt + QPoint(60, -20);
|
||||||
|
p.drawEllipse(cursorPos, 60, 30);
|
||||||
|
p.drawLine(pt, pt2);
|
||||||
|
p.drawLine(pt2 - offs, pt2 + offs);
|
||||||
|
p.drawText(pt2 - offs, "cursor pos");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if (moving)
|
||||||
|
return;
|
||||||
|
QRect r1 = getRect(1);
|
||||||
|
QRect r2 = getRect(2);
|
||||||
|
|
||||||
|
moving = r1.contains(e->pos()) || r2.contains(e->pos());
|
||||||
|
if (!moving)
|
||||||
|
return;
|
||||||
|
useCursorPos = r1.contains(e->pos());
|
||||||
|
|
||||||
|
if (!moveLabel)
|
||||||
|
moveLabel = new QLabel(this,Qt::BypassWindowManagerHint|Qt::FramelessWindowHint|Qt::Window );
|
||||||
|
|
||||||
|
if (useCursorPos)
|
||||||
|
moveLabel->setText("I'm following QCursor::pos()");
|
||||||
|
else
|
||||||
|
moveLabel->setText("I'm following QMouseEvent::globalPos()");
|
||||||
|
moveLabel->adjustSize();
|
||||||
|
mouseMoveEvent(e);
|
||||||
|
moveLabel->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QMouseEvent *)
|
||||||
|
{
|
||||||
|
if (moveLabel)
|
||||||
|
moveLabel->hide();
|
||||||
|
update();
|
||||||
|
moving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouseMoveEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if (!moving)
|
||||||
|
return;
|
||||||
|
QPoint pos = useCursorPos ? QCursor::pos() : e->globalPos();
|
||||||
|
pos -= moveLabel->rect().center();
|
||||||
|
moveLabel->move(pos);
|
||||||
|
mousePos = e->pos();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLabel *moveLabel;
|
||||||
|
bool useCursorPos;
|
||||||
|
bool moving;
|
||||||
|
QPoint mousePos;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ScreenDisplayer : public QWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScreenDisplayer()
|
||||||
|
: QWidget(), moveLabel(0), scaleFactor(1.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerEvent(QTimerEvent *) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *) {
|
||||||
|
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) {
|
||||||
|
if (!moveLabel)
|
||||||
|
return;
|
||||||
|
moveLabel->move(e->pos() / scaleFactor);
|
||||||
|
QString str;
|
||||||
|
QDebug dbg(&str);
|
||||||
|
dbg.setAutoInsertSpaces(false);
|
||||||
|
dbg << moveLabel->geometry();
|
||||||
|
moveLabel->setText(str);
|
||||||
|
}
|
||||||
|
void mouseReleaseEvent(QMouseEvent *) {
|
||||||
|
if (moveLabel)
|
||||||
|
moveLabel->hide();
|
||||||
|
}
|
||||||
|
void showEvent(QShowEvent *) {
|
||||||
|
refreshTimer.start(300, this);
|
||||||
|
}
|
||||||
|
void hideEvent(QHideEvent *) {
|
||||||
|
refreshTimer.stop();
|
||||||
|
}
|
||||||
|
void paintEvent(QPaintEvent *) {
|
||||||
|
QPainter p(this);
|
||||||
|
QRectF total;
|
||||||
|
QList<QScreen*> screens = qApp->screens();
|
||||||
|
foreach (QScreen *screen, screens) {
|
||||||
|
total |= screen->geometry();
|
||||||
|
}
|
||||||
|
if (total.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
scaleFactor = qMin(width()/total.width(), height()/total.height());
|
||||||
|
|
||||||
|
p.fillRect(rect(), Qt::black);
|
||||||
|
p.scale(scaleFactor, scaleFactor);
|
||||||
|
p.translate(-total.topLeft());
|
||||||
|
p.setPen(QPen(Qt::white, 10));
|
||||||
|
p.setBrush(Qt::gray);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (QScreen *screen, screens) {
|
||||||
|
p.drawRect(screen->geometry());
|
||||||
|
QFont f = font();
|
||||||
|
f.setPixelSize(screen->geometry().height() / 8);
|
||||||
|
p.setFont(f);
|
||||||
|
p.drawText(screen->geometry(), Qt::AlignCenter, screen->name());
|
||||||
|
}
|
||||||
|
p.setBrush(QColor(200,220,255,127));
|
||||||
|
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
|
||||||
|
if (!widget->isHidden())
|
||||||
|
p.drawRect(widget->geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
QPolygon cursorShape;
|
||||||
|
cursorShape << QPoint(0,0) << QPoint(20, 60)
|
||||||
|
<< QPoint(30, 50) << QPoint(60, 80)
|
||||||
|
<< QPoint(80, 60) << QPoint(50, 30)
|
||||||
|
<< QPoint(60, 20);
|
||||||
|
cursorShape.translate(QCursor::pos());
|
||||||
|
p.drawPolygon(cursorShape);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
QLabel *moveLabel;
|
||||||
|
QBasicTimer refreshTimer;
|
||||||
|
qreal scaleFactor;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PhysicalSizeTest : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PhysicalSizeTest() : QWidget(), m_ignoreResize(false) {}
|
||||||
|
void paintEvent(QPaintEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *) {
|
||||||
|
qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX();
|
||||||
|
QSizeF s = size();
|
||||||
|
if (!m_ignoreResize)
|
||||||
|
m_physicalSize = s / ppi;
|
||||||
|
}
|
||||||
|
bool event(QEvent *event) {
|
||||||
|
if (event->type() == QEvent::ScreenChangeInternal) {
|
||||||
|
// we will get resize events when the scale factor changes
|
||||||
|
m_ignoreResize = true;
|
||||||
|
QTimer::singleShot(100, this, SLOT(handleScreenChange()));
|
||||||
|
}
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
||||||
|
public slots:
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PhysicalSizeTest::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
p.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX();
|
||||||
|
qreal ppmm = ppi / 25.4;
|
||||||
|
qreal h = 15 * ppmm;
|
||||||
|
QRectF rulerRect(0,0, width(), h);
|
||||||
|
rulerRect.moveCenter(rect().center());
|
||||||
|
|
||||||
|
QFont f = font();
|
||||||
|
f.setPixelSize(18);
|
||||||
|
p.setFont(f);
|
||||||
|
|
||||||
|
// draw a rectangle in (Qt) pixel coordinates, for comparison
|
||||||
|
QRect pixelRect(0, 0, 300, 50);
|
||||||
|
pixelRect.moveTopLeft(QPoint(5 * ppmm, rulerRect.bottom() + 5 * ppmm));
|
||||||
|
p.fillRect(pixelRect, QColor(199,222,255));
|
||||||
|
p.drawText(pixelRect, "This rectangle is 300x50 pixels");
|
||||||
|
|
||||||
|
f.setPixelSize(4 * ppmm);
|
||||||
|
p.setFont(f);
|
||||||
|
|
||||||
|
QRectF topRect(0, 0, width(), rulerRect.top());
|
||||||
|
p.drawText(topRect, Qt::AlignCenter, "The ruler is drawn in physical units.\nThis window tries to keep its physical size\nwhen moved between screens.");
|
||||||
|
|
||||||
|
// draw a ruler in real physical coordinates
|
||||||
|
|
||||||
|
p.fillRect(rulerRect, QColor(255, 222, 111));
|
||||||
|
|
||||||
|
QPen linePen(Qt::black, 0.3 * ppmm);
|
||||||
|
p.setPen(linePen);
|
||||||
|
f.setBold(true);
|
||||||
|
p.setFont(f);
|
||||||
|
|
||||||
|
qreal vCenter = rulerRect.center().y();
|
||||||
|
p.drawLine(0, vCenter, width(), vCenter);
|
||||||
|
|
||||||
|
// cm
|
||||||
|
for (int i = 0;;) {
|
||||||
|
i++;
|
||||||
|
qreal x = i * ppmm;
|
||||||
|
if (x > width())
|
||||||
|
break;
|
||||||
|
qreal y = rulerRect.bottom();
|
||||||
|
qreal len;
|
||||||
|
if (i % 5)
|
||||||
|
len = 2 * ppmm;
|
||||||
|
else if (i % 10)
|
||||||
|
len = 3 * ppmm;
|
||||||
|
else
|
||||||
|
len = h / 2;
|
||||||
|
|
||||||
|
p.drawLine(QPointF(x, y), QPointF(x, y - len));
|
||||||
|
if (i % 10 == 5) {
|
||||||
|
QRectF textR(0, 0, 5 * ppmm, h / 2 - 2 * ppmm);
|
||||||
|
textR.moveTopLeft(QPointF(x, vCenter));
|
||||||
|
int n = i / 10 + 1;
|
||||||
|
if (n % 10 == 0)
|
||||||
|
p.setPen(Qt::red);
|
||||||
|
p.drawText(textR, Qt::AlignCenter, QString::number(n));
|
||||||
|
p.setPen(linePen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//inches
|
||||||
|
for (int i = 0;;) {
|
||||||
|
i++;
|
||||||
|
qreal x = i * ppi / 16;
|
||||||
|
if (x > width())
|
||||||
|
break;
|
||||||
|
qreal y = rulerRect.top();
|
||||||
|
|
||||||
|
qreal d = h / 10;
|
||||||
|
qreal len;
|
||||||
|
if (i % 2)
|
||||||
|
len = 1 * d;
|
||||||
|
else if (i % 4)
|
||||||
|
len = 2 * d;
|
||||||
|
else if (i % 8)
|
||||||
|
len = 3 * d;
|
||||||
|
else if (i % 16)
|
||||||
|
len = 4 * d;
|
||||||
|
else
|
||||||
|
len = h / 2;
|
||||||
|
|
||||||
|
p.drawLine(QPointF(x, y), QPointF(x, y + len));
|
||||||
|
if (i % 16 == 12) {
|
||||||
|
QRectF textR(0, 0, 0.25 * ppi, h / 2 - 2 * d);
|
||||||
|
textR.moveBottomLeft(QPointF(x, vCenter));
|
||||||
|
p.drawText(textR, Qt::AlignCenter, QString::number(1 + i/16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -468,90 +1088,51 @@ int main(int argc, char **argv)
|
|||||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||||
|
|
||||||
|
int argumentCount = QCoreApplication::arguments().count();
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription("High DPI tester");
|
parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n"
|
||||||
|
"test various high-dpi aspects. \n"
|
||||||
|
"--interactive is a special option and opens a configuration"
|
||||||
|
" window.");
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addVersionOption();
|
parser.addVersionOption();
|
||||||
QCommandLineOption pixmapPainterOption("pixmap", "Test pixmap painter");
|
QCommandLineOption controllerOption("interactive", "Show configuration window.");
|
||||||
parser.addOption(pixmapPainterOption);
|
parser.addOption(controllerOption);
|
||||||
QCommandLineOption labelOption("label", "Test Labels");
|
|
||||||
parser.addOption(labelOption);
|
|
||||||
QCommandLineOption mainWindowOption("mainwindow", "Test QMainWindow");
|
DemoContainerList demoList;
|
||||||
parser.addOption(mainWindowOption);
|
demoList << new DemoContainer<PixmapPainter>("pixmap", "Test pixmap painter");
|
||||||
QCommandLineOption standardIconsOption("standard-icons", "Test standard icons");
|
demoList << new DemoContainer<Labels>("label", "Test Labels");
|
||||||
parser.addOption(standardIconsOption);
|
demoList << new DemoContainer<MainWindow>("mainwindow", "Test QMainWindow");
|
||||||
QCommandLineOption cachingOption("caching", "Test caching");
|
demoList << new DemoContainer<StandardIcons>("standard-icons", "Test standard icons");
|
||||||
parser.addOption(cachingOption);
|
demoList << new DemoContainer<Caching>("caching", "Test caching");
|
||||||
QCommandLineOption styleOption("styles", "Test style");
|
demoList << new DemoContainer<Style>("styles", "Test style");
|
||||||
parser.addOption(styleOption);
|
demoList << new DemoContainer<Fonts>("fonts", "Test fonts");
|
||||||
QCommandLineOption fontsOption("fonts", "Test fonts");
|
demoList << new DemoContainer<IconDrawing>("icondrawing", "Test icon drawing");
|
||||||
parser.addOption(fontsOption);
|
demoList << new DemoContainer<Buttons>("buttons", "Test buttons");
|
||||||
QCommandLineOption iconDrawingOption("icondrawing", "Test icon drawing");
|
demoList << new DemoContainer<LinePainter>("linepainter", "Test line painting");
|
||||||
parser.addOption(iconDrawingOption);
|
demoList << new DemoContainer<DragWidget>("draganddrop", "Test drag and drop");
|
||||||
QCommandLineOption buttonsOption("buttons", "Test buttons");
|
demoList << new DemoContainer<CursorTester>("cursorpos", "Test cursor and window positioning");
|
||||||
parser.addOption(buttonsOption);
|
demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning");
|
||||||
|
demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch");
|
||||||
|
|
||||||
|
|
||||||
|
foreach (DemoContainerBase *demo, demoList)
|
||||||
|
parser.addOption(demo->option());
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
QScopedPointer<PixmapPainter> pixmapPainter;
|
//controller takes ownership of all demos
|
||||||
if (parser.isSet(pixmapPainterOption)) {
|
DemoController controller(&demoList, &parser);
|
||||||
pixmapPainter.reset(new PixmapPainter);
|
|
||||||
pixmapPainter->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<Labels> label;
|
if (parser.isSet(controllerOption) || argumentCount <= 1)
|
||||||
if (parser.isSet(labelOption)) {
|
controller.show();
|
||||||
label.reset(new Labels);
|
|
||||||
label->resize(200, 200);
|
|
||||||
label->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<MainWindow> mainWindow;
|
|
||||||
if (parser.isSet(mainWindowOption)) {
|
|
||||||
mainWindow.reset(new MainWindow);
|
|
||||||
mainWindow->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<StandardIcons> icons;
|
|
||||||
if (parser.isSet(standardIconsOption)) {
|
|
||||||
icons.reset(new StandardIcons);
|
|
||||||
icons->resize(510, 510);
|
|
||||||
icons->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<Caching> caching;
|
|
||||||
if (parser.isSet(cachingOption)) {
|
|
||||||
caching.reset(new Caching);
|
|
||||||
caching->resize(300, 300);
|
|
||||||
caching->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<Style> style;
|
|
||||||
if (parser.isSet(styleOption)) {
|
|
||||||
style.reset(new Style);
|
|
||||||
style->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<Fonts> fonts;
|
|
||||||
if (parser.isSet(fontsOption)) {
|
|
||||||
fonts.reset(new Fonts);
|
|
||||||
fonts->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<IconDrawing> iconDrawing;
|
|
||||||
if (parser.isSet(iconDrawingOption)) {
|
|
||||||
iconDrawing.reset(new IconDrawing);
|
|
||||||
iconDrawing->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
QScopedPointer<Buttons> buttons;
|
|
||||||
if (parser.isSet(buttonsOption)) {
|
|
||||||
buttons.reset(new Buttons);
|
|
||||||
buttons->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QApplication::topLevelWidgets().isEmpty())
|
if (QApplication::topLevelWidgets().isEmpty())
|
||||||
parser.showHelp(0);
|
parser.showHelp(0);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "main.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user