qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View File

@ -0,0 +1,38 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(imagegestures LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/gestures/imagegestures")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(imagegestures
imagewidget.cpp imagewidget.h
main.cpp
mainwidget.cpp mainwidget.h
)
set_target_properties(imagegestures PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(imagegestures PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS imagegestures
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,111 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example gestures/imagegestures
\title Image Gestures Example
\brief Demonstrates the use of simple gestures in a widget.
This example shows how to enable gestures for a widget and use gesture input
to perform actions.
\image imagegestures-example.jpg
We use two classes to create the user interface for the application: \c MainWidget
and \c ImageWidget. The \c MainWidget class is simply used as a container for the
\c ImageWidget class, which we will configure to accept gesture input. Since we
are interested in the way gestures are used, we will concentrate on the
implementation of the \c ImageWidget class.
\section1 ImageWidget Class Definition
The \c ImageWidget class is a simple QWidget subclass that reimplements the general
QWidget::event() handler function in addition to several more specific event handlers:
\snippet gestures/imagegestures/imagewidget.h class definition begin
\dots
\snippet gestures/imagegestures/imagewidget.h class definition end
We also implement a private helper function, \c gestureEvent(), to help manage
gesture events delivered to the widget, and three functions to perform actions
based on gestures: \c panTriggered(), \c pinchTriggered() and \c swipeTriggered().
\section1 ImageWidget Class Implementation
In the widget's constructor, we begin by setting up various parameters that will
be used to control the way images are displayed.
\snippet gestures/imagegestures/imagewidget.cpp constructor
We enable three of the standard gestures for the widget by calling QWidget::grabGesture()
with the types of gesture we need. These will be recognized by the application's
default gesture recognizer, and events will be delivered to our widget.
Since QWidget does not define a specific event handler for gestures, the widget
needs to reimplement the general QWidget::event() to receive gesture events.
\snippet gestures/imagegestures/imagewidget.cpp event handler
We implement the event handler to delegate gesture events to a private function
specifically written for the task, and pass all other events to QWidget's
implementation.
The \c gestureHandler() function examines the gestures supplied by the
newly-delivered QGestureEvent. Since only one gesture of a given type can be
used on a widget at any particular time, we can check for each gesture type
using the QGestureEvent::gesture() function:
\snippet gestures/imagegestures/imagewidget.cpp gesture event handler
If a QGesture object is supplied for a certain type of gesture, we call a special
purpose function to deal with it, casting the gesture object to the appropriate
QGesture subclass.
To illustrate how a standard gesture can be interpreted by an application, we
show the implementation of the \c pinchTriggered() function, which handles the
pinch gesture when the user moves two fingers around on the display or
input device:
\snippet gestures/imagegestures/imagewidget.cpp pinch function
The QPinchGesture class provides properties to interpret the changing
distance between the two touch points as a zoom factor, and the angle delta
as a rotation to be applied to the image. The center point between the
touch points could be used to drag the image, but in this example we use
the pan gesture for that purpose.
The \c scaleFactor() is a relative value representing how much the zoom
should change from one event to the next, whereas \c totalScaleFactor()
provides the amount of zoom that has been expressed since the gesture
began. When the touch points are released and another gesture begins,
\c totalScaleFactor() will begin again at 1.0. In this case we store
\c totalScaleFactor() into the \c currentStepScaleFactor variable so that
it can be used in \c paintEvent() to scale the image. Alternatively it would
be possible to simply multiply the stored total scale factor by
\c scaleFactor() here in the pinch handler.
In contrast, \c rotationAngle() represents the amount of rotation since the
pinch gesture began, while \c lastRotationAngle() provides the previous
value. So it is necessary to subtract in order to get an incremental delta.
When the user begins a new pinch gesture, \c rotationAngle() will start
from zero, and we want the image to begin to rotate from its current angle.
This is achieved by adding the delta to the stored \c rotationAngle (which
will be applied in \c paintEvent()). If we simply assigned
\c totalRotationAngle() to the stored \c rotationAngle, a new gesture would
cause the image to reset to a right-side-up orientation before beginning to
rotate again. But it would be possible to store the rotation angle since the
gesture began and add it to \c rotationAngle in \c paintEvent(), just as
we store the amount of zoom since the gesture began.
The pan and swipe gestures in this example are also handled in separate
functions, and use the values of properties from the QGesture objects
passed to them.
\snippet gestures/imagegestures/imagewidget.cpp paint method
In \c paintEvent(), scaleFactor represents the zoom level before the pinch
gesture began, while currentStepScaleFactor represents the additional zoom
factor while a pinch gesture is in progress. But for rotation, only the
current rotationAngle is stored. The horizontal and vertical offsets
represent the distance that the image has been dragged by the pan gesture.
*/

View File

@ -0,0 +1,13 @@
QT += widgets
requires(qtConfig(filedialog))
HEADERS = imagewidget.h \
mainwidget.h
SOURCES = imagewidget.cpp \
main.cpp \
mainwidget.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/gestures/imagegestures
INSTALLS += target

View File

@ -0,0 +1,246 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "imagewidget.h"
#include <QDir>
#include <QImageReader>
#include <QGestureEvent>
#include <QPainter>
Q_LOGGING_CATEGORY(lcExample, "qt.examples.imagegestures")
//! [constructor]
ImageWidget::ImageWidget(QWidget *parent)
: QWidget(parent), position(0), horizontalOffset(0), verticalOffset(0)
, rotationAngle(0), scaleFactor(1), currentStepScaleFactor(1)
{
setMinimumSize(QSize(100, 100));
}
//! [constructor]
void ImageWidget::grabGestures(const QList<Qt::GestureType> &gestures)
{
//! [enable gestures]
for (Qt::GestureType gesture : gestures)
grabGesture(gesture);
//! [enable gestures]
}
//! [event handler]
bool ImageWidget::event(QEvent *event)
{
if (event->type() == QEvent::Gesture)
return gestureEvent(static_cast<QGestureEvent*>(event));
return QWidget::event(event);
}
//! [event handler]
//! [paint method]
void ImageWidget::paintEvent(QPaintEvent*)
{
QPainter p(this);
const qreal iw = currentImage.width();
const qreal ih = currentImage.height();
const qreal wh = height();
const qreal ww = width();
p.translate(ww / 2, wh / 2);
p.translate(horizontalOffset, verticalOffset);
p.rotate(rotationAngle);
p.scale(currentStepScaleFactor * scaleFactor, currentStepScaleFactor * scaleFactor);
p.translate(-iw / 2, -ih / 2);
p.drawImage(0, 0, currentImage);
}
//! [paint method]
void ImageWidget::mouseDoubleClickEvent(QMouseEvent *)
{
rotationAngle = 0;
scaleFactor = 1;
currentStepScaleFactor = 1;
verticalOffset = 0;
horizontalOffset = 0;
update();
qCDebug(lcExample) << "reset on mouse double click";
}
//! [gesture event handler]
bool ImageWidget::gestureEvent(QGestureEvent *event)
{
qCDebug(lcExample) << "gestureEvent():" << event;
if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
swipeTriggered(static_cast<QSwipeGesture *>(swipe));
else if (QGesture *pan = event->gesture(Qt::PanGesture))
panTriggered(static_cast<QPanGesture *>(pan));
if (QGesture *pinch = event->gesture(Qt::PinchGesture))
pinchTriggered(static_cast<QPinchGesture *>(pinch));
return true;
}
//! [gesture event handler]
void ImageWidget::panTriggered(QPanGesture *gesture)
{
#ifndef QT_NO_CURSOR
switch (gesture->state()) {
case Qt::GestureStarted:
case Qt::GestureUpdated:
setCursor(Qt::SizeAllCursor);
break;
default:
setCursor(Qt::ArrowCursor);
}
#endif
QPointF delta = gesture->delta();
qCDebug(lcExample) << "panTriggered():" << gesture;
horizontalOffset += delta.x();
verticalOffset += delta.y();
update();
}
//! [pinch function]
void ImageWidget::pinchTriggered(QPinchGesture *gesture)
{
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::RotationAngleChanged) {
qreal rotationDelta = gesture->rotationAngle() - gesture->lastRotationAngle();
rotationAngle += rotationDelta;
qCDebug(lcExample) << "pinchTriggered(): rotate by" <<
rotationDelta << "->" << rotationAngle;
}
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
currentStepScaleFactor = gesture->totalScaleFactor();
qCDebug(lcExample) << "pinchTriggered(): zoom by" <<
gesture->scaleFactor() << "->" << currentStepScaleFactor;
}
if (gesture->state() == Qt::GestureFinished) {
scaleFactor *= currentStepScaleFactor;
currentStepScaleFactor = 1;
}
update();
}
//! [pinch function]
//! [swipe function]
void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
if (gesture->state() == Qt::GestureFinished) {
if (gesture->horizontalDirection() == QSwipeGesture::Left
|| gesture->verticalDirection() == QSwipeGesture::Up) {
qCDebug(lcExample) << "swipeTriggered(): swipe to previous";
goPrevImage();
} else {
qCDebug(lcExample) << "swipeTriggered(): swipe to next";
goNextImage();
}
update();
}
}
//! [swipe function]
void ImageWidget::resizeEvent(QResizeEvent*)
{
update();
}
void ImageWidget::openDirectory(const QString &path)
{
this->path = path;
QDir dir(path);
const QStringList nameFilters{"*.jpg", "*.png"};
files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name);
position = 0;
goToImage(0);
update();
}
QImage ImageWidget::loadImage(const QString &fileName) const
{
QImageReader reader(fileName);
reader.setAutoTransform(true);
qCDebug(lcExample) << "loading" << QDir::toNativeSeparators(fileName) << position << '/' << files.size();
if (!reader.canRead()) {
qCWarning(lcExample) << QDir::toNativeSeparators(fileName) << ": can't load image";
return QImage();
}
QImage image;
if (!reader.read(&image)) {
qCWarning(lcExample) << QDir::toNativeSeparators(fileName) << ": corrupted image: " << reader.errorString();
return QImage();
}
const QSize maximumSize(2000, 2000); // Reduce in case someone has large photo images.
if (image.size().width() > maximumSize.width() || image.height() > maximumSize.height())
image = image.scaled(maximumSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
return image;
}
void ImageWidget::goNextImage()
{
if (files.isEmpty())
return;
if (position < files.size()-1) {
++position;
prevImage = currentImage;
currentImage = nextImage;
if (position+1 < files.size())
nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1));
else
nextImage = QImage();
}
update();
}
void ImageWidget::goPrevImage()
{
if (files.isEmpty())
return;
if (position > 0) {
--position;
nextImage = currentImage;
currentImage = prevImage;
if (position > 0)
prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1));
else
prevImage = QImage();
}
update();
}
void ImageWidget::goToImage(int index)
{
if (files.isEmpty())
return;
if (index < 0 || index >= files.size()) {
qCWarning(lcExample) << "goToImage: invalid index: " << index;
return;
}
if (index == position+1) {
goNextImage();
return;
}
if (position > 0 && index == position-1) {
goPrevImage();
return;
}
position = index;
if (index > 0)
prevImage = loadImage(path + QLatin1Char('/') + files.at(position-1));
else
prevImage = QImage();
currentImage = loadImage(path + QLatin1Char('/') + files.at(position));
if (position+1 < files.size())
nextImage = loadImage(path + QLatin1Char('/') + files.at(position+1));
else
nextImage = QImage();
update();
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H
#include <QImage>
#include <QLoggingCategory>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QGestureEvent;
class QPanGesture;
class QPinchGesture;
class QSwipeGesture;
QT_END_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcExample)
//! [class definition begin]
class ImageWidget : public QWidget
{
Q_OBJECT
public:
ImageWidget(QWidget *parent = nullptr);
void openDirectory(const QString &path);
void grabGestures(const QList<Qt::GestureType> &gestures);
protected:
bool event(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
private:
bool gestureEvent(QGestureEvent *event);
void panTriggered(QPanGesture*);
void pinchTriggered(QPinchGesture*);
void swipeTriggered(QSwipeGesture*);
//! [class definition begin]
QImage loadImage(const QString &fileName) const;
void loadImage();
void goNextImage();
void goPrevImage();
void goToImage(int index);
QString path;
QStringList files;
int position;
QImage prevImage, nextImage;
QImage currentImage;
qreal horizontalOffset;
qreal verticalOffset;
qreal rotationAngle;
qreal scaleFactor;
qreal currentStepScaleFactor;
//! [class definition end]
};
//! [class definition end]
#endif

View File

@ -0,0 +1,83 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "mainwidget.h"
static void showHelp(QCommandLineParser &parser, const QString errorMessage = QString())
{
QString text;
QTextStream str(&text);
str << "<html><head/><body>";
if (!errorMessage.isEmpty())
str << "<p>" << errorMessage << "</p>";
str << "<pre>" << parser.helpText() << "</pre></body></html>";
QMessageBox box(errorMessage.isEmpty() ? QMessageBox::Information : QMessageBox::Warning,
QGuiApplication::applicationDisplayName(), text,
QMessageBox::Ok);
box.setTextInteractionFlags(Qt::TextBrowserInteraction);
box.exec();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCoreApplication::setApplicationName(QStringLiteral("imagegestures"));
QGuiApplication::setApplicationDisplayName(QStringLiteral("Image Gestures Example"));
QCommandLineParser commandLineParser;
const QCommandLineOption disablePanOption("no-pan", "Disable pan gesture");
commandLineParser.addOption(disablePanOption);
const QCommandLineOption disablePinchOption("no-pinch", "Disable pinch gesture");
commandLineParser.addOption(disablePinchOption);
const QCommandLineOption disableSwipeOption("no-swipe", "Disable swipe gesture");
commandLineParser.addOption(disableSwipeOption);
const QCommandLineOption helpOption = commandLineParser.addHelpOption();
commandLineParser.addPositionalArgument(QStringLiteral("Directory"),
QStringLiteral("Directory to display"));
const QString description = QGuiApplication::applicationDisplayName()
+ QLatin1String("\n\nEnable \"debug\" on the logging category \"qt.examples.imagegestures\" in order to\n"
"in order to obtain verbose information about Qt's gesture event processing,\n"
"for example by setting the environment variables QT_LOGGING_RULES to\n"
"qt.examples.imagegestures.debug=true\n");
commandLineParser.setApplicationDescription(description);
commandLineParser.process(QCoreApplication::arguments());
QStringList arguments = commandLineParser.positionalArguments();
if (!arguments.isEmpty() && !QFileInfo(arguments.front()).isDir()) {
showHelp(commandLineParser,
QLatin1Char('"') + QDir::toNativeSeparators(arguments.front())
+ QStringLiteral("\" is not a directory."));
return -1;
}
QList<Qt::GestureType> gestures;
if (!commandLineParser.isSet(disablePanOption))
gestures << Qt::PanGesture;
if (!commandLineParser.isSet(disablePinchOption))
gestures << Qt::PinchGesture;
if (!commandLineParser.isSet(disableSwipeOption))
gestures << Qt::SwipeGesture;
MainWidget w;
w.grabGestures(gestures);
w.show();
if (arguments.isEmpty()) {
const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
const QString directory =
QFileDialog::getExistingDirectory(&w, "Select image folder",
picturesLocations.isEmpty() ? QString() : picturesLocations.front());
if (directory.isEmpty())
return 0;
arguments.append(directory);
}
w.openDirectory(arguments.front());
return app.exec();
}

View File

@ -0,0 +1,31 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "imagewidget.h"
#include "mainwidget.h"
#include <QScreen>
#include <QGuiApplication>
#include <QDir>
MainWidget::MainWidget(QWidget *parent)
: QMainWindow(parent)
, imageWidget(new ImageWidget(this))
{
setCentralWidget(imageWidget);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableGeometry();
QRect geometry(QPoint(0, 0), QSize(screenGeometry.width() * 3 / 4, screenGeometry.height() * 3 / 4));
geometry.moveCenter(screenGeometry.center());
setGeometry(geometry);
}
void MainWidget::openDirectory(const QString &path)
{
setWindowTitle(QDir::toNativeSeparators(path));
imageWidget->openDirectory(path);
}
void MainWidget::grabGestures(const QList<Qt::GestureType> &gestures)
{
imageWidget->grabGestures(gestures);
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QMainWindow>
class ImageWidget;
class MainWidget : public QMainWindow
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
void grabGestures(const QList<Qt::GestureType> &gestures);
public slots:
void openDirectory(const QString &path);
private:
ImageWidget *imageWidget;
};
#endif