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:
parent
d4b3ce9a28
commit
ab9f4d5db6
@ -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));
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user