From d450bcd7605a12f396a46ddebb0f0b3df82c6517 Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 12 Mar 2010 16:26:42 +0100 Subject: [PATCH] Keep notification bar clean The patch makes notification items fade away after 5 seconds. KeepOnFinish items like the build notification are kept for 5 seconds after the user interacts with mouse or keyboard. Done-width: jbache --- .../progressmanager/futureprogress.cpp | 51 +++++++++++++++++++ .../progressmanager/futureprogress.h | 33 ++++++++++++ .../progressmanager/progressview.cpp | 31 ++++++----- .../coreplugin/progressmanager/progressview.h | 4 +- 4 files changed, 102 insertions(+), 17 deletions(-) diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.cpp b/src/plugins/coreplugin/progressmanager/futureprogress.cpp index 69b17c103b7..66f390c5590 100644 --- a/src/plugins/coreplugin/progressmanager/futureprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/futureprogress.cpp @@ -35,10 +35,25 @@ #include #include #include +#include +#include +#include +#include +#include using namespace Core; +void FadeWidgetHack::paintEvent(QPaintEvent *) +{ + if (m_opacity == 0) + return; + + QPainter p(this); + p.setOpacity(m_opacity); + Utils::StyleHelper::verticalGradient(&p, rect(), rect()); +} + /*! \mainclass \class Core::FutureProgress @@ -96,6 +111,10 @@ FutureProgress::FutureProgress(QWidget *parent) connect(&m_watcher, SIGNAL(progressTextChanged(const QString&)), this, SLOT(setProgressText(const QString&))); connect(m_progress, SIGNAL(clicked()), this, SLOT(cancel())); + + m_keep = false; + m_waitingForUserInteraction = false; + m_faderWidget = new FadeWidgetHack(this); } /*! @@ -162,6 +181,17 @@ void FutureProgress::setStarted() m_progress->setValue(m_watcher.progressValue()); } + +bool FutureProgress::eventFilter(QObject *, QEvent *e) +{ + if (m_waitingForUserInteraction + && (e->type() == QEvent::MouseMove || e->type() == QEvent::KeyPress)) { + qApp->removeEventFilter(this); + QTimer::singleShot(5000, this, SLOT(fadeAway())); + } + return false; +} + void FutureProgress::setFinished() { updateToolTip(m_watcher.future().progressText()); @@ -171,6 +201,12 @@ void FutureProgress::setFinished() m_progress->setError(false); } emit finished(); + if (m_keep) { + m_waitingForUserInteraction = true; + qApp->installEventFilter(this); + } else { + QTimer::singleShot(5000, this, SLOT(fadeAway())); + } } void FutureProgress::setProgressRange(int min, int max) @@ -217,6 +253,11 @@ void FutureProgress::mousePressEvent(QMouseEvent *event) QWidget::mousePressEvent(event); } +void FutureProgress::resizeEvent(QResizeEvent *) +{ + m_faderWidget->setGeometry(rect()); +} + /*! \fn bool FutureProgress::hasError() const Returns the error state of this progress indicator. @@ -225,3 +266,13 @@ bool FutureProgress::hasError() const { return m_progress->hasError(); } + +void FutureProgress::fadeAway() +{ + m_faderWidget->raise(); + QPropertyAnimation *animation = new QPropertyAnimation(m_faderWidget, "opacity"); + animation->setDuration(600); + animation->setEndValue(1.0); + animation->start(QAbstractAnimation::DeleteWhenStopped); + connect(animation, SIGNAL(finished()), this, SIGNAL(removeMe())); +} diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.h b/src/plugins/coreplugin/progressmanager/futureprogress.h index 5d2e936757f..c09cf84ac31 100644 --- a/src/plugins/coreplugin/progressmanager/futureprogress.h +++ b/src/plugins/coreplugin/progressmanager/futureprogress.h @@ -46,6 +46,23 @@ class ProgressBar; namespace Core { + class FadeWidgetHack : public QWidget + { + Q_OBJECT + Q_PROPERTY(float opacity READ opacity WRITE setOpacity) + public: + FadeWidgetHack(QWidget *parent):QWidget(parent), m_opacity(0){ + setAttribute(Qt::WA_TransparentForMouseEvents); + } + void paintEvent(QPaintEvent *); + + void setOpacity(float o) { m_opacity = o; update(); } + float opacity() const { return m_opacity; } + + private: + float m_opacity; + }; + class CORE_EXPORT FutureProgress : public QWidget { Q_OBJECT @@ -54,12 +71,20 @@ public: FutureProgress(QWidget *parent = 0); ~FutureProgress(); + bool eventFilter(QObject *object, QEvent *); + void setFuture(const QFuture &future); QFuture future() const; void setTitle(const QString &title); QString title() const; + void setType(const QString &type) {m_type = type; } + QString type() const { return m_type; } + + void setKeepOnFinish(bool keep) { m_keep = keep; } + bool keepOnFinish() const { return m_keep; } + bool hasError() const; void setWidget(QWidget *widget); @@ -68,9 +93,11 @@ public: signals: void clicked(); void finished(); + void removeMe(); protected: void mousePressEvent(QMouseEvent *event); + void resizeEvent(QResizeEvent *); private slots: void updateToolTip(const QString &); @@ -80,12 +107,18 @@ private slots: void setProgressRange(int min, int max); void setProgressValue(int val); void setProgressText(const QString &text); + void fadeAway(); private: QFutureWatcher m_watcher; ProgressBar *m_progress; QWidget *m_widget; QHBoxLayout *m_widgetLayout; + QString m_type; + bool m_keep; + bool m_waitingForUserInteraction; + FadeWidgetHack *m_faderWidget; + }; } // namespace Core diff --git a/src/plugins/coreplugin/progressmanager/progressview.cpp b/src/plugins/coreplugin/progressmanager/progressview.cpp index fcf6b09ce97..36e55f80673 100644 --- a/src/plugins/coreplugin/progressmanager/progressview.cpp +++ b/src/plugins/coreplugin/progressmanager/progressview.cpp @@ -51,8 +51,6 @@ ProgressView::~ProgressView() { qDeleteAll(m_taskList); m_taskList.clear(); - m_type.clear(); - m_keep.clear(); } FutureProgress *ProgressView::addTask(const QFuture &future, @@ -66,11 +64,12 @@ FutureProgress *ProgressView::addTask(const QFuture &future, FutureProgress *progress = new FutureProgress(this); progress->setTitle(title); progress->setFuture(future); + m_layout->insertWidget(0, progress); m_taskList.append(progress); - m_type.insert(progress, type); - m_keep.insert(progress, (flags & ProgressManager::KeepOnFinish)); - connect(progress, SIGNAL(finished()), this, SLOT(slotFinished())); + progress->setType(type); + progress->setKeepOnFinish(flags & ProgressManager::KeepOnFinish); + connect(progress, SIGNAL(removeMe()), this, SLOT(slotRemoveTask())); return progress; } @@ -80,7 +79,7 @@ void ProgressView::removeOldTasks(const QString &type, bool keepOne) QList::iterator i = m_taskList.end(); while (i != m_taskList.begin()) { --i; - if (m_type.value(*i) == type) { + if ((*i)->type() == type) { if (firstFound && (*i)->future().isFinished()) { deleteTask(*i); i = m_taskList.erase(i); @@ -92,8 +91,6 @@ void ProgressView::removeOldTasks(const QString &type, bool keepOne) void ProgressView::deleteTask(FutureProgress *progress) { - m_type.remove(progress); - m_keep.remove(progress); layout()->removeWidget(progress); progress->hide(); progress->deleteLater(); @@ -113,8 +110,14 @@ void ProgressView::removeOneOldTask() } // no ended process, look for a task type with multiple running tasks and remove the oldest one for (QList::iterator i = m_taskList.begin(); i != m_taskList.end(); ++i) { - QString type = m_type.value(*i); - if (m_type.keys(type).size() > 1) { // don't care for optimizations it's only a handful of entries + 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; @@ -132,11 +135,11 @@ void ProgressView::removeTask(FutureProgress *task) deleteTask(task); } -void ProgressView::slotFinished() +void ProgressView::slotRemoveTask() { FutureProgress *progress = qobject_cast(sender()); QTC_ASSERT(progress, return); - if (m_keep.contains(progress) && !m_keep.value(progress) && !progress->hasError()) - removeTask(progress); - removeOldTasks(m_type.value(progress), true); + QString type = progress->type(); + removeTask(progress); + removeOldTasks(type, true); } diff --git a/src/plugins/coreplugin/progressmanager/progressview.h b/src/plugins/coreplugin/progressmanager/progressview.h index e12c9f21a3b..bc589f67115 100644 --- a/src/plugins/coreplugin/progressmanager/progressview.h +++ b/src/plugins/coreplugin/progressmanager/progressview.h @@ -58,7 +58,7 @@ public: ProgressManager::ProgressFlags flags); private slots: - void slotFinished(); + void slotRemoveTask(); private: void removeOldTasks(const QString &type, bool keepOne = false); @@ -68,8 +68,6 @@ private: QVBoxLayout *m_layout; QList m_taskList; - QHash m_type; - QHash m_keep; }; } // namespace Internal