Revamp QtConcurrent examples to C++11

I updated signals and slots and for each loops to the new syntax and
replaced most free functions with std::function.

Task-number: QTBUG-60641
Change-Id: I7693f81f71c7f53fcbe83189a0de2fb76ddf99a8
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Michael Winkelmann 2017-08-03 15:43:26 +02:00 committed by Topi Reiniö
parent d4b3ce9a28
commit ab9f4d5db6
5 changed files with 57 additions and 48 deletions

View File

@ -48,15 +48,10 @@
**
****************************************************************************/
#include "imagescaling.h"
#include <qmath.h>
const int imageSize = 100;
QImage scale(const QString &imageFileName)
{
QImage image(imageFileName);
return image.scaled(QSize(imageSize, imageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
#include <functional>
Images::Images(QWidget *parent)
: QWidget(parent)
@ -65,19 +60,19 @@ Images::Images(QWidget *parent)
resize(800, 600);
imageScaling = new QFutureWatcher<QImage>(this);
connect(imageScaling, SIGNAL(resultReadyAt(int)), SLOT(showImage(int)));
connect(imageScaling, SIGNAL(finished()), SLOT(finished()));
connect(imageScaling, &QFutureWatcher<QImage>::resultReadyAt, this, &Images::showImage);
connect(imageScaling, &QFutureWatcher<QImage>::finished, this, &Images::finished);
openButton = new QPushButton(tr("Open Images"));
connect(openButton, SIGNAL(clicked()), SLOT(open()));
connect(openButton, &QPushButton::clicked, this, &Images::open);
cancelButton = new QPushButton(tr("Cancel"));
cancelButton->setEnabled(false);
connect(cancelButton, SIGNAL(clicked()), imageScaling, SLOT(cancel()));
connect(cancelButton, &QPushButton::clicked, imageScaling, &QFutureWatcher<QImage>::cancel);
pauseButton = new QPushButton(tr("Pause/Resume"));
pauseButton->setEnabled(false);
connect(pauseButton, SIGNAL(clicked()), imageScaling, SLOT(togglePaused()));
connect(pauseButton, &QPushButton::clicked, imageScaling, &QFutureWatcher<QImage>::togglePaused);
QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addWidget(openButton);
@ -113,9 +108,11 @@ void Images::open()
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),
"*.jpg *.png");
if (files.count() == 0)
if (files.isEmpty())
return;
const int imageSize = 100;
// Do a simple layout.
qDeleteAll(labels);
labels.clear();
@ -130,6 +127,11 @@ void Images::open()
}
}
std::function<QImage(const QString&)> scale = [imageSize](const QString &imageFileName) {
QImage image(imageFileName);
return image.scaled(QSize(imageSize, imageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
};
// Use mapped to run the thread safe scale function on the files.
imageScaling->setFuture(QtConcurrent::mapped(files, scale));

View File

@ -57,9 +57,9 @@ class Images : public QWidget
{
Q_OBJECT
public:
Images(QWidget *parent = 0);
Images(QWidget *parent = nullptr);
~Images();
public Q_SLOTS:
public slots:
void open();
void showImage(int num);
void finished();

View File

@ -55,11 +55,7 @@
#include <QGuiApplication>
#include <qtconcurrentmap.h>
QImage scale(const QImage &image)
{
qDebug() << "Scaling image in thread" << QThread::currentThread();
return image.scaled(QSize(100, 100), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
#include <functional>
int main(int argc, char *argv[])
{
@ -72,6 +68,12 @@ int main(int argc, char *argv[])
for (int i = 0; i < imageCount; ++i)
images.append(QImage(1600, 1200, QImage::Format_ARGB32_Premultiplied));
std::function<QImage(const QImage&)> scale = [](const QImage &image) -> QImage
{
qDebug() << "Scaling image in thread" << QThread::currentThread();
return image.scaled(QSize(100, 100), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
};
// Use QtConcurrentBlocking::mapped to apply the scale function to all the
// images in the list.
QList<QImage> thumbnails = QtConcurrent::blockingMapped(images, scale);

View File

@ -51,24 +51,16 @@
#include <QtWidgets>
#include <QtConcurrent>
#include <functional>
using namespace QtConcurrent;
const int iterations = 20;
void spin(int &iteration)
{
const int work = 1000 * 1000 * 40;
volatile int v = 0;
for (int j = 0; j < work; ++j)
++v;
qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId();
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
const int iterations = 20;
// Prepare the vector.
QVector<int> vector;
for (int i = 0; i < iterations; ++i)
@ -80,10 +72,20 @@ int main(int argc, char **argv)
// Create a QFutureWatcher and connect signals and slots.
QFutureWatcher<void> futureWatcher;
QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int)));
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
QObject::connect(&futureWatcher, &QFutureWatcher<void>::finished, &dialog, &QProgressDialog::reset);
QObject::connect(&dialog, &QProgressDialog::canceled, &futureWatcher, &QFutureWatcher<void>::cancel);
QObject::connect(&futureWatcher, &QFutureWatcher<void>::progressRangeChanged, &dialog, &QProgressDialog::setRange);
QObject::connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog, &QProgressDialog::setValue);
// Our function to compute
std::function<void(int&)> spin = [](int &iteration) {
const int work = 1000 * 1000 * 40;
volatile int v = 0;
for (int j = 0; j < work; ++j)
++v;
qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId();
};
// Start the computation.
futureWatcher.setFuture(QtConcurrent::map(vector, spin));

View File

@ -65,15 +65,17 @@ using namespace QtConcurrent;
/*
Utility function that recursivily searches for files.
*/
QStringList findFiles(const QString &startDir, QStringList filters)
QStringList findFiles(const QString &startDir, const QStringList &filters)
{
QStringList names;
QDir dir(startDir);
foreach (QString file, dir.entryList(filters, QDir::Files))
const auto files = dir.entryList(filters, QDir::Files);
for (const QString &file : files)
names += startDir + '/' + file;
foreach (QString subdir, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot))
const auto subdirs = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
for (const QString &subdir : subdirs)
names += findFiles(startDir + '/' + subdir, filters);
return names;
}
@ -83,17 +85,18 @@ typedef QMap<QString, int> WordCount;
/*
Single threaded word counter function.
*/
WordCount singleThreadedWordCount(QStringList files)
WordCount singleThreadedWordCount(const QStringList &files)
{
WordCount wordCount;
foreach (QString file, files) {
for (const QString &file : files) {
QFile f(file);
f.open(QIODevice::ReadOnly);
QTextStream textStream(&f);
while (textStream.atEnd() == false)
foreach (const QString &word, textStream.readLine().split(' '))
while (!textStream.atEnd()) {
const auto words = textStream.readLine().split(' ');
for (const QString &word : words)
wordCount[word] += 1;
}
}
return wordCount;
}
@ -109,9 +112,11 @@ WordCount countWords(const QString &file)
QTextStream textStream(&f);
WordCount wordCount;
while (textStream.atEnd() == false)
foreach (const QString &word, textStream.readLine().split(' '))
while (!textStream.atEnd()) {
const auto words = textStream.readLine().split(' ');
for (const QString &word : words)
wordCount[word] += 1;
}
return wordCount;
}
@ -137,8 +142,6 @@ int main(int argc, char** argv)
qDebug() << "warmup";
{
QTime time;
time.start();
WordCount total = singleThreadedWordCount(files);
}