05fc3aef53
Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Task-number: QTBUG-67283 Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
256 lines
7.3 KiB
C++
256 lines
7.3 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
|
|
|
#include <QtCore>
|
|
#include <QtWidgets>
|
|
|
|
#define NUM_ITEMS 100
|
|
#define NUM_LISTS 10
|
|
|
|
/*!
|
|
\class RectObject
|
|
Note that it needs to be a QGraphicsObject or else the gestures will not work correctly.
|
|
*/
|
|
class RectObject : public QGraphicsObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
RectObject(const QString &text, qreal x, qreal y, qreal width, qreal height, QBrush brush, QGraphicsItem *parent = nullptr)
|
|
: QGraphicsObject(parent)
|
|
, m_text(text)
|
|
, m_rect(x, y, width, height)
|
|
, m_pen(brush.color().lighter(), 3.0)
|
|
, m_brush(brush)
|
|
{
|
|
setFlag(QGraphicsItem::ItemClipsToShape, true);
|
|
}
|
|
|
|
QRectF boundingRect() const override
|
|
{
|
|
// here we only want the size of the children and not the size of the children of the children...
|
|
qreal halfpw = m_pen.widthF() / 2;
|
|
QRectF rect = m_rect;
|
|
if (halfpw > 0.0)
|
|
rect.adjust(-halfpw, -halfpw, halfpw, halfpw);
|
|
|
|
return rect;
|
|
}
|
|
|
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
|
|
{
|
|
Q_UNUSED(option);
|
|
Q_UNUSED(widget);
|
|
painter->setPen(m_pen);
|
|
painter->setBrush(m_brush);
|
|
painter->drawRect(m_rect);
|
|
|
|
painter->setPen(Qt::black);
|
|
QFont f;
|
|
f.setPixelSize(m_rect.height());
|
|
painter->setFont(f);
|
|
painter->drawText(m_rect, Qt::AlignCenter, m_text);
|
|
}
|
|
|
|
QString m_text;
|
|
QRectF m_rect;
|
|
QPen m_pen;
|
|
QBrush m_brush;
|
|
};
|
|
|
|
class ViewObject : public QGraphicsObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
ViewObject(QGraphicsObject *parent)
|
|
: QGraphicsObject(parent)
|
|
{ }
|
|
|
|
QRectF boundingRect() const override
|
|
{
|
|
QRectF rect;
|
|
const auto items = childItems();
|
|
for (const QGraphicsItem *item : items)
|
|
rect |= item->boundingRect().translated(item->pos());
|
|
return rect;
|
|
}
|
|
|
|
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override
|
|
{ }
|
|
};
|
|
|
|
class ListObject : public QGraphicsObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
ListObject(const QSizeF &size, bool useTouch)
|
|
{
|
|
m_size = size;
|
|
setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
|
|
// grab gesture via Touch or Mouse events
|
|
QScroller::grabGesture(this, useTouch ? QScroller::TouchGesture : QScroller::LeftMouseButtonGesture);
|
|
|
|
// this needs to be QGraphicsOBJECT - otherwise gesture recognition
|
|
// will not work for the parent of the viewport (in this case the
|
|
// list)
|
|
m_viewport = new ViewObject(this);
|
|
|
|
}
|
|
|
|
QGraphicsObject *viewport() const
|
|
{
|
|
return m_viewport;
|
|
}
|
|
|
|
bool event(QEvent *e) override
|
|
{
|
|
switch (e->type()) {
|
|
// ![2]
|
|
case QEvent::ScrollPrepare: {
|
|
QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
|
|
se->setViewportSize(m_size);
|
|
QRectF br = m_viewport->boundingRect();
|
|
se->setContentPosRange(QRectF(0, 0,
|
|
qMax(qreal(0), br.width() - m_size.width()),
|
|
qMax(qreal(0), br.height() - m_size.height())));
|
|
se->setContentPos(-m_viewport->pos());
|
|
se->accept();
|
|
return true;
|
|
}
|
|
// ![1]
|
|
// ![2]
|
|
case QEvent::Scroll: {
|
|
QScrollEvent *se = static_cast<QScrollEvent *>(e);
|
|
m_viewport->setPos(-se->contentPos() - se->overshootDistance());
|
|
return true;
|
|
}
|
|
// ![2]
|
|
default:
|
|
break;
|
|
}
|
|
return QGraphicsObject::event(e);
|
|
}
|
|
|
|
bool sceneEvent(QEvent *e) override
|
|
{
|
|
switch (e->type()) {
|
|
case QEvent::TouchBegin: {
|
|
// We need to return true for the TouchBegin here in the
|
|
// top-most graphics object - otherwise gestures in our parent
|
|
// objects will NOT work at all (the accept() flag is already
|
|
// set due to our setAcceptTouchEvents(true) call in the c'tor
|
|
return true;
|
|
|
|
}
|
|
case QEvent::GraphicsSceneMousePress: {
|
|
// We need to return true for the MousePress here in the
|
|
// top-most graphics object - otherwise gestures in our parent
|
|
// objects will NOT work at all (the accept() flag is already
|
|
// set to true by Qt)
|
|
return true;
|
|
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return QGraphicsObject::sceneEvent(e);
|
|
}
|
|
|
|
QRectF boundingRect() const override
|
|
{
|
|
return QRectF(0, 0, m_size.width() + 3, m_size.height());
|
|
}
|
|
|
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
|
|
{
|
|
Q_UNUSED(option);
|
|
Q_UNUSED(widget);
|
|
painter->setPen(QPen(QColor(100, 100, 100), 3.0));
|
|
painter->drawRect(QRectF(1.5, 1.5, m_size.width() - 3, m_size.height() - 3));
|
|
}
|
|
|
|
QSizeF m_size;
|
|
ViewObject *m_viewport;
|
|
};
|
|
|
|
class MainWindow : public QMainWindow
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
MainWindow(bool useTouch)
|
|
{
|
|
m_scene = new QGraphicsScene();
|
|
|
|
// -- make the main list
|
|
ListObject *mainList = new ListObject(QSizeF(780, 400), useTouch);
|
|
mainList->setObjectName(QLatin1String("MainList"));
|
|
m_scene->addItem(mainList);
|
|
// ![3]
|
|
for (int i=0; i<NUM_LISTS; i++) {
|
|
ListObject *childList = new ListObject(QSizeF(mainList->m_size.width()/3, mainList->m_size.height()), useTouch);
|
|
childList->setObjectName(QString("ChildList %1").arg(i));
|
|
fillList(childList);
|
|
childList->setParentItem(mainList->viewport());
|
|
childList->setPos(i*mainList->m_size.width()/3, 0);
|
|
}
|
|
mainList->viewport()->setPos(0, 0);
|
|
|
|
|
|
/*
|
|
list1->setTransformOriginPoint(200, 200);
|
|
list1->setRotation(135);
|
|
list1->setPos(20 + 200 * .41, 20 + 200 * .41);
|
|
*/
|
|
// ![3]
|
|
|
|
m_view = new QGraphicsView(m_scene);
|
|
setCentralWidget(m_view);
|
|
setWindowTitle(tr("Gesture example"));
|
|
m_scene->setSceneRect(0, 0, m_view->viewport()->width(), m_view->viewport()->height());
|
|
}
|
|
|
|
/**
|
|
* Fills the list object \a list with RectObjects.
|
|
*/
|
|
void fillList(ListObject *list)
|
|
{
|
|
qreal h = list->m_size.height() / 10;
|
|
for (int i=0; i<NUM_ITEMS; i++) {
|
|
QColor color = QColor(255*i/NUM_ITEMS, 255*(NUM_ITEMS-i)/NUM_ITEMS, 127*(i%2)+64*(i/2%2));
|
|
QString text = QLatin1String("Item #") + QString::number(i);
|
|
QGraphicsItem *rect = new RectObject(text, 0, 0, list->m_size.width() - 6, h - 3, QBrush(color), list->viewport());
|
|
rect->setPos(3, h*i+3);
|
|
}
|
|
list->viewport()->setPos(0, 0);
|
|
}
|
|
|
|
|
|
protected:
|
|
void resizeEvent(QResizeEvent *e) override
|
|
{
|
|
// resize the scene according to our own size to prevent scrolling
|
|
m_scene->setSceneRect(0, 0, m_view->viewport()->width(), m_view->viewport()->height());
|
|
QMainWindow::resizeEvent(e);
|
|
}
|
|
|
|
QGraphicsScene *m_scene;
|
|
QGraphicsView *m_view;
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
QApplication a(argc, argv);
|
|
bool touch = (a.arguments().contains(QLatin1String("--touch")));
|
|
MainWindow mw(touch);
|
|
mw.show();
|
|
#ifdef Q_OS_MAC
|
|
mw.raise();
|
|
#endif
|
|
return a.exec();
|
|
}
|
|
|
|
#include "main.moc"
|