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 @@ ...@@ -27,6 +27,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include "futureprogress.h"
#include "progressmanager_p.h" #include "progressmanager_p.h"
#include "progressbar.h" #include "progressbar.h"
#include "progressview.h" #include "progressview.h"
...@@ -267,8 +268,6 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent) ...@@ -267,8 +268,6 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent)
m_hovered(false) m_hovered(false)
{ {
m_progressView = new ProgressView; 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 // withDelay, so the statusBarWidget has the chance to get the enter event
connect(m_progressView, SIGNAL(hoveredChanged(bool)), this, SLOT(updateVisibilityWithDelay())); connect(m_progressView, SIGNAL(hoveredChanged(bool)), this, SLOT(updateVisibilityWithDelay()));
connect(ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(cancelAllRunningTasks())); connect(ICore::instance(), SIGNAL(coreAboutToClose()), this, SLOT(cancelAllRunningTasks()));
...@@ -276,6 +275,8 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent) ...@@ -276,6 +275,8 @@ ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent)
ProgressManagerPrivate::~ProgressManagerPrivate() ProgressManagerPrivate::~ProgressManagerPrivate()
{ {
qDeleteAll(m_taskList);
m_taskList.clear();
ExtensionSystem::PluginManager::removeObject(m_statusBarWidgetContainer); ExtensionSystem::PluginManager::removeObject(m_statusBarWidgetContainer);
delete m_statusBarWidgetContainer; delete m_statusBarWidgetContainer;
cleanup(); cleanup();
...@@ -379,11 +380,15 @@ void ProgressManagerPrivate::cancelAllRunningTasks() ...@@ -379,11 +380,15 @@ void ProgressManagerPrivate::cancelAllRunningTasks()
FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, const QString &title, FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, const QString &title,
const QString &type, ProgressFlags flags) const QString &type, ProgressFlags flags)
{ {
// watch
QFutureWatcher<void> *watcher = new QFutureWatcher<void>(); QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
m_runningTasks.insert(watcher, type); m_runningTasks.insert(watcher, type);
connect(watcher, SIGNAL(progressRangeChanged(int,int)), this, SLOT(updateSummaryProgressBar())); connect(watcher, SIGNAL(progressRangeChanged(int,int)), this, SLOT(updateSummaryProgressBar()));
connect(watcher, SIGNAL(progressValueChanged(int)), this, SLOT(updateSummaryProgressBar())); connect(watcher, SIGNAL(progressValueChanged(int)), this, SLOT(updateSummaryProgressBar()));
connect(watcher, SIGNAL(finished()), this, SLOT(taskFinished())); connect(watcher, SIGNAL(finished()), this, SLOT(taskFinished()));
watcher->setFuture(future);
// handle application task
if (flags & ShowInApplicationIcon) { if (flags & ShowInApplicationIcon) {
if (m_applicationTask) if (m_applicationTask)
disconnectApplicationTask(); disconnectApplicationTask();
...@@ -396,9 +401,28 @@ FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, con ...@@ -396,9 +401,28 @@ FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, con
this, SLOT(setApplicationProgressValue(int))); this, SLOT(setApplicationProgressValue(int)));
setApplicationProgressVisible(true); 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); emit taskStarted(type);
return m_progressView->addTask(future, title, type, flags); return progress;
} }
ProgressView *ProgressManagerPrivate::progressView() ProgressView *ProgressManagerPrivate::progressView()
...@@ -434,16 +458,16 @@ void ProgressManagerPrivate::disconnectApplicationTask() ...@@ -434,16 +458,16 @@ void ProgressManagerPrivate::disconnectApplicationTask()
void ProgressManagerPrivate::updateSummaryProgressBar() void ProgressManagerPrivate::updateSummaryProgressBar()
{ {
m_summaryProgressBar->setError(m_progressView->hasError()); m_summaryProgressBar->setError(hasError());
updateVisibility(); updateVisibility();
if (m_runningTasks.isEmpty()) { if (m_runningTasks.isEmpty()) {
m_summaryProgressBar->setFinished(true); m_summaryProgressBar->setFinished(true);
if (m_progressView->isEmpty() || m_progressView->isFading()) if (m_taskList.isEmpty() || isLastFading())
fadeAway(); fadeAwaySummaryProgress();
return; return;
} }
stopFade(); stopFadeOfSummaryProgress();
m_summaryProgressBar->setFinished(false); m_summaryProgressBar->setFinished(false);
QMapIterator<QFutureWatcher<void> *, QString> it(m_runningTasks); QMapIterator<QFutureWatcher<void> *, QString> it(m_runningTasks);
...@@ -460,17 +484,17 @@ void ProgressManagerPrivate::updateSummaryProgressBar() ...@@ -460,17 +484,17 @@ void ProgressManagerPrivate::updateSummaryProgressBar()
m_summaryProgressBar->setValue(value); m_summaryProgressBar->setValue(value);
} }
void ProgressManagerPrivate::fadeAway() void ProgressManagerPrivate::fadeAwaySummaryProgress()
{ {
stopFade(); stopFadeOfSummaryProgress();
m_opacityAnimation = new QPropertyAnimation(m_opacityEffect, "opacity"); m_opacityAnimation = new QPropertyAnimation(m_opacityEffect, "opacity");
m_opacityAnimation->setDuration(Utils::StyleHelper::progressFadeAnimationDuration); m_opacityAnimation->setDuration(Utils::StyleHelper::progressFadeAnimationDuration);
m_opacityAnimation->setEndValue(0.); 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); m_opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
} }
void ProgressManagerPrivate::stopFade() void ProgressManagerPrivate::stopFadeOfSummaryProgress()
{ {
if (m_opacityAnimation) { if (m_opacityAnimation) {
m_opacityAnimation->stop(); m_opacityAnimation->stop();
...@@ -479,10 +503,100 @@ void ProgressManagerPrivate::stopFade() ...@@ -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() void ProgressManagerPrivate::updateVisibility()
{ {
m_progressView->setVisible(m_progressViewPinned || m_hovered || m_progressView->isHovered()); 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); && !m_progressViewPinned);
} }
...@@ -491,7 +605,7 @@ void ProgressManagerPrivate::updateVisibilityWithDelay() ...@@ -491,7 +605,7 @@ void ProgressManagerPrivate::updateVisibilityWithDelay()
QTimer::singleShot(150, this, SLOT(updateVisibility())); QTimer::singleShot(150, this, SLOT(updateVisibility()));
} }
void ProgressManagerPrivate::fadeFinished() void ProgressManagerPrivate::summaryProgressFinishedFading()
{ {
m_summaryProgressBar->setVisible(false); m_summaryProgressBar->setVisible(false);
m_opacityEffect->setOpacity(1.); m_opacityEffect->setOpacity(1.);
......
...@@ -77,17 +77,27 @@ private slots: ...@@ -77,17 +77,27 @@ private slots:
void setApplicationProgressVisible(bool visible); void setApplicationProgressVisible(bool visible);
void disconnectApplicationTask(); void disconnectApplicationTask();
void updateSummaryProgressBar(); void updateSummaryProgressBar();
void fadeAway(); void fadeAwaySummaryProgress();
void fadeFinished(); void summaryProgressFinishedFading();
void progressDetailsToggled(bool checked); void progressDetailsToggled(bool checked);
void updateVisibility(); void updateVisibility();
void updateVisibilityWithDelay(); void updateVisibilityWithDelay();
void slotRemoveTask();
private: private:
void initInternal(); 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; QPointer<ProgressView> m_progressView;
QList<FutureProgress *> m_taskList;
QMap<QFutureWatcher<void> *, QString> m_runningTasks; QMap<QFutureWatcher<void> *, QString> m_runningTasks;
QFutureWatcher<void> *m_applicationTask; QFutureWatcher<void> *m_applicationTask;
Core::StatusBarWidget *m_statusBarWidgetContainer; Core::StatusBarWidget *m_statusBarWidgetContainer;
......
...@@ -28,9 +28,6 @@ ...@@ -28,9 +28,6 @@
****************************************************************************/ ****************************************************************************/
#include "progressview.h" #include "progressview.h"
#include "futureprogress.h"
#include <utils/qtcassert.h>
#include <QEvent> #include <QEvent>
#include <QVBoxLayout> #include <QVBoxLayout>
...@@ -53,57 +50,16 @@ ProgressView::ProgressView(QWidget *parent) ...@@ -53,57 +50,16 @@ ProgressView::ProgressView(QWidget *parent)
ProgressView::~ProgressView() 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 void ProgressView::addProgressWidget(QWidget *widget)
{ {
foreach (FutureProgress *progress, m_taskList) m_layout->insertWidget(0, widget);
if (progress->hasError())
return true;
return false;
}
bool ProgressView::isFading() const
{
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;
} }
bool ProgressView::isEmpty() const void ProgressView::removeProgressWidget(QWidget *widget)
{ {
return m_taskList.isEmpty(); m_layout->removeWidget(widget);
} }
bool ProgressView::isHovered() const bool ProgressView::isHovered() const
...@@ -146,29 +102,6 @@ bool ProgressView::eventFilter(QObject *obj, QEvent *event) ...@@ -146,29 +102,6 @@ bool ProgressView::eventFilter(QObject *obj, QEvent *event)
return false; 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() void ProgressView::reposition()
{ {
if (!parentWidget() || !m_referenceWidget) if (!parentWidget() || !m_referenceWidget)
...@@ -177,57 +110,3 @@ void ProgressView::reposition() ...@@ -177,57 +110,3 @@ void ProgressView::reposition()
m_referenceWidget->mapTo(parentWidget(), m_referenceWidget->rect().topRight()); m_referenceWidget->mapTo(parentWidget(), m_referenceWidget->rect().topRight());
move(topRightReferenceInParent - rect().bottomRight()); 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 @@ ...@@ -32,7 +32,6 @@
#include "progressmanager.h" #include "progressmanager.h"
#include <QFuture>
#include <QWidget> #include <QWidget>
...@@ -42,8 +41,6 @@ QT_END_NAMESPACE ...@@ -42,8 +41,6 @@ QT_END_NAMESPACE
namespace Core { namespace Core {
class FutureProgress;
namespace Internal { namespace Internal {
class ProgressView : public QWidget class ProgressView : public QWidget
...@@ -54,15 +51,9 @@ public: ...@@ -54,15 +51,9 @@ public:
ProgressView(QWidget *parent = 0); ProgressView(QWidget *parent = 0);
~ProgressView(); ~ProgressView();
/** The returned FutureProgress instance is guaranteed to live till next main loop event processing (deleteLater). */ void addProgressWidget(QWidget *widget);
FutureProgress *addTask(const QFuture<void> &future, void removeProgressWidget(QWidget *widget);
const QString &title,
const QString &type,
ProgressManager::ProgressFlags flags);
bool hasError() const;
bool isFading() const;
bool isEmpty() const;
bool isHovered() const; bool isHovered() const;
void setReferenceWidget(QWidget *widget); void setReferenceWidget(QWidget *widget);
...@@ -72,23 +63,12 @@ protected: ...@@ -72,23 +63,12 @@ protected:
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event);
signals: signals:
void hasErrorChanged();
void fadeOfLastProgressStarted();
void hoveredChanged(bool hovered); void hoveredChanged(bool hovered);
private slots:
void slotRemoveTask();
void checkForLastProgressFading();
private: private:
void removeOldTasks(const QString &type, bool keepOne = false);
void removeOneOldTask();
void removeTask(FutureProgress *task);
void deleteTask(FutureProgress *task);
void reposition(); void reposition();
QVBoxLayout *m_layout; QVBoxLayout *m_layout;
QList<FutureProgress *> m_taskList;
QWidget *m_referenceWidget; QWidget *m_referenceWidget;
bool m_hovered; 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!