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

View File

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

View File

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

View File

@ -51,24 +51,16 @@
#include <QtWidgets> #include <QtWidgets>
#include <QtConcurrent> #include <QtConcurrent>
#include <functional>
using namespace QtConcurrent; 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) int main(int argc, char **argv)
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
const int iterations = 20;
// Prepare the vector. // Prepare the vector.
QVector<int> vector; QVector<int> vector;
for (int i = 0; i < iterations; ++i) 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. // Create a QFutureWatcher and connect signals and slots.
QFutureWatcher<void> futureWatcher; QFutureWatcher<void> futureWatcher;
QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); QObject::connect(&futureWatcher, &QFutureWatcher<void>::finished, &dialog, &QProgressDialog::reset);
QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); QObject::connect(&dialog, &QProgressDialog::canceled, &futureWatcher, &QFutureWatcher<void>::cancel);
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); QObject::connect(&futureWatcher, &QFutureWatcher<void>::progressRangeChanged, &dialog, &QProgressDialog::setRange);
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); 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. // Start the computation.
futureWatcher.setFuture(QtConcurrent::map(vector, spin)); futureWatcher.setFuture(QtConcurrent::map(vector, spin));

View File

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