From e453de0c0b8787ae672f77f9922e9960bc9fe0b7 Mon Sep 17 00:00:00 2001 From: Dennis Oberst Date: Thu, 16 Feb 2023 18:14:38 +0100 Subject: [PATCH] Example: rename progressdialog to primecounter and modernize it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous example finished way too quickly and provided no real value in regards to API understanding. Previously, QtConcurrent::map was used, which was also used in other examples. We are now using QtConcurrent::filterReduce to demonstrate other functionality. Task-number: QTBUG-111165 Change-Id: Ibd6eb119d0711cddfe8b211d460e9d67d6ce95c3 Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Ivan Solovev (cherry picked from commit 8352756d27e5657390b6e87f45e0c0bae6b7784e) Reviewed-by: Qt Cherry-pick Bot --- doc/global/manifest-meta.qdocconf | 1 - examples/qtconcurrent/CMakeLists.txt | 2 +- .../CMakeLists.txt | 19 +- .../primecounter/doc/images/primecounter.png | Bin 0 -> 9732 bytes .../doc/src/qtconcurrent-primecounter.qdoc | 88 +++++++++ examples/qtconcurrent/primecounter/main.cpp | 18 ++ .../primecounter/primecounter.cpp | 139 ++++++++++++++ .../qtconcurrent/primecounter/primecounter.h | 49 +++++ .../primecounter/primecounter.pro | 9 + .../qtconcurrent/primecounter/primecounter.ui | 177 ++++++++++++++++++ .../images/qtconcurrent-progressdialog.png | Bin 4608 -> 0 bytes .../doc/src/qtconcurrent-progressdialog.qdoc | 14 -- examples/qtconcurrent/progressdialog/main.cpp | 53 ------ .../progressdialog/progressdialog.pro | 7 - examples/qtconcurrent/qtconcurrent.pro | 4 +- 15 files changed, 494 insertions(+), 86 deletions(-) rename examples/qtconcurrent/{progressdialog => primecounter}/CMakeLists.txt (57%) create mode 100644 examples/qtconcurrent/primecounter/doc/images/primecounter.png create mode 100644 examples/qtconcurrent/primecounter/doc/src/qtconcurrent-primecounter.qdoc create mode 100644 examples/qtconcurrent/primecounter/main.cpp create mode 100644 examples/qtconcurrent/primecounter/primecounter.cpp create mode 100644 examples/qtconcurrent/primecounter/primecounter.h create mode 100644 examples/qtconcurrent/primecounter/primecounter.pro create mode 100644 examples/qtconcurrent/primecounter/primecounter.ui delete mode 100644 examples/qtconcurrent/progressdialog/doc/images/qtconcurrent-progressdialog.png delete mode 100644 examples/qtconcurrent/progressdialog/doc/src/qtconcurrent-progressdialog.qdoc delete mode 100644 examples/qtconcurrent/progressdialog/main.cpp delete mode 100644 examples/qtconcurrent/progressdialog/progressdialog.pro diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index 5f269c13856..2fd73a48287 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -40,7 +40,6 @@ manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \ "QtBluetooth/Bluetooth Scanner Example" \ "QtBluetooth/QML Bluetooth Scanner Example" \ "QtCharts/*" \ - "QtConcurrent/QtConcurrent Progress Dialog Example" \ "QtDataVisualization/Audiolevels Example" \ "QtDataVisualization/Qt Quick 2 Scatter Example" \ "QtDataVisualization/Qt Quick 2 Surface Multiseries Example" \ diff --git a/examples/qtconcurrent/CMakeLists.txt b/examples/qtconcurrent/CMakeLists.txt index 77244436e45..6a5ef9e8ce9 100644 --- a/examples/qtconcurrent/CMakeLists.txt +++ b/examples/qtconcurrent/CMakeLists.txt @@ -6,6 +6,6 @@ if(NOT TARGET Qt6::Concurrent) endif() if(TARGET Qt6::Widgets) qt_internal_add_example(imagescaling) - qt_internal_add_example(progressdialog) + qt_internal_add_example(primecounter) qt_internal_add_example(wordcount) endif() diff --git a/examples/qtconcurrent/progressdialog/CMakeLists.txt b/examples/qtconcurrent/primecounter/CMakeLists.txt similarity index 57% rename from examples/qtconcurrent/progressdialog/CMakeLists.txt rename to examples/qtconcurrent/primecounter/CMakeLists.txt index 5609572d95b..de098df3242 100644 --- a/examples/qtconcurrent/progressdialog/CMakeLists.txt +++ b/examples/qtconcurrent/primecounter/CMakeLists.txt @@ -1,36 +1,39 @@ -# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.16) -project(progressdialog LANGUAGES CXX) +project(primecounter LANGUAGES CXX) if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") endif() -set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qtconcurrent/progressdialog") +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qtconcurrent/primecounter") find_package(Qt6 REQUIRED COMPONENTS Concurrent Core Gui Widgets) qt_standard_project_setup() -qt_add_executable(progressdialog +qt_add_executable(primecounter main.cpp + primecounter.ui + primecounter.cpp + primecounter.h ) -set_target_properties(progressdialog PROPERTIES - WIN32_EXECUTABLE FALSE +set_target_properties(primecounter PROPERTIES + WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) -target_link_libraries(progressdialog PRIVATE +target_link_libraries(primecounter PRIVATE Qt6::Concurrent Qt6::Core Qt6::Gui Qt6::Widgets ) -install(TARGETS progressdialog +install(TARGETS primecounter RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" diff --git a/examples/qtconcurrent/primecounter/doc/images/primecounter.png b/examples/qtconcurrent/primecounter/doc/images/primecounter.png new file mode 100644 index 0000000000000000000000000000000000000000..d611a507b55cebfaaf9be84ff2bfd01efe41b679 GIT binary patch literal 9732 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 +#include "primecounter.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + app.setOrganizationName("QtProject"); + app.setApplicationName(QApplication::translate("main", "Prime Counter")); + + PrimeCounter dialog; + dialog.setWindowTitle(QApplication::translate("main", "Prime Counter")); + dialog.show(); + + return app.exec(); +} diff --git a/examples/qtconcurrent/primecounter/primecounter.cpp b/examples/qtconcurrent/primecounter/primecounter.cpp new file mode 100644 index 00000000000..01bde5d87f3 --- /dev/null +++ b/examples/qtconcurrent/primecounter/primecounter.cpp @@ -0,0 +1,139 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "primecounter.h" +#include "ui_primecounter.h" + +PrimeCounter::PrimeCounter(QWidget *parent) + : QDialog(parent), stepSize(100000), ui(setupUi()) +{ + // Control the concurrent operation with the QFutureWatcher + //! [1] + connect(ui->pushButton, &QPushButton::clicked, + this, [this] { start(); }); + connect(&watcher, &QFutureWatcher::finished, + this, [this] { finish(); }); + connect(&watcher, &QFutureWatcher::progressRangeChanged, + ui->progressBar, &QProgressBar::setRange); + connect(&watcher, &QFutureWatcher::progressValueChanged, + ui->progressBar, &QProgressBar::setValue); + //! [1] +} + +PrimeCounter::~PrimeCounter() +{ + watcher.cancel(); + delete ui; +} + +//! [3] +bool PrimeCounter::filterFunction(const Element &element) +{ + // Filter for primes + if (element <= 1) + return false; + for (Element i = 2; i*i <= element; ++i) { + if (element % i == 0) + return false; + } + return true; +} +//! [3] + +//! [4] +void PrimeCounter::reduceFunction(Element &out, const Element &value) +{ + // Count the amount of primes. + Q_UNUSED(value); + ++out; +} +//! [4] + +//! [2] +void PrimeCounter::start() +{ + if (ui->pushButton->isChecked()) { + ui->comboBox->setEnabled(false); + ui->pushButton->setText(tr("Cancel")); + ui->labelResult->setText(tr("Calculating ...")); + ui->labelFilter->setText(tr("Selected Reduce Option: %1").arg(ui->comboBox->currentText())); + fillElementList(ui->horizontalSlider->value() * stepSize); + + timer.start(); + watcher.setFuture( + QtConcurrent::filteredReduced( + &pool, + elementList, + filterFunction, + reduceFunction, + currentReduceOpt | QtConcurrent::SequentialReduce)); +//! [2] + } else { + watcher.cancel(); + ui->progressBar->setValue(0); + ui->comboBox->setEnabled(true); + ui->labelResult->setText(tr("")); + ui->pushButton->setText(tr("Start")); + ui->labelFilter->setText(tr("Operation Canceled")); + } +} + +void PrimeCounter::finish() +{ + // The finished signal from the QFutureWatcher is also emitted when cancelling. + if (watcher.isCanceled()) + return; + + auto elapsedTime = timer.elapsed(); + ui->progressBar->setValue(0); + ui->comboBox->setEnabled(true); + ui->pushButton->setChecked(false); + ui->pushButton->setText(tr("Start")); + ui->labelFilter->setText( + tr("Filter '%1' took %2 ms to calculate").arg(ui->comboBox->currentText()) + .arg(elapsedTime)); + ui->labelResult->setText( + tr("Found %1 primes in the range of elements").arg(watcher.result())); +} + +void PrimeCounter::fillElementList(unsigned int count) +{ + // Fill elementList with values from [1, count] when starting the calculations. + auto prevSize = elementList.size(); + if (prevSize == count) + return; // Nothing to do here. + + auto startVal = elementList.empty() ? 1 : elementList.back() + 1; + elementList.resize(count); + if (elementList.begin() + prevSize < elementList.end()) + std::iota(elementList.begin() + prevSize, elementList.end(), startVal); +} + +Ui::PrimeCounter* PrimeCounter::setupUi() +{ + Ui::PrimeCounter *setupUI = new Ui::PrimeCounter; + setupUI->setupUi(this); + setModal(true); + + // Set up the slider + connect(setupUI->horizontalSlider, &QSlider::valueChanged, + this, [setupUI, this] (const int &pos) { + setupUI->labelResult->setText(""); + setupUI->labelSize->setText(tr("Elements in list: %1").arg(pos * stepSize)); + }); + setupUI->horizontalSlider->setValue(30); + + // Set up the combo box + setupUI->comboBox->insertItem(0, tr("Unordered Reduce"), QtConcurrent::UnorderedReduce); + setupUI->comboBox->insertItem(1, tr("Ordered Reduce"), QtConcurrent::OrderedReduce); + + auto comboBoxChange = [this, setupUI](int pos) { + currentReduceOpt = setupUI->comboBox->itemData(pos).value(); + setupUI->labelFilter->setText(tr("Selected Reduce Option: %1") + .arg(setupUI->comboBox->currentText())); + }; + comboBoxChange(setupUI->comboBox->currentIndex()); + connect(setupUI->comboBox, &QComboBox::currentIndexChanged, this, comboBoxChange); + + return setupUI; +} diff --git a/examples/qtconcurrent/primecounter/primecounter.h b/examples/qtconcurrent/primecounter/primecounter.h new file mode 100644 index 00000000000..5b6d442cc8c --- /dev/null +++ b/examples/qtconcurrent/primecounter/primecounter.h @@ -0,0 +1,49 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef PRIMECOUNTER_H +#define PRIMECOUNTER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QProgressBar; +namespace Ui { +class PrimeCounter; +} + +QT_END_NAMESPACE + +class PrimeCounter : public QDialog +{ + Q_OBJECT + using Element = unsigned long long; +public: + explicit PrimeCounter(QWidget* parent = nullptr); + ~PrimeCounter() override; + +private: + static bool filterFunction(const Element &element); + static void reduceFunction(Element &out, const Element &value); + void fillElementList(unsigned int count); + Ui::PrimeCounter* setupUi(); + +private slots: + void start(); + void finish(); + +private: + QList elementList; + QFutureWatcher watcher; + QtConcurrent::ReduceOptions currentReduceOpt; + QElapsedTimer timer; + QThreadPool pool; + unsigned int stepSize; + Ui::PrimeCounter *ui; +}; + +#endif //PRIMECOUNTER_H diff --git a/examples/qtconcurrent/primecounter/primecounter.pro b/examples/qtconcurrent/primecounter/primecounter.pro new file mode 100644 index 00000000000..bb5a740688a --- /dev/null +++ b/examples/qtconcurrent/primecounter/primecounter.pro @@ -0,0 +1,9 @@ +QT += concurrent widgets + +SOURCES += main.cpp primecounter.cpp +HEADERS += primecounter.h + +target.path = $$[QT_INSTALL_EXAMPLES]/qtconcurrent/primecounter +INSTALLS += target + +FORMS += primecounter.ui diff --git a/examples/qtconcurrent/primecounter/primecounter.ui b/examples/qtconcurrent/primecounter/primecounter.ui new file mode 100644 index 00000000000..625462e05e1 --- /dev/null +++ b/examples/qtconcurrent/primecounter/primecounter.ui @@ -0,0 +1,177 @@ + + + PrimeCounter + + + Qt::WindowModal + + + + 0 + 0 + 454 + 320 + + + + Dialog + + + false + + + + + + + 20 + + + 20 + + + 20 + + + 20 + + + + + + 11 + false + + + + Select a reducing option and measure the speed + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + + 20 + 30 + + + + + + + + 10 + + + 10 + + + + + + + + + + 10 + + + 10 + + + + + Start + + + true + + + + + + + 0 + + + + + + + + + Filter Label + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + 1 + + + 100 + + + Qt::Horizontal + + + + + + + size + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 5 + + + 10 + + + + + + + + + Result Label + + + + + + + + diff --git a/examples/qtconcurrent/progressdialog/doc/images/qtconcurrent-progressdialog.png b/examples/qtconcurrent/progressdialog/doc/images/qtconcurrent-progressdialog.png deleted file mode 100644 index 2e8b7735ad3e8d081f8a95919c6eaf68736372f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4608 zcmaJ_WmuF=+oo#?0bNR3*rmH0DOX}aN=oSlN$HT1Mp;?ul9Dc2Bvx=0SmKfHkdlt2 z`-A6szW2v>yvO(BzV2g=nJZ?_Yv!D5VxijVWF+(?SXfwOPc&5YZvQj4UnCLEt@K_Q z(!|1|?0TZ2r0+MiolR)`%!r}uBIx+c1Q$G&->shz7l)hjyEH=D#CfxH?6c2!Z2ib! zbzHemEl$$s7o%TT0*Tm!+2VvbaOfUc#wco7QMvH(R|J8Y@40Je@Z&`9wcY%=G24}s z+HL+bbJEou-))*mGO1~fN3c0do9J$-QYGm<0OBVk9V?`aq=mcZhpz4v^X?-_ZuQG#OGLlCN`ljuxA>cb+d5exrqFQD&qg&v z#)a|0*0HqC^vvXA@abI1wx&FsqKj}INQ>Vo|9%T(rc_@3VTC}Gf=7V65^V071?CxB0*hHx1b=;eKODk|0A z4U$ZuLgW51;TexwZwOf2<13|(P4@%rY@VDn)~G&B%%s1Y%dyUHh|VNk&8j!fDpz?s zvye}fCpDdGfpQS>=VS`P&E8WKW$m3dDV@SIxlgM3$H0^l_dR8nf+A1VKxX~CtOKve zq2YGG<#C@+-($|cjJB(f|ILEQCkr_h`;E~HLF>YY>NX7p^%UIDkPuPj^<<<%<278R z?=h$^qkakT|0{b9W0OMuQ67+EDmzRtFOkS;37-t^=f7|~fMs?&P(N6F3jKSDe}ao)KEEW6L{k9g_H?TF#N@N{me$6 z`3~9r*vwY%&6?PH6WRw(IuG0N^^vLtqkzVyy|S2xDh(ruvReEHV5BTv<>6MFebcoB z-7cN;$%NJ=9$jU_DG}XhS4_l_ZO~#d?{st#sk?ruoCo7vr#(~5-qB$3F;G9xY?-m} zFze>B?#hb9qwxInRZaWMHEO->*6P0dBjoA+%)rw!RN@A8&^Ymq{=ex2x!mmbzZeL# zD5jG5JYPJXy`b%RL0xikYY&A?x;*z=yS$=lzuD%bEX*hk$+UR=MyBUBdFSo`m*QY@ zuW)2j6Ej7um`KN34DwutMiGmHC=V|j3vy3!QV!L!BR_H_T|K>B?wCBzX`ohe^MPJDZxzo)yq6h66j7Nh5&oTqJyqLFBw1q7uRL zXAe#FK;=EeW-E5XT@#4p#Ocr9vNDQ$%neglnnniuP^BkWUA79j7gj??WkF=Web@~5 zlIVPykA-(eL;E_d9StVDd9BQ+P6zYae>$XHzgnwc7qxVbLTjTk56f&W!`BNKbEj365V~fCUl?X>Z?;{-icO%X5YiK z(?29NsBSzdn0pohSi1SJrn<1G07UUId?~uRh23E%?&p#KoFzCh`@nGwx9u?(^>U7? z$co#UCYM6V$)oD)LPhY05t1UG(Gee;Ua64RepJM}NxSxG%SRIBwFkcl>W*5!^>N33 z;%0x zX1v5GKj=Aa@|?#99x9=bY**XRFixj72I>5*Pr>V1HzW3tBSuQuXrIMJM2)^-rM})1 zxn-x{0T3m<{z|RK74juE`aK6L5?!rjsiPxNHt-kC{WK2rG1V!N2jwFEl#O4V&7Lu7 z8<;&SP_EZ)PgvC+o3T)0@<|yJ&5m~<-0Iz7QeyGx9#qd7)-s$QJyx;)taa5ld*50FtYhLm{Yt;qukiD)yldS!G#r>v`LP~dbiF7VZvM=IiqljFVUm9Ywf_7z`=uO5_&C1y zJRivt&xcG*hYC+7Z!(j+oK(JliqHdur>(TX_mV?@(~vJtY40WvRnC|=K5(@&*vXIu z+_Z)B$CIPrT*7%}w~i5}ey&p0jficLpDn?x`Gd>)ZeO9G1tk&*1C5dq=M#TVz zj3zDNs+AggT7Yxknr(?DCljs_a)|Tnw{q^m*`Iu^n#Gb5=C4GJDu2~puwkt{a#n_J z$Vb0999_soUUi~YQ|&vxWXj63n}ikNz_FhwOB=J%c$V9 z{j%J@MEDE?;6ndNix{_}Il(wk~jXUV9bIoz`--OJ}WO*s5(8b>?StM)$(&8m)~#$WD7s%w-0ZAs$&)KdYA4%5H7WNx*#I_-lMNtQpv! zUC}=!k52D&$)FS?XAXR|yd>(R?i(W;y)FwL*v%<$QI#_NNbPwE5*mWGzs?+k&;L zK$*pgiQnP7r3)YHm)ZlBKNt~j@DS{)5z5Whfdr5Sg}Wt@?llbN*4gKcbv7D7;#F_GN>AT zIrW|dkp=PCG*64=kupj$Uh;guCEcgB|X^fOEFE8gRv2-eb^X7-qzT>bpcqypV6x%x0V}p;I)wpwaIo&0cy4)Skn$pJ!MS}XV4W*OUYFti#VjPY z53V1L$LWF%#zr6i3{c;W;|;}Ne!Q4z(G_~4zf(w~Q_iMs9*Dm(oPqjyn)g<6xflLM zJeO3ezbbSRs;*-{D%M(IALD+KbU>6)yezlyBg!=*ohomO2pnOJPnMWWI|qB@F9tF0 zD1=k&M(q%}L}PxpG2_0fol|Q1B*4JDx_v^94w*RB%c$+T*cbpbTZN#pA;MYh*l6-_ zVepeniZ>V=MJjO_psbTiY0(auLo_DW-X~Nc@H{0{L5Os}X-;N2!K#?IwI9Z1ht8hs za8&L%67euy$heInZ{qFMlg{X$G@*6F>{f1{YHk7s->xG2Zoqk;fP-bRv8=TtE*+_% z^b9H^EEKtt-dc2j-B$>?Hb!Y2owRvInwVw+H|XwpByv@SS_oL_abXinHOs4}kX4^#k999T62L(6uMns$Jb%3paD?LC{FkuXd({74r|x!5ba|nA^1w!t@)8c1>|=LKsN8yp8#NrumWB##R*6V@ zagcXG*9KQB#08U4LBcf*4fxcUY^>*8)4G2Y$%YMu}D&XGfC zZp#yqrcYFNO&-5S2VbS$9ZMJ9tVNQrp_lm;A7Dl#UmNIjtAI<7XH!YE ztmhyn2#J7plgBw%eC6+9Obg6*U~HEzHQ^%B#P3m*X#xqLld>b`b$|WEFVsYzYp`H; zgn^xXwuwaIWxG&MX>w8TR1Ho}Yf7q@?@|LR^GDkBLx!^-9UnW|UM$3NIls`dZdU zspbLk!oxFe?j#JO%P3b`J9(c_V{N*okAWch4Pbp80+v}bI%hYqKhY}eraRVb;2Qx{ z9faKHGe!`s988Vq*y$20I@UnP-VP2^i?-x(u+CHDI;?vN>8Oio58#6~>GJVQLq66| zI_xG0`&;gCfO@%%Fg(qNn=huxZ}^LhIpRW=GFh$3=lEBEMz0Vn6)mvZFE7-FAMkx_ zx%NQ5e@RhWiv=SfwKYhjm6LOf04xC~lB9xK^oL7|=xD^Xm@b*hKtnBZ0WH@`QSu4&#yG= z@?l$)O7?;~S6^%sp18w%n{6v*c$WGe@VHz`vj_A;4;(G>)6F>JKLDxUWxPOJiCBv# zJ(Rt%(FekR@aNCAg{+(D@jq?E@8q|6g$0R-dM{uD{7^87&qv%M30ggk>+!t`pgVe$ zo{@a+9dV;YUk>ZxCbDpLpDFA@&I>WNowiuo@x#3!=~5)0Jnx4ieAKS_at%@mj>XvM zGEF3_$p^UJ8G-vG+Z^wZfd1v{|MblgqT4`! w6_DM&hp2(k`6{8D53g_uUQ@EO+z -#include - -#include - -using namespace QtConcurrent; - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - - const int iterations = 20; - - // Prepare the list. - QList list; - for (int i = 0; i < iterations; ++i) - list.append(i); - - // Create a progress dialog. - QProgressDialog dialog; - dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount())); - - // Create a QFutureWatcher and connect signals and slots. - QFutureWatcher futureWatcher; - QObject::connect(&futureWatcher, &QFutureWatcher::finished, &dialog, &QProgressDialog::reset); - QObject::connect(&dialog, &QProgressDialog::canceled, &futureWatcher, &QFutureWatcher::cancel); - QObject::connect(&futureWatcher, &QFutureWatcher::progressRangeChanged, &dialog, &QProgressDialog::setRange); - QObject::connect(&futureWatcher, &QFutureWatcher::progressValueChanged, &dialog, &QProgressDialog::setValue); - - // Our function to compute - std::function 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(list, spin)); - - // Display the dialog and start the event loop. - dialog.exec(); - - futureWatcher.waitForFinished(); - - // Query the future to check if was canceled. - qDebug() << "Canceled?" << futureWatcher.future().isCanceled(); -} diff --git a/examples/qtconcurrent/progressdialog/progressdialog.pro b/examples/qtconcurrent/progressdialog/progressdialog.pro deleted file mode 100644 index 8a5b3aabb77..00000000000 --- a/examples/qtconcurrent/progressdialog/progressdialog.pro +++ /dev/null @@ -1,7 +0,0 @@ -QT += concurrent widgets -CONFIG += console - -SOURCES += main.cpp - -target.path = $$[QT_INSTALL_EXAMPLES]/qtconcurrent/progressdialog -INSTALLS += target diff --git a/examples/qtconcurrent/qtconcurrent.pro b/examples/qtconcurrent/qtconcurrent.pro index 1db6013c4a6..ea7618fa004 100644 --- a/examples/qtconcurrent/qtconcurrent.pro +++ b/examples/qtconcurrent/qtconcurrent.pro @@ -2,12 +2,12 @@ requires(qtHaveModule(concurrent)) TEMPLATE = subdirs SUBDIRS = imagescaling \ - progressdialog \ + primecounter \ wordcount !qtHaveModule(widgets) { SUBDIRS -= \ imagescaling \ - progressdialog \ + primecounter \ wordcount }