Polish the image gestures example.

- Add a command line parser to properly evaluate help option and
  directory argument, add options to disable gestures.
- Add logging category so that the user can actually see what is
  happening.
- Scale large images.
- Use qreal instead of float.
- Minor polishing: set window title, position file dialog at
  pictures location.

Task-number: QTBUG-37759
Task-number: QTBUG-37203

Change-Id: Ibaf54a13034b150386a8aee476f83a9eba298298
Reviewed-by: Indrajit Tapadar <indrajit.tapadar@digia.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Friedemann Kleint 2014-03-27 09:57:59 +01:00 committed by The Qt Project
parent 4cb0e96505
commit c0701f3789
5 changed files with 138 additions and 34 deletions

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -43,6 +43,8 @@
#include <QtWidgets>
Q_LOGGING_CATEGORY(lcExample, "qt.examples.imagegestures")
//! [constructor]
ImageWidget::ImageWidget(QWidget *parent)
: QWidget(parent),
@ -55,15 +57,17 @@ ImageWidget::ImageWidget(QWidget *parent)
{
setMinimumSize(QSize(100,100));
//! [enable gestures]
grabGesture(Qt::PanGesture);
grabGesture(Qt::PinchGesture);
grabGesture(Qt::SwipeGesture);
//! [enable gestures]
}
//! [constructor]
void ImageWidget::grabGestures(const QList<Qt::GestureType> &gestures)
{
//! [enable gestures]
foreach (Qt::GestureType gesture, gestures)
grabGesture(gesture);
//! [enable gestures]
}
//! [event handler]
bool ImageWidget::event(QEvent *event)
{
@ -77,10 +81,10 @@ void ImageWidget::paintEvent(QPaintEvent*)
{
QPainter p(this);
float iw = currentImage.width();
float ih = currentImage.height();
float wh = height();
float ww = width();
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);
@ -98,11 +102,13 @@ void ImageWidget::mouseDoubleClickEvent(QMouseEvent *)
verticalOffset = 0;
horizontalOffset = 0;
update();
qCDebug(lcExample) << "reset on mouse double click";
}
//! [gesture event handler]
bool ImageWidget::gestureEvent(QGestureEvent *event)
{
qCDebug(lcExample) << "gestureEvent():" << event->gestures().size();
if (QGesture *swipe = event->gesture(Qt::SwipeGesture))
swipeTriggered(static_cast<QSwipeGesture *>(swipe));
else if (QGesture *pan = event->gesture(Qt::PanGesture))
@ -126,6 +132,7 @@ void ImageWidget::panTriggered(QPanGesture *gesture)
}
#endif
QPointF delta = gesture->delta();
qCDebug(lcExample) << "panTriggered():" << delta;
horizontalOffset += delta.x();
verticalOffset += delta.y();
update();
@ -135,13 +142,16 @@ void ImageWidget::pinchTriggered(QPinchGesture *gesture)
{
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::RotationAngleChanged) {
qreal value = gesture->property("rotationAngle").toReal();
qreal lastValue = gesture->property("lastRotationAngle").toReal();
rotationAngle += value - lastValue;
const qreal value = gesture->property("rotationAngle").toReal();
const qreal lastValue = gesture->property("lastRotationAngle").toReal();
const qreal rotationAngleDelta = value - lastValue;
rotationAngle += rotationAngleDelta;
qCDebug(lcExample) << "pinchTriggered(): rotation by" << rotationAngleDelta << rotationAngle;
}
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
qreal value = gesture->property("scaleFactor").toReal();
currentStepScaleFactor = value;
qCDebug(lcExample) << "pinchTriggered(): " << currentStepScaleFactor;
}
if (gesture->state() == Qt::GestureFinished) {
scaleFactor *= currentStepScaleFactor;
@ -155,10 +165,13 @@ void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
if (gesture->state() == Qt::GestureFinished) {
if (gesture->horizontalDirection() == QSwipeGesture::Left
|| gesture->verticalDirection() == QSwipeGesture::Up)
|| gesture->verticalDirection() == QSwipeGesture::Up) {
qCDebug(lcExample) << "swipeTriggered(): swipe to previous";
goPrevImage();
else
} else {
qCDebug(lcExample) << "swipeTriggered(): swipe to next";
goNextImage();
}
update();
}
}
@ -184,17 +197,22 @@ void ImageWidget::openDirectory(const QString &path)
QImage ImageWidget::loadImage(const QString &fileName)
{
qDebug() << position << files << fileName;
QImageReader reader(fileName);
qCDebug(lcExample) << "loading" << QDir::toNativeSeparators(fileName) << position << '/' << files.size();
if (!reader.canRead()) {
qDebug() << fileName << ": can't load image";
qCWarning(lcExample) << QDir::toNativeSeparators(fileName) << ": can't load image";
return QImage();
}
QImage image;
if (!reader.read(&image)) {
qDebug() << fileName << ": corrupted 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;
}
@ -238,7 +256,7 @@ void ImageWidget::goToImage(int index)
return;
if (index < 0 || index >= files.size()) {
qDebug() << "goToImage: invalid index: " << index;
qCWarning(lcExample) << "goToImage: invalid index: " << index;
return;
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -52,6 +52,8 @@ class QPinchGesture;
class QSwipeGesture;
QT_END_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcExample)
//! [class definition begin]
class ImageWidget : public QWidget
{
@ -60,6 +62,7 @@ class ImageWidget : public QWidget
public:
ImageWidget(QWidget *parent = 0);
void openDirectory(const QString &path);
void grabGestures(const QList<Qt::GestureType> &gestures);
protected:
bool event(QEvent *event);
@ -88,11 +91,11 @@ private:
QImage prevImage, nextImage;
QImage currentImage;
float horizontalOffset;
float verticalOffset;
float rotationAngle;
float scaleFactor;
float currentStepScaleFactor;
qreal horizontalOffset;
qreal verticalOffset;
qreal rotationAngle;
qreal scaleFactor;
qreal currentStepScaleFactor;
//! [class definition end]
};
//! [class definition end]

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -42,17 +42,86 @@
#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);
if (!commandLineParser.parse(QCoreApplication::arguments())) {
showHelp(commandLineParser, commandLineParser.errorText());
return -1;
}
if (commandLineParser.isSet(helpOption)) {
showHelp(commandLineParser);
return 0;
}
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 (QApplication::arguments().size() > 1)
w.openDirectory(QApplication::arguments().at(1));
else
w.openDirectory(QFileDialog::getExistingDirectory(0, "Select image folder"));
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

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -41,15 +41,28 @@
#include "imagewidget.h"
#include "mainwidget.h"
#include <QScreen>
#include <QGuiApplication>
#include <QDir>
MainWidget::MainWidget(QWidget *parent)
: QMainWindow(parent)
, imageWidget(new ImageWidget(this))
{
resize(400, 300);
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

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@ -51,6 +51,7 @@ class MainWidget : public QMainWindow
public:
MainWidget(QWidget *parent = 0);
void grabGestures(const QList<Qt::GestureType> &gestures);
public slots:
void openDirectory(const QString &path);