1
/***************************************************************************
2
* Copyright (C) 2008, 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl> *
3
* Copyright (C) 2010 Marco Martin <notmart@gmail.com> *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
19
***************************************************************************/
21
#include "busywidget.h"
24
#include <QtGui/QPainter>
25
#include <QtGui/QTextOption>
26
#include <QtGui/QStyleOptionGraphicsItem>
27
#include <QtGui/QWidget> // QWIDGETSIZE_MAX
28
#include <QSequentialAnimationGroup>
30
#include <plasma/extender.h>
31
#include <plasma/extenderitem.h>
32
#include <plasma/extendergroup.h>
33
#include <plasma/popupapplet.h>
34
#include <plasma/tooltipmanager.h>
35
#include <plasma/theme.h>
36
#include <Plasma/Animation>
37
#include <Plasma/Animator>
40
#include <KGlobalSettings>
42
#include "../core/notificationsmanager.h"
43
#include "../core/job.h"
44
#include "../core/notification.h"
45
#include "../core/completedjobnotification.h"
49
BusyWidget::BusyWidget(Plasma::PopupApplet *parent, const Manager *manager)
50
: Plasma::BusyWidget(parent),
51
m_icon("dialog-information"),
53
m_svg(new Plasma::Svg(this)),
58
setAcceptsHoverEvents(true);
59
m_svg->setImagePath("icons/notification");
60
m_svg->setContainsMultipleImages(true);
63
m_fadeInAnimation = Plasma::Animator::create(Plasma::Animator::PixmapTransitionAnimation);
64
m_fadeInAnimation->setTargetWidget(this);
65
m_fadeInAnimation->setProperty("duration", 1000);
66
m_fadeInAnimation->setProperty("targetPixmap", m_svg->pixmap("notification-active"));
68
m_fadeOutAnimation = Plasma::Animator::create(Plasma::Animator::PixmapTransitionAnimation);
69
m_fadeOutAnimation->setTargetWidget(this);
70
m_fadeOutAnimation->setProperty("duration", 1000);
71
m_fadeOutAnimation->setProperty("startPixmap", m_svg->pixmap("notification-active"));
74
m_fadeGroup = new QSequentialAnimationGroup(this);
75
m_fadeGroup->addAnimation(m_fadeInAnimation);
76
m_fadeGroup->addAnimation(m_fadeOutAnimation);
78
connect(manager, SIGNAL(notificationAdded(Notification*)),
79
this, SLOT(updateTask()));
80
connect(manager, SIGNAL(notificationRemoved(Notification*)),
81
this, SLOT(updateTask()));
82
connect(manager, SIGNAL(notificationChanged(Notification*)),
83
this, SLOT(updateTask()));
84
connect(manager, SIGNAL(notificationExpired(Notification*)),
85
this, SLOT(updateTask()));
86
connect(manager, SIGNAL(jobAdded(Job*)),
87
this, SLOT(updateTask()));
88
connect(manager, SIGNAL(jobRemoved(Job*)),
89
this, SLOT(updateTask()));
90
connect(manager, SIGNAL(jobStateChanged(Job*)),
91
this, SLOT(updateTask()));
93
Plasma::Extender *extender = qobject_cast<Plasma::Extender *>(m_systray->graphicsWidget());
95
connect(extender, SIGNAL(itemDetached(Plasma::ExtenderItem*)),
96
this, SLOT(updateTask()));
102
void BusyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
104
QRectF iconRect(0, 0, qMin(size().width(), size().height()), qMin(size().width(), size().height()));
105
iconRect.moveCenter(boundingRect().center());
107
if (m_state == Running) {
108
const int arcStart = 90*16;
109
const int arcEnd = -(360*(qreal)m_manager->jobTotals()->percentage()/100)*16;
111
Plasma::BusyWidget::paint(painter, option, widget);
113
//kDebug() << arcStart << arcEnd;
115
QPixmap activePixmap(iconRect.size().toSize());
116
activePixmap.fill(Qt::transparent);
117
QPixmap inActivePixmap(iconRect.size().toSize());
118
inActivePixmap.fill(Qt::transparent);
119
QRect pieRect(QPoint(0, 0), activePixmap.size()*2);
120
pieRect.moveCenter(activePixmap.rect().center());
122
QPainter p(&activePixmap);
124
p.setBrush(Qt::black);
125
p.setCompositionMode(QPainter::CompositionMode_Source);
126
p.drawPie(pieRect, arcStart, arcEnd);
127
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
128
m_svg->paint(&p, QRectF(QPointF(0, 0), iconRect.size()), "notification-progress-active");
131
p.begin(&inActivePixmap);
133
p.setBrush(Qt::black);
134
p.setCompositionMode(QPainter::CompositionMode_Source);
135
p.drawPie(pieRect, arcStart, (360*16)+arcEnd);
136
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
137
m_svg->paint(&p, QRectF(QPointF(0, 0), iconRect.size()), "notification-progress-inactive");
140
painter->drawPixmap(iconRect.topLeft().toPoint(), activePixmap);
141
painter->drawPixmap(iconRect.topLeft().toPoint(), inActivePixmap);
143
Plasma::BusyWidget::paint(painter, option, widget);
145
} else if (m_state == Empty && m_manager->notifications().count() > 0) {
146
m_svg->paint(painter, iconRect, "notification-inactive");
147
} else if (m_state == Empty && m_manager->notifications().count() == 0) {
148
m_svg->paint(painter, iconRect, "notification-disabled");
151
m_svg->paint(painter, iconRect, "notification-empty");
152
QFont font(KGlobalSettings::smallestReadableFont());
153
painter->setFont(font);
156
painter->setPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor));
158
const QFontMetrics fm(font);
159
const QSize textSize = fm.boundingRect(label()).size();
160
const bool textFits = textSize.width() <= r.width() && textSize.height() <= r.height();
161
if (m_svg && m_svg->hasElement(expanderElement())) {
162
QSizeF arrowSize(m_svg->elementSize(expanderElement()));
163
QRectF arrowRect(r.center() - QPointF(arrowSize.width() / 2, arrowSize.height() + fm.xHeight() / 2), arrowSize);
164
m_svg->paint(painter, arrowRect, expanderElement());
166
r.setTop(arrowRect.bottom());
169
painter->drawText(r, Qt::AlignHCenter|Qt::AlignTop, label());
171
} else if (textFits) {
172
painter->drawText(r, Qt::AlignCenter, label());
176
if (m_fadeInAnimation->state() == QAbstractAnimation::Running) {
177
QPixmap pix = m_fadeInAnimation->property("currentPixmap").value<QPixmap>();
178
painter->drawPixmap(iconRect, pix, pix.rect());
179
} else if (m_fadeOutAnimation->state() == QAbstractAnimation::Running) {
180
QPixmap pix = m_fadeOutAnimation->property("currentPixmap").value<QPixmap>();
181
painter->drawPixmap(iconRect, pix, pix.rect());
185
void BusyWidget::resizeEvent(QGraphicsSceneResizeEvent *)
188
m_svg->resize(contentsRect().size());
189
m_fadeInAnimation->setProperty("targetPixmap", m_svg->pixmap("notification-active"));
190
m_fadeOutAnimation->setProperty("startPixmap", m_svg->pixmap("notification-active"));
194
void BusyWidget::setState(State state)
196
if (m_state == state) {
201
setRunning(m_state == Running);
205
QString BusyWidget::expanderElement() const
207
switch (m_systray->location()) {
208
case Plasma::TopEdge:
209
return "expander-top";
210
case Plasma::RightEdge:
211
return "expander-right";
212
case Plasma::LeftEdge:
213
return "expander-left";
214
case Plasma::BottomEdge:
216
return "expander-bottom";
220
void BusyWidget::updateTask()
224
int completedJobs = 0;
225
foreach (const Job *job, m_manager->jobs()) {
226
switch (job->state()) {
238
int total = m_manager->jobs().count();
240
foreach (Notification *notification, m_manager->notifications()) {
241
if (qobject_cast<CompletedJobNotification *>(notification)) {
243
} else if (!notification->isExpired()) {
248
total += completedJobs;
251
if (!(total + m_manager->notifications().count())) {
252
m_systray->hidePopup();
255
if (total > m_total) {
256
m_fadeGroup->start();
261
setState(BusyWidget::Empty);
263
} else if (runningJobs) {
264
setState(BusyWidget::Running);
265
setLabel(QString("%1").arg(QString::number(total)));
267
setState(BusyWidget::Info);
268
setLabel(QString::number(total));
271
//make a nice plasma tooltip
272
QString tooltipContent;
273
if (runningJobs > 0) {
274
tooltipContent += i18np("%1 running job", "%1 running jobs", runningJobs);
275
if (pausedJobs > 0 || completedJobs > 0 || !m_manager->notifications().isEmpty()) {
276
tooltipContent += "<br>";
280
if (pausedJobs > 0) {
281
tooltipContent += i18np("%1 suspended job", "%1 suspended jobs", pausedJobs);
282
if (completedJobs > 0 || !m_manager->notifications().isEmpty()) {
283
tooltipContent += "<br>";
287
if (completedJobs > 0) {
288
tooltipContent += i18np("%1 completed job", "%1 completed jobs", completedJobs);
289
if (!m_manager->notifications().isEmpty()) {
290
tooltipContent += "<br>";
294
if (!m_manager->notifications().isEmpty()) {
295
tooltipContent += i18np("%1 notification", "%1 notifications",
296
m_manager->notifications().count());
299
if (tooltipContent.isEmpty()) {
300
tooltipContent = i18n("No active jobs or notifications");
303
Plasma::ToolTipContent data(i18n("Notifications and jobs"),
305
KIcon("help-about"));
306
Plasma::ToolTipManager::self()->setContent(this, data);
310
#include "busywidget.moc"