fix start/stop/pause
[Sak.git] / sakwidget.cpp
blob809fa0ebd1fba498066a0ac443c5d98e46a7fb35
1 #include "sakwidget.h"
4 QBitmap* SakWidget::m_mask = 0;
5 int SakWidget::m_maxzvalue = 0;
7 SakWidget::SakWidget(const Task& task)
9 m_task = task;
11 m_palette.setColor(QPalette::Window, task.bgColor);
12 m_palette.setColor(QPalette::WindowText, task.fgColor);
14 m_flipTimer = 0;
15 m_showingDetails=false;
16 m_sideB = false;
17 m_ismoving = false;
19 setAcceptsHoverEvents(false);
20 m_dailyWorked = m_weeklyWorked = m_dailyPercentage = m_weeklyPercentage = 0;
22 m_text = 0;
23 m_rect = QRectF(0,0,400,400);
25 m_border = 5;
26 if (m_mask == 0 ) {
27 m_mask = new QBitmap(QSize(400,400));
28 QPainter p(m_mask);
29 m_mask->fill(Qt::white);
30 QPen pen;
31 pen.setWidth(4);
32 pen.setColor(Qt::black);
33 p.setPen(pen);
34 p.setBrush(Qt::black);
35 int border = m_border + 4;
36 p.drawRoundRect(m_rect.adjusted(border,border, -border,-border), 25, 25 );
39 m_text = new QTextDocument(this);
40 m_text->setHtml(m_tooltipText);
41 m_text->setTextWidth(m_rect.width() - 20);
43 m_cachedPixmap = QPixmap(QSize((int)m_rect.width(), (int)m_rect.height()));
44 m_cachedPixmapB = QPixmap(QSize((int)m_rect.width(), (int)m_rect.height()));
47 m_ic = QPixmap(m_task.icon);
48 if (!m_ic.isNull()) {
49 m_ic = m_ic.scaled(m_mask->width()-14, m_mask->height()-14, Qt::KeepAspectRatio);
50 QRect r = m_ic.rect();
51 r.moveTopLeft(QPoint((m_mask->width() - m_ic.width())/2, (m_mask->height()-m_ic.height())/2));
52 m_ic.setMask(m_mask->copy(r));
54 m_redrawCachedPixmap=true;
55 m_redrawCachedPixmapB=true;
56 redrawPixmaps();
59 SakWidget::~SakWidget()
61 delete m_text;
66 void SakWidget::setStatistics(double dailyWorked, double weeklyWorked, double monthlyWorked, double dailyPercentage, double weeklyPercentage, double monthlyPercentage)
68 m_dailyWorked = dailyWorked;
69 m_weeklyWorked = weeklyWorked;
70 m_monthlyWorked = monthlyWorked;
71 m_dailyPercentage = dailyPercentage;
72 m_weeklyPercentage = weeklyPercentage;
73 m_monthlyPercentage = monthlyPercentage;
74 m_tooltipText = QString("<div style=\"color:" + m_task.fgColor.name() + "\"><center><h1>%1</h1></center>%2%3<div>Today: <b>%4</b> h (%5%)<br />Last week: <b>%6</b> h (%7%)<br />Last month: <b>%8</b> h (%9%)</div></div>").arg(m_task.title).arg(m_task.description.isEmpty() ? "" : "<p>").arg(m_task.description).arg(m_dailyWorked).arg(m_dailyPercentage, 0, 'f', 2).arg(m_weeklyWorked).arg(m_weeklyPercentage, 0, 'f', 2).arg(m_monthlyWorked).arg(m_monthlyPercentage, 0, 'f', 2);
75 m_text->setHtml(m_tooltipText);
76 m_redrawCachedPixmapB=true;
79 #define ITERATIONS 5
80 void SakWidget::timerEvent(QTimerEvent* e)
82 if (!scene()) return;
83 if (e->timerId() == m_flipTimer) {
84 if (m_showingDetails == true) {
85 QTransform t;
86 t.translate( m_animItr * (m_rect.width() / 2 / ITERATIONS), 0);
87 t.rotate( - m_animItr * 90.0 / ITERATIONS, Qt::YAxis);
88 double newScale = m_scale + m_animItr * (qMax(1.0, m_scale) - m_scale) / 2 / ITERATIONS;
89 t.scale( newScale, newScale );
90 setTransform(t);
91 setPos( m_position + m_animItr * ( scene()->sceneRect().center() - m_rect.center() - m_position ) / 2/ ITERATIONS );
92 if (m_animItr == ITERATIONS+1) {
93 m_sideB = true;
94 } else if (m_animItr >= 2*ITERATIONS ) {
95 killTimer(m_flipTimer);
96 m_animItr=0;
98 m_animItr += 1;
99 } else {
100 QTransform t;
101 t.translate( m_rect.width() - m_animItr * (m_rect.width() / 2 / ITERATIONS), 0);
102 t.rotate( - 180 - m_animItr * 90.0 / ITERATIONS, Qt::YAxis);
103 double newScale = qMax(1.0, m_scale) + m_animItr * (m_scale - qMax(1.0, m_scale)) / 2 / ITERATIONS;
104 t.scale(newScale, newScale);
105 setTransform(t);
106 setPos( scene()->sceneRect().center() - m_rect.center() + m_animItr * ( m_position - scene()->sceneRect().center() + m_rect.center()) / 2/ ITERATIONS );
107 if (m_animItr == ITERATIONS+1) {
108 m_sideB = false;
109 } else if (m_animItr >= 2*ITERATIONS ) {
110 killTimer(m_flipTimer);
111 m_animItr=0;
112 setZValue(0);
113 m_maxzvalue--;
115 m_animItr += 1;
121 void SakWidget::showDetails(bool show)
123 if (show == m_showingDetails) return;
124 else {
125 if (show) {
126 setZValue( ++m_maxzvalue );
128 m_showingDetails = show;
129 m_animItr = 0;
130 m_flipTimer = startTimer(25);
134 void SakWidget::setGeometry(const QRect& geom) {
135 prepareGeometryChange ();
137 setPos(geom.topLeft());
138 m_position = geom.topLeft();
139 m_scale = geom.width() / m_rect.width();
141 QTransform t=transform();
142 t.setMatrix(m_scale, t.m12(), t.m13(), t.m21(), m_scale, t.m23(), t.m31(), t.m32(), t.m33());
143 setTransform(t);
145 m_redrawCachedPixmap = m_redrawCachedPixmapB = true;
146 redrawPixmaps();
149 void SakWidget::keyPressEvent ( QKeyEvent * event ) {
150 if (event->key() == Qt::Key_Return && (event->modifiers() & Qt::ControlModifier) ) {
151 event->accept();
152 emit clicked(m_task.title);
153 } else if (event->key() == Qt::Key_Return && (event->modifiers() & Qt::ShiftModifier) ) {
154 event->accept();
155 emit clicked("");
156 } else if (event->key() == Qt::Key_Space) {
157 event->accept();
158 showDetails(!m_showingDetails);
163 void SakWidget::mousePressEvent(QGraphicsSceneMouseEvent* e)
165 m_lastPoint = e->screenPos();
168 void SakWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* )
170 emit clicked(m_task.title);
173 void SakWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent* )
175 if (!m_ismoving)
176 showDetails(!m_showingDetails);
177 else if (!m_showingDetails)
178 m_position = pos();
179 m_ismoving = false;
183 void SakWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
185 if (e->buttons() != Qt::NoButton && (m_lastPoint - e->screenPos()).manhattanLength() > 4) {
186 m_ismoving = true;
187 if (e->buttons() & Qt::LeftButton ) {
188 setPos(pos() + (e->screenPos() - m_lastPoint));
189 m_lastPoint = e->screenPos();
194 void SakWidget::drawBasicShape(QPixmap& basicShape)
196 basicShape.fill(QColor(0,0,0,0));
197 QPainter p(&basicShape);
198 QPen pen;
199 pen.setWidth(4);
200 pen.setColor(m_task.bgColor.darker(130));
201 p.setPen(pen);
202 p.setBrush(m_task.bgColor);
203 p.drawRoundRect(m_rect.adjusted(m_border,m_border, -m_border,-m_border), 25, 25 );
205 pen.setColor(m_task.fgColor);
206 p.setPen(pen);
209 void SakWidget::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget *)
211 QTime t;
212 t.start();
214 redrawPixmaps();
216 painter->save();
217 QRectF exposed = option->exposedRect.adjusted(-1,-1,1,1);
218 exposed &= QRectF(0,0, m_cachedPixmap.width(), m_cachedPixmap.height());
219 if (m_sideB)
220 painter->drawPixmap(exposed, m_cachedPixmapB, exposed);
221 else
222 painter->drawPixmap(exposed, m_cachedPixmap, exposed);
223 painter->restore();
227 void SakWidget::redrawPixmaps() {
228 if (m_redrawCachedPixmap) {
229 drawBasicShape(m_cachedPixmap);
230 QPainter p(&m_cachedPixmap);
231 p.setRenderHints(QPainter::Antialiasing, true);
232 QPen pen;
233 pen.setColor(m_task.fgColor);
234 p.setPen(pen);
235 if (!m_ic.isNull()) {
236 p.drawPixmap((int)(m_rect.width() - m_ic.width())/2, (int)(m_rect.height() - m_ic.height())/2, m_ic);
237 } else if ( m_text && !m_sideB) {
238 QFont f = p.font();
239 QFontMetricsF metrix(f);
240 f.setPixelSize( (int)m_rect.width() / m_task.title.count() );
241 p.setFont(f);
242 p.drawText(m_rect, Qt::AlignCenter, m_task.title);
245 // draw completion
246 QPointF dateInfoTopLeft(m_rect.width() - 100, m_rect.height() - 100);
247 if (m_task.dueDate.isValid()) {
248 p.setBrush(Qt::red);
249 int days = QDate::currentDate().daysTo(m_task.dueDate);
250 p.setPen(Qt::NoPen);
251 if (days <= 0) {
252 p.setBrush(Qt::red);
253 } else {
254 QConicalGradient g(dateInfoTopLeft + QPointF(32,32), 90);
255 g.setColorAt(0.0, Qt::red);
256 g.setColorAt(1.0, Qt::green);
257 p.setBrush(g);
258 days = qMin(30, days);
259 days *= 12;
262 p.drawPie(QRectF(dateInfoTopLeft, QSizeF(64, 64)), 90*16, -(360 - days)*16);
263 p.drawPixmap(dateInfoTopLeft, QPixmap(":/images/hourglass.png"));
265 if (m_task.estimatedHours) {
266 p.setPen(Qt::NoPen);
267 QLinearGradient g(QPointF(dateInfoTopLeft.x(),0), QPointF(dateInfoTopLeft.x()+64,0));
268 g.setColorAt(0.0, Qt::red);
269 g.setColorAt(1.0, Qt::green);
270 p.setBrush(Qt::gray);
271 QRectF infoRect(dateInfoTopLeft + QPointF(0,66), QSizeF(64, 8));
272 p.drawRoundedRect(infoRect,3,3);
273 p.setBrush(g);
274 double percentage = ((double)m_task.totHours / (double)m_task.estimatedHours) * 64.0;
275 p.drawRoundedRect(infoRect.adjusted(0,0,percentage-64,0), 3,3);
278 m_redrawCachedPixmap = false;
281 if (m_redrawCachedPixmapB) {
282 drawBasicShape(m_cachedPixmapB);
283 QPainter p(&m_cachedPixmapB);
284 p.setRenderHints(QPainter::Antialiasing, true);
285 QPen pen;
286 pen.setColor(m_task.fgColor);
287 p.setPen(pen);
288 if (!m_ic.isNull()) {
289 p.drawPixmap(QPoint(25, (int)m_rect.height() - 120), m_ic.scaled(100, 100, Qt::KeepAspectRatio));
291 QTransform t;
292 t.translate( m_rect.width() -10 , 10);
293 t.rotate( -180 , Qt::YAxis);
294 p.setTransform(t);
295 m_text->drawContents(&p);
296 m_redrawCachedPixmapB = false;