2 ******************************************************************************
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "qtconcurrent_global.h"
33 #include "runextensions.h"
35 #include <QtCore/QObject>
36 #include <QtCore/QList>
37 #include <QtCore/QEventLoop>
38 #include <QtCore/QFutureWatcher>
39 #include <QtConcurrent/QtConcurrentRun>
40 #include <QtCore/QThreadPool>
46 namespace QtConcurrent
{
47 class QTCONCURRENT_EXPORT MultiTaskBase
: public QObject
, public QRunnable
{
50 virtual void cancelSelf() = 0;
51 virtual void setFinished() = 0;
52 virtual void setProgressRange(int min
, int max
) = 0;
53 virtual void setProgressValue(int value
) = 0;
54 virtual void setProgressText(QString value
) = 0;
57 template <typename Class
, typename R
>
58 class MultiTask
: public MultiTaskBase
{
60 MultiTask(void(Class::*fn
)(QFutureInterface
<R
> &), const QList
<Class
*> &objects
)
64 maxProgress
= 100 * objects
.size();
69 futureInterface
.reportStarted();
70 return futureInterface
.future();
75 QThreadPool::globalInstance()->releaseThread();
77 futureInterface
.setProgressRange(0, maxProgress
);
78 foreach(Class
* object
, objects
) {
79 QFutureWatcher
<R
> *watcher
= new QFutureWatcher
<R
>();
80 watchers
.insert(object
, watcher
);
81 finished
.insert(watcher
, false);
82 connect(watcher
, SIGNAL(finished()), this, SLOT(setFinished()));
83 connect(watcher
, SIGNAL(progressRangeChanged(int, int)), this, SLOT(setProgressRange(int, int)));
84 connect(watcher
, SIGNAL(progressValueChanged(int)), this, SLOT(setProgressValue(int)));
85 connect(watcher
, SIGNAL(progressTextChanged(QString
)), this, SLOT(setProgressText(QString
)));
86 watcher
->setFuture(QtConcurrent::run(fn
, object
));
88 selfWatcher
= new QFutureWatcher
<R
>();
89 connect(selfWatcher
, SIGNAL(canceled()), this, SLOT(cancelSelf()));
90 selfWatcher
->setFuture(futureInterface
.future());
91 loop
= new QEventLoop
;
93 futureInterface
.reportFinished();
94 QThreadPool::globalInstance()->reserveThread();
95 qDeleteAll(watchers
.values());
102 foreach(QFutureWatcher
<R
> *watcher
, watchers
)
103 watcher
->future().cancel();
109 QFutureWatcher
<R
> *watcher
= static_cast<QFutureWatcher
<R
> *>(sender());
110 if (finished
.contains(watcher
)) {
111 finished
[watcher
] = true;
113 bool allFinished
= true;
114 const QList
<bool> finishedValues
= finished
.values();
115 foreach(bool isFinished
, finishedValues
) {
126 void setProgressRange(int min
, int max
)
133 void setProgressValue(int value
)
139 void setProgressText(QString value
)
142 updateProgressText();
145 void updateProgress()
148 const QList
<QFutureWatcher
<R
> *> watchersValues
= watchers
.values();
150 foreach(QFutureWatcher
<R
> *watcher
, watchersValues
) {
151 if (watcher
->progressMinimum() == watcher
->progressMaximum()) {
152 if (watcher
->future().isFinished() && !watcher
->future().isCanceled()) {
156 progressSum
+= 100 * (watcher
->progressValue() - watcher
->progressMinimum()) / (watcher
->progressMaximum() - watcher
->progressMinimum());
159 futureInterface
.setProgressValue(progressSum
);
162 void updateProgressText()
165 const QList
<QFutureWatcher
<R
> *> watchersValues
= watchers
.values();
167 foreach(QFutureWatcher
<R
> *watcher
, watchersValues
) {
168 if (!watcher
->progressText().isEmpty()) {
169 text
+= watcher
->progressText() + "\n";
172 text
= text
.trimmed();
173 futureInterface
.setProgressValueAndText(futureInterface
.progressValue(), text
);
176 QFutureInterface
<R
> futureInterface
;
177 void (Class::*fn
)(QFutureInterface
<R
> &);
178 QList
<Class
*> objects
;
180 QFutureWatcher
<R
> *selfWatcher
;
181 QMap
<Class
*, QFutureWatcher
<R
> *> watchers
;
182 QMap
<QFutureWatcher
<R
> *, bool> finished
;
187 template <typename Class
, typename T
>
188 QFuture
<T
> run(void (Class::*fn
)(QFutureInterface
<T
> &), const QList
<Class
*> &objects
, int priority
= 0)
190 MultiTask
<Class
, T
> *task
= new MultiTask
<Class
, T
>(fn
, objects
);
191 QFuture
<T
> future
= task
->future();
192 QThreadPool::globalInstance()->start(task
, priority
);
195 } // namespace QtConcurrent
199 #endif // MULTITASK_H