Commit 9e714006 authored by Eike Ziller's avatar Eike Ziller
Browse files

Move all progress indicator handling to progress manager.



Part of it was managed in ProgressView, which only complicates things.

Change-Id: Ia9ca03e3228f3662864749da751f7ec4bdf23297
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent e0f05e3b
......@@ -27,6 +27,7 @@
**
****************************************************************************/
#include "futureprogress.h"
#include "progressmanager_p.h"
#include "progressbar.h"
#include "progressview.h"
......@@ -267,8 +268,6 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent)
m_hovered(false)
{
m_progressView = new ProgressView;
connect(m_progressView, SIGNAL(hasErrorChanged()), this, SLOT(updateSummaryProgressBar()));
connect(m_progressView, SIGNAL(fadeOfLastProgressStarted()), this, SLOT(updateSummaryProgressBar()));
// withDelay, so the statusBarWidget has the chance to get the enter event
connect(m_progressView, SIGNAL(hoveredChanged(bool)), this, SLOT(updateVisibilityWithDelay()));
connect(ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(cancelAllRunningTasks()));
......@@ -276,6 +275,8 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent)
ProgressManagerPrivate::~ProgressManagerPrivate()
{
qDeleteAll(m_taskList);
m_taskList.clear();
ExtensionSystem::PluginManager::removeObject(m_statusBarWidgetContainer);
delete m_statusBarWidgetContainer;
cleanup();
......@@ -379,11 +380,15 @@ void ProgressManagerPrivate::cancelAllRunningTasks()
FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, const QString &title,
const QString &type, ProgressFlags flags)
{
// watch
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
m_runningTasks.insert(watcher, type);
connect(watcher, SIGNAL(progressRangeChanged(int,int)), this, SLOT(updateSummaryProgressBar()));
connect(watcher, SIGNAL(progressValueChanged(int)), this, SLOT(updateSummaryProgressBar()));
connect(watcher, SIGNAL(finished()), this, SLOT(taskFinished()));
watcher->setFuture(future);
// handle application task
if (flags & ShowInApplicationIcon) {
if (m_applicationTask)
disconnectApplicationTask();
......@@ -396,9 +401,28 @@ FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, con
this, SLOT(setApplicationProgressValue(int)));
setApplicationProgressVisible(true);
}
watcher->setFuture(future);
// create FutureProgress and manage task list
removeOldTasks(type);
if (m_taskList.size() == 10)
removeOneOldTask();
FutureProgress *progress = new FutureProgress;
progress->setTitle(title);
progress->setFuture(future);
m_progressView->addProgressWidget(progress);
m_taskList.append(progress);
progress->setType(type);
if (flags.testFlag(ProgressManager::KeepOnFinish))
progress->setKeepOnFinish(FutureProgress::KeepOnFinishTillUserInteraction);
else
progress->setKeepOnFinish(FutureProgress::HideOnFinish);
connect(progress, SIGNAL(hasErrorChanged()), this, SLOT(updateSummaryProgressBar()));
connect(progress, SIGNAL(removeMe()), this, SLOT(slotRemoveTask()));
connect(progress, SIGNAL(fadeStarted()), this, SLOT(updateSummaryProgressBar()));
emit taskStarted(type);
return m_progressView->addTask(future, title, type, flags);
return progress;
}
ProgressView *ProgressManagerPrivate::progressView()
......@@ -434,16 +458,16 @@ void ProgressManagerPrivate::disconnectApplicationTask()
void ProgressManagerPrivate::updateSummaryProgressBar()
{
m_summaryProgressBar->setError(m_progressView->hasError());
m_summaryProgressBar->setError(hasError());
updateVisibility();
if (m_runningTasks.isEmpty()) {
m_summaryProgressBar->setFinished(true);
if (m_progressView->isEmpty() || m_progressView->isFading())
fadeAway();
if (m_taskList.isEmpty() || isLastFading())
fadeAwaySummaryProgress();
return;
}
stopFade();
stopFadeOfSummaryProgress();
m_summaryProgressBar->setFinished(false);
QMapIterator<QFutureWatcher<void> *, QString> it(m_runningTasks);
......@@ -460,17 +484,17 @@ void ProgressManagerPrivate::updateSummaryProgressBar()
m_summaryProgressBar->setValue(value);
}
void ProgressManagerPrivate::fadeAway()
void ProgressManagerPrivate::fadeAwaySummaryProgress()
{
stopFade();
stopFadeOfSummaryProgress();
m_opacityAnimation = new QPropertyAnimation(m_opacityEffect, "opacity");
m_opacityAnimation->setDuration(Utils::StyleHelper::progressFadeAnimationDuration);
m_opacityAnimation->setEndValue(0.);
connect(m_opacityAnimation, SIGNAL(finished()), this, SLOT(fadeFinished()));
connect(m_opacityAnimation, SIGNAL(finished()), this, SLOT(summaryProgressFinishedFading()));
m_opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
void ProgressManagerPrivate::stopFade()
void ProgressManagerPrivate::stopFadeOfSummaryProgress()
{
if (m_opacityAnimation) {
m_opacityAnimation->stop();
......@@ -479,10 +503,100 @@ void ProgressManagerPrivate::stopFade()
}
}
bool ProgressManagerPrivate::hasError() const
{
foreach (FutureProgress *progress, m_taskList)
if (progress->hasError())
return true;
return false;
}
bool ProgressManagerPrivate::isLastFading() const
{
if (m_taskList.isEmpty())
return false;
foreach (FutureProgress *progress, m_taskList) {
if (!progress->isFading()) // we still have progress bars that are not fading
return false;
}
return true;
}
void ProgressManagerPrivate::slotRemoveTask()
{
FutureProgress *progress = qobject_cast<FutureProgress *>(sender());
QTC_ASSERT(progress, return);
QString type = progress->type();
removeTask(progress);
removeOldTasks(type, true);
}
void ProgressManagerPrivate::removeOldTasks(const QString &type, bool keepOne)
{
bool firstFound = !keepOne; // start with false if we want to keep one
QList<FutureProgress *>::iterator i = m_taskList.end();
while (i != m_taskList.begin()) {
--i;
if ((*i)->type() == type) {
if (firstFound && ((*i)->future().isFinished() || (*i)->future().isCanceled())) {
deleteTask(*i);
i = m_taskList.erase(i);
}
firstFound = true;
}
}
}
void ProgressManagerPrivate::removeOneOldTask()
{
if (m_taskList.isEmpty())
return;
// look for oldest ended process
for (QList<FutureProgress *>::iterator i = m_taskList.begin(); i != m_taskList.end(); ++i) {
if ((*i)->future().isFinished()) {
deleteTask(*i);
i = m_taskList.erase(i);
return;
}
}
// no ended process, look for a task type with multiple running tasks and remove the oldest one
for (QList<FutureProgress *>::iterator i = m_taskList.begin(); i != m_taskList.end(); ++i) {
QString type = (*i)->type();
int taskCount = 0;
foreach (FutureProgress *p, m_taskList)
if (p->type() == type)
++taskCount;
if (taskCount > 1) { // don't care for optimizations it's only a handful of entries
deleteTask(*i);
i = m_taskList.erase(i);
return;
}
}
// no ended process, no type with multiple processes, just remove the oldest task
FutureProgress *task = m_taskList.takeFirst();
deleteTask(task);
}
void ProgressManagerPrivate::removeTask(FutureProgress *task)
{
m_taskList.removeAll(task);
deleteTask(task);
}
void ProgressManagerPrivate::deleteTask(FutureProgress *progress)
{
m_progressView->removeProgressWidget(progress);
progress->hide();
progress->deleteLater();
}
void ProgressManagerPrivate::updateVisibility()
{
m_progressView->setVisible(m_progressViewPinned || m_hovered || m_progressView->isHovered());
m_summaryProgressBar->setVisible((!m_runningTasks.isEmpty() || !m_progressView->isEmpty())
m_summaryProgressBar->setVisible((!m_runningTasks.isEmpty() || !m_taskList.isEmpty())
&& !m_progressViewPinned);
}
......@@ -491,7 +605,7 @@ void ProgressManagerPrivate::updateVisibilityWithDelay()
QTimer::singleShot(150, this, SLOT(updateVisibility()));
}
void ProgressManagerPrivate::fadeFinished()
void ProgressManagerPrivate::summaryProgressFinishedFading()
{
m_summaryProgressBar->setVisible(false);
m_opacityEffect->setOpacity(1.);
......
......@@ -77,17 +77,27 @@ private slots:
void setApplicationProgressVisible(bool visible);
void disconnectApplicationTask();
void updateSummaryProgressBar();
void fadeAway();
void fadeFinished();
void fadeAwaySummaryProgress();
void summaryProgressFinishedFading();
void progressDetailsToggled(bool checked);
void updateVisibility();
void updateVisibilityWithDelay();
void slotRemoveTask();
private:
void initInternal();
void stopFade();
void stopFadeOfSummaryProgress();
bool hasError() const;
bool isLastFading() const;
void removeOldTasks(const QString &type, bool keepOne = false);
void removeOneOldTask();
void removeTask(FutureProgress *task);
void deleteTask(FutureProgress *task);
QPointer<ProgressView> m_progressView;
QList<FutureProgress *> m_taskList;
QMap<QFutureWatcher<void> *, QString> m_runningTasks;
QFutureWatcher<void> *m_applicationTask;
Core::StatusBarWidget *m_statusBarWidgetContainer;
......
......@@ -28,9 +28,6 @@
****************************************************************************/
#include "progressview.h"
#include "futureprogress.h"
#include <utils/qtcassert.h>
#include <QEvent>
#include <QVBoxLayout>
......@@ -53,57 +50,16 @@ ProgressView::ProgressView(QWidget *parent)
ProgressView::~ProgressView()
{
qDeleteAll(m_taskList);
m_taskList.clear();
}
FutureProgress *ProgressView::addTask(const QFuture<void> &future,
const QString &title,
const QString &type,
ProgressManager::ProgressFlags flags)
{
removeOldTasks(type);
if (m_taskList.size() == 10)
removeOneOldTask();
FutureProgress *progress = new FutureProgress(this);
progress->setTitle(title);
progress->setFuture(future);
m_layout->insertWidget(0, progress);
m_taskList.append(progress);
progress->setType(type);
if (flags.testFlag(ProgressManager::KeepOnFinish))
progress->setKeepOnFinish(FutureProgress::KeepOnFinishTillUserInteraction);
else
progress->setKeepOnFinish(FutureProgress::HideOnFinish);
connect(progress, SIGNAL(hasErrorChanged()), this, SIGNAL(hasErrorChanged()));
connect(progress, SIGNAL(removeMe()), this, SLOT(slotRemoveTask()));
connect(progress, SIGNAL(fadeStarted()), this, SLOT(checkForLastProgressFading()));
return progress;
}
bool ProgressView::hasError() const
{
foreach (FutureProgress *progress, m_taskList)
if (progress->hasError())
return true;
return false;
}
bool ProgressView::isFading() const
void ProgressView::addProgressWidget(QWidget *widget)
{
if (m_taskList.isEmpty())
return false;
foreach (FutureProgress *progress, m_taskList) {
if (!progress->isFading()) // we still have progress bars that are not fading, do nothing
return false;
}
return true;
m_layout->insertWidget(0, widget);
}
bool ProgressView::isEmpty() const
void ProgressView::removeProgressWidget(QWidget *widget)
{
return m_taskList.isEmpty();
m_layout->removeWidget(widget);
}
bool ProgressView::isHovered() const
......@@ -146,29 +102,6 @@ bool ProgressView::eventFilter(QObject *obj, QEvent *event)
return false;
}
void ProgressView::removeOldTasks(const QString &type, bool keepOne)
{
bool firstFound = !keepOne; // start with false if we want to keep one
QList<FutureProgress *>::iterator i = m_taskList.end();
while (i != m_taskList.begin()) {
--i;
if ((*i)->type() == type) {
if (firstFound && ((*i)->future().isFinished() || (*i)->future().isCanceled())) {
deleteTask(*i);
i = m_taskList.erase(i);
}
firstFound = true;
}
}
}
void ProgressView::deleteTask(FutureProgress *progress)
{
layout()->removeWidget(progress);
progress->hide();
progress->deleteLater();
}
void ProgressView::reposition()
{
if (!parentWidget() || !m_referenceWidget)
......@@ -177,57 +110,3 @@ void ProgressView::reposition()
m_referenceWidget->mapTo(parentWidget(), m_referenceWidget->rect().topRight());
move(topRightReferenceInParent - rect().bottomRight());
}
void ProgressView::removeOneOldTask()
{
if (m_taskList.isEmpty())
return;
// look for oldest ended process
for (QList<FutureProgress *>::iterator i = m_taskList.begin(); i != m_taskList.end(); ++i) {
if ((*i)->future().isFinished()) {
deleteTask(*i);
i = m_taskList.erase(i);
return;
}
}
// no ended process, look for a task type with multiple running tasks and remove the oldest one
for (QList<FutureProgress *>::iterator i = m_taskList.begin(); i != m_taskList.end(); ++i) {
QString type = (*i)->type();
int taskCount = 0;
foreach (FutureProgress *p, m_taskList)
if (p->type() == type)
++taskCount;
if (taskCount > 1) { // don't care for optimizations it's only a handful of entries
deleteTask(*i);
i = m_taskList.erase(i);
return;
}
}
// no ended process, no type with multiple processes, just remove the oldest task
FutureProgress *task = m_taskList.takeFirst();
deleteTask(task);
}
void ProgressView::removeTask(FutureProgress *task)
{
m_taskList.removeAll(task);
deleteTask(task);
}
void ProgressView::slotRemoveTask()
{
FutureProgress *progress = qobject_cast<FutureProgress *>(sender());
QTC_ASSERT(progress, return);
QString type = progress->type();
removeTask(progress);
removeOldTasks(type, true);
}
void ProgressView::checkForLastProgressFading()
{
if (isEmpty() || isFading())
emit fadeOfLastProgressStarted();
}
......@@ -32,7 +32,6 @@
#include "progressmanager.h"
#include <QFuture>
#include <QWidget>
......@@ -42,8 +41,6 @@ QT_END_NAMESPACE
namespace Core {
class FutureProgress;
namespace Internal {
class ProgressView : public QWidget
......@@ -54,15 +51,9 @@ public:
ProgressView(QWidget *parent = 0);
~ProgressView();
/** The returned FutureProgress instance is guaranteed to live till next main loop event processing (deleteLater). */
FutureProgress *addTask(const QFuture<void> &future,
const QString &title,
const QString &type,
ProgressManager::ProgressFlags flags);
void addProgressWidget(QWidget *widget);
void removeProgressWidget(QWidget *widget);
bool hasError() const;
bool isFading() const;
bool isEmpty() const;
bool isHovered() const;
void setReferenceWidget(QWidget *widget);
......@@ -72,23 +63,12 @@ protected:
bool eventFilter(QObject *obj, QEvent *event);
signals:
void hasErrorChanged();
void fadeOfLastProgressStarted();
void hoveredChanged(bool hovered);
private slots:
void slotRemoveTask();
void checkForLastProgressFading();
private:
void removeOldTasks(const QString &type, bool keepOne = false);
void removeOneOldTask();
void removeTask(FutureProgress *task);
void deleteTask(FutureProgress *task);
void reposition();
QVBoxLayout *m_layout;
QList<FutureProgress *> m_taskList;
QWidget *m_referenceWidget;
bool m_hovered;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment