qt6windows7/tests/manual/windowgeometry/controllerwidget.cpp

451 lines
15 KiB
C++
Raw Normal View History

2023-10-30 06:33:08 +08:00
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "controllerwidget.h"
#include <controls.h>
#include <QtWidgets>
#include <QBackingStore>
#include <QPaintDevice>
#include <QPainter>
#include <QResizeEvent>
#include <QWindow>
CoordinateControl::CoordinateControl(const QString &sep) : m_x(new QSpinBox), m_y(new QSpinBox)
{
m_x->setMinimum(0);
m_x->setMaximum(2000);
connect(m_x, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged()));
m_y->setMinimum(0);
m_y->setMaximum(2000);
connect(m_y, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged()));
QHBoxLayout *l = new QHBoxLayout(this);
l->setSpacing(2);
l->addWidget(m_x);
l->addWidget(new QLabel(sep));
l->addWidget(m_y);
}
void CoordinateControl::setCoordinates(int x, int y)
{
m_x->blockSignals(true);
m_y->blockSignals(true);
m_x->setValue(x);
m_y->setValue(y);
m_x->blockSignals(false);
m_y->blockSignals(false);
}
QPair<int, int> CoordinateControl::coordinates() const
{
return QPair<int, int>(m_x->value(), m_y->value());
}
void CoordinateControl::spinBoxChanged()
{
const int x = m_x->value();
const int y = m_y->value();
emit pointValueChanged(QPoint(x, y));
emit sizeValueChanged(QSize(x, y));
}
RectControl::RectControl()
: m_point(new CoordinateControl(QLatin1String("+")))
, m_size(new CoordinateControl(QLatin1String("x")))
{
QHBoxLayout *l = new QHBoxLayout(this);
l->setSpacing(0);
l->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
connect(m_point, SIGNAL(pointValueChanged(QPoint)), this, SLOT(handleChanged()));
connect(m_point, SIGNAL(pointValueChanged(QPoint)), this, SIGNAL(positionChanged(QPoint)));
l->addWidget(m_point);
l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
connect(m_size, SIGNAL(sizeValueChanged(QSize)), this, SLOT(handleChanged()));
connect(m_size, SIGNAL(sizeValueChanged(QSize)), this, SIGNAL(sizeChanged(QSize)));
l->addWidget(m_size);
}
void RectControl::setRectValue(const QRect &r)
{
m_point->setPointValue(r.topLeft());
m_size->setSizeValue(r.size());
}
QRect RectControl::rectValue() const
{
return QRect(m_point->pointValue(), m_size->sizeValue());
}
void RectControl::handleChanged()
{
emit changed(rectValue());
}
BaseWindowControl::BaseWindowControl(QObject *w)
: m_layout(new QGridLayout(this))
, m_object(w)
, m_geometry(new RectControl)
, m_framePosition(new CoordinateControl(QLatin1String("x")))
, m_typeControl(new TypeControl)
, m_hintControl(new HintControl)
, m_moveEventLabel(new QLabel(tr("Move events")))
, m_resizeEventLabel(new QLabel(tr("Resize events")))
, m_mouseEventLabel(new QLabel(tr("Mouse events")))
, m_moveCount(0)
, m_resizeCount(0)
{
m_object->installEventFilter(this);
m_geometry->setTitle(tr("Geometry"));
int row = 0;
m_layout->addWidget(m_geometry, row, 0, 1, 2);
m_layout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
QGroupBox *frameGB = new QGroupBox(tr("Frame"));
QVBoxLayout *frameL = new QVBoxLayout(frameGB);
frameL->setSpacing(0);
frameL->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
frameL->addWidget(m_framePosition);
m_layout->addWidget(frameGB, row, 2);
m_layout->addWidget(m_hintControl, ++row, 0, 1, 2);
connect(m_hintControl, SIGNAL(changed(Qt::WindowFlags)), this, SLOT(windowFlagsChanged()));
m_layout->addWidget(m_typeControl, row, 2);
connect(m_typeControl, SIGNAL(changed(Qt::WindowFlags)), this, SLOT(windowFlagsChanged()));
QGroupBox *eventGroupBox = new QGroupBox(tr("Events"));
QVBoxLayout *l = new QVBoxLayout(eventGroupBox);
l->setSpacing(0);
l->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
l->addWidget(m_moveEventLabel);
l->addWidget(m_resizeEventLabel);
l->addWidget(m_mouseEventLabel);
m_layout->addWidget(eventGroupBox, ++row, 2);
connect(m_geometry, SIGNAL(positionChanged(QPoint)), this, SLOT(posChanged(QPoint)));
connect(m_geometry, SIGNAL(sizeChanged(QSize)), this, SLOT(sizeChanged(QSize)));
connect(m_framePosition, SIGNAL(pointValueChanged(QPoint)), this, SLOT(framePosChanged(QPoint)));
}
bool BaseWindowControl::eventFilter(QObject *, QEvent *e)
{
switch (e->type()) {
case QEvent::Resize: {
const QResizeEvent *re = static_cast<const QResizeEvent *>(e);
m_resizeEventLabel->setText(tr("Resize %1x%2 (#%3)")
.arg(re->size().width()).arg(re->size().height())
.arg(++m_resizeCount));
refresh();
}
break;
case QEvent::Move: {
const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
m_moveEventLabel->setText(tr("Move %1,%2 (#%3)")
.arg(me->pos().x()).arg(me->pos().y())
.arg(++m_moveCount));
refresh();
}
break;
case QEvent::MouseMove: {
const QMouseEvent *me = static_cast<const QMouseEvent *>(e);
const QPoint pos = me->pos();
QPoint globalPos = objectMapToGlobal(m_object, pos);
m_mouseEventLabel->setText(tr("Mouse: %1,%2 Global: %3,%4 ").
arg(pos.x()).arg(pos.y()).arg(globalPos.x()).arg(globalPos.y()));
}
break;
case QEvent::WindowStateChange:
refresh();
default:
break;
}
return false;
}
void BaseWindowControl::posChanged(const QPoint &p)
{
QRect geom = objectGeometry(m_object);
geom.moveTopLeft(p);
setObjectGeometry(m_object, geom);
}
void BaseWindowControl::sizeChanged(const QSize &s)
{
QRect geom = objectGeometry(m_object);
geom.setSize(s);
setObjectGeometry(m_object, geom);
}
void BaseWindowControl::framePosChanged(const QPoint &p)
{
setObjectFramePosition(m_object, p);
}
void BaseWindowControl::windowFlagsChanged()
{
const Qt::WindowFlags f = m_typeControl->type() | m_hintControl->hints();
setObjectWindowFlags(m_object, f);
}
void BaseWindowControl::refresh()
{
m_geometry->setRectValue(objectGeometry(m_object));
m_framePosition->setPointValue(objectFramePosition(m_object));
const Qt::WindowFlags flags = objectWindowFlags(m_object);
m_typeControl->setType(flags);
m_hintControl->setHints(flags);
}
// A control for a QWidget
class WidgetWindowControl : public BaseWindowControl
{
Q_OBJECT
public:
explicit WidgetWindowControl(QWidget *w);
virtual void refresh();
private slots:
void statesChanged();
private:
virtual QRect objectGeometry(const QObject *o) const
{ return static_cast<const QWidget *>(o)->geometry(); }
virtual void setObjectGeometry(QObject *o, const QRect &r) const
{ static_cast<QWidget *>(o)->setGeometry(r); }
virtual QPoint objectFramePosition(const QObject *o) const
{ return static_cast<const QWidget *>(o)->pos(); }
virtual void setObjectFramePosition(QObject *o, const QPoint &p) const
{ static_cast<QWidget *>(o)->move(p); }
virtual QPoint objectMapToGlobal(const QObject *o, const QPoint &p) const
{ return static_cast<const QWidget *>(o)->mapToGlobal(p); }
virtual Qt::WindowFlags objectWindowFlags(const QObject *o) const
{ return static_cast<const QWidget *>(o)->windowFlags(); }
virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f);
WindowStatesControl *m_statesControl;
};
WidgetWindowControl::WidgetWindowControl(QWidget *w )
: BaseWindowControl(w)
, m_statesControl(new WindowStatesControl)
{
setTitle(w->windowTitle());
m_layout->addWidget(m_statesControl, 2, 0);
connect(m_statesControl, SIGNAL(changed()), this, SLOT(statesChanged()));
}
void WidgetWindowControl::setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
{
QWidget *w = static_cast<QWidget *>(o);
const bool visible = w->isVisible();
w->setWindowFlags(f); // hides.
if (visible)
w->show();
}
void WidgetWindowControl::refresh()
{
const QWidget *w = static_cast<const QWidget *>(m_object);
m_statesControl->setVisibleValue(w->isVisible());
m_statesControl->setStates(w->windowState());
BaseWindowControl::refresh();
}
void WidgetWindowControl::statesChanged()
{
QWidget *w = static_cast<QWidget *>(m_object);
w->setVisible(m_statesControl->visibleValue());
w->setWindowState(m_statesControl->states());
}
// Test window drawing diagonal lines
class Window : public QWindow
{
public:
explicit Window(QWindow *parent = nullptr)
: QWindow(parent)
, m_backingStore(new QBackingStore(this))
{
setObjectName(QStringLiteral("window"));
setTitle(tr("TestWindow"));
}
protected:
void exposeEvent(QExposeEvent *)
{ render(); }
private:
QBackingStore *m_backingStore;
void render();
};
void Window::render()
{
QRect rect(QPoint(), geometry().size());
m_backingStore->resize(rect.size());
m_backingStore->beginPaint(rect);
if (!rect.size().isEmpty()) {
QPaintDevice *device = m_backingStore->paintDevice();
QPainter p(device);
p.fillRect(rect, Qt::white);
p.drawLine(0, 0, rect.width(), rect.height());
p.drawLine(0, rect.height(), rect.width(), 0);
}
m_backingStore->endPaint();
m_backingStore->flush(rect);
}
// A control for a QWindow
class WindowControl : public BaseWindowControl
{
Q_OBJECT
public:
explicit WindowControl(QWindow *w);
virtual void refresh();
private slots:
void stateChanged();
private:
virtual QRect objectGeometry(const QObject *o) const
{ return static_cast<const QWindow *>(o)->geometry(); }
virtual void setObjectGeometry(QObject *o, const QRect &r) const
{ static_cast<QWindow *>(o)->setGeometry(r); }
virtual QPoint objectFramePosition(const QObject *o) const
{ return static_cast<const QWindow *>(o)->framePosition(); }
virtual void setObjectFramePosition(QObject *o, const QPoint &p) const
{ static_cast<QWindow *>(o)->setFramePosition(p); }
virtual QPoint objectMapToGlobal(const QObject *o, const QPoint &p) const
{ return static_cast<const QWindow *>(o)->mapToGlobal(p); }
virtual Qt::WindowFlags objectWindowFlags(const QObject *o) const
{ return static_cast<const QWindow *>(o)->flags(); }
virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
{ static_cast<QWindow *>(o)->setFlags(f); }
WindowStatesControl *m_statesControl;
};
WindowControl::WindowControl(QWindow *w )
: BaseWindowControl(w)
, m_statesControl(new WindowStatesControl)
{
setTitle(w->title());
QGroupBox *stateGroupBox = new QGroupBox(tr("State"));
QVBoxLayout *l = new QVBoxLayout(stateGroupBox);
l->addWidget(m_statesControl);
m_layout->addWidget(stateGroupBox, 2, 0);
connect(m_statesControl, SIGNAL(changed()), this, SLOT(stateChanged()));
}
void WindowControl::refresh()
{
const QWindow *w = static_cast<const QWindow *>(m_object);
BaseWindowControl::refresh();
m_statesControl->setVisibleValue(w->isVisible());
m_statesControl->setStates(w->windowStates());
}
void WindowControl::stateChanged()
{
QWindow *w = static_cast<QWindow *>(m_object);
w->setVisible(m_statesControl->visibleValue());
w->setWindowStates(m_statesControl->states());
}
ControllerWidget::ControllerWidget(QWidget *parent)
: QMainWindow(parent)
, m_testWidget(new QWidget)
, m_testWindow(new Window)
{
QMenu *fileMenu = menuBar()->addMenu(tr("File"));
QAction *exitAction = fileMenu->addAction(tr("Exit"));
exitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q));
connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
QString title = QLatin1String("Geometry test, (Qt ");
title += QLatin1String(QT_VERSION_STR);
title += QLatin1String(", ");
title += qApp->platformName();
title += QLatin1Char(')');
setWindowTitle(title);
int x = 100;
int y = 100;
const QStringList args = QApplication::arguments();
const int offsetArgIndex = args.indexOf(QLatin1String("-offset"));
if (offsetArgIndex >=0 && offsetArgIndex < args.size() - 1) {
y += args.at(offsetArgIndex + 1).toInt();
}
move(x, y);
x += 800;
m_testWidget->setWindowTitle(tr("TestWidget"));
if (args.contains(QLatin1String("-layout"))) {
QVBoxLayout *layout = new QVBoxLayout(m_testWidget.data());
QLabel *label = new QLabel("Hallo");
layout->addWidget(label);
}
m_testWidget->move(x, y);
m_testWidget->resize(200, 200);
if (args.contains(QLatin1String("-widgetminimized"), Qt::CaseInsensitive))
m_testWidget->showMinimized();
else if (args.contains(QLatin1String("-widgetmaximized"), Qt::CaseInsensitive))
m_testWidget->showMaximized();
else if (args.contains(QLatin1String("-widgetfullscreen"), Qt::CaseInsensitive))
m_testWidget->showFullScreen();
else
m_testWidget->show();
x += 300;
m_testWindow->setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint
| Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint
| Qt::WindowTitleHint | Qt::WindowFullscreenButtonHint);
m_testWindow->setFramePosition(QPoint(x, y));
m_testWindow->resize(200, 200);
if (args.contains(QLatin1String("-windowminimized"), Qt::CaseInsensitive))
m_testWindow->showMinimized();
else if (args.contains(QLatin1String("-windowmaximized"), Qt::CaseInsensitive))
m_testWindow->showMaximized();
else if (args.contains(QLatin1String("-windowfullscreen"), Qt::CaseInsensitive))
m_testWindow->showFullScreen();
else
m_testWindow->show();
m_testWindow->setTitle(tr("TestWindow"));
QWidget *central = new QWidget ;
QVBoxLayout *l = new QVBoxLayout(central);
const QString labelText = tr(
"<html><head/><body><p>This example lets you control the geometry"
" of a QWidget and a QWindow (Qt 5) for testing out"
" QPA plugins.</p>"
"<p>It compiles with Qt 4 and Qt 5 for comparison.</p>"
"<p>The command line option <code>-offset &lt;value&gt;</code> specifies"
" a vertical offset.</p></body></html>");
l->addWidget(new QLabel(labelText));
BaseWindowControl *widgetControl = new WidgetWindowControl(m_testWidget.data());
widgetControl->refresh();
l->addWidget(widgetControl);
BaseWindowControl *windowControl = new WindowControl(m_testWindow.data());
windowControl->refresh();
l->addWidget(windowControl);
setCentralWidget(central);
}
ControllerWidget::~ControllerWidget()
{
}
#include "controllerwidget.moc"