1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 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<Element>::finished,
this, [this] { finish(); });
connect(&watcher, &QFutureWatcher<Element>::progressRangeChanged,
ui->progressBar, &QProgressBar::setRange);
connect(&watcher, &QFutureWatcher<Element>::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<QtConcurrent::ReduceOptions>();
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;
}
|