limit subtask list
[Sak.git] / sakwidget.cpp
blobd1cd0ed4e0dd66beeb4972e751806bacf9acab48
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 if (e->button() != Qt::LeftButton)
166 return;
167 m_lastPoint = e->screenPos();
170 void SakWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e)
172 if (e->button() != Qt::LeftButton)
173 return;
174 emit clicked(m_task.title);
177 void SakWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent* e)
179 if (e->button() != Qt::LeftButton)
180 return;
181 if (!m_ismoving)
182 showDetails(!m_showingDetails);
183 else if (!m_showingDetails)
184 m_position = pos();
185 m_ismoving = false;
189 void SakWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
191 if (e->button() != Qt::LeftButton)
192 return;
193 if (e->buttons() != Qt::NoButton && (m_lastPoint - e->screenPos()).manhattanLength() > 4) {
194 m_ismoving = true;
195 if (e->buttons() & Qt::LeftButton ) {
196 setPos(pos() + (e->screenPos() - m_lastPoint));
197 m_lastPoint = e->screenPos();
202 void SakWidget::drawBasicShape(QPixmap& basicShape)
204 basicShape.fill(QColor(0,0,0,0));
205 QPainter p(&basicShape);
206 QPen pen;
207 pen.setWidth(4);
208 pen.setColor(m_task.bgColor.darker(130));
209 p.setPen(pen);
210 p.setBrush(m_task.bgColor);
211 p.drawRoundRect(m_rect.adjusted(m_border,m_border, -m_border,-m_border), 25, 25 );
213 pen.setColor(m_task.fgColor);
214 p.setPen(pen);
217 void SakWidget::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget *)
219 QTime t;
220 t.start();
222 redrawPixmaps();
224 painter->save();
225 QRectF exposed = option->exposedRect.adjusted(-1,-1,1,1);
226 exposed &= QRectF(0,0, m_cachedPixmap.width(), m_cachedPixmap.height());
227 if (m_sideB)
228 painter->drawPixmap(exposed, m_cachedPixmapB, exposed);
229 else
230 painter->drawPixmap(exposed, m_cachedPixmap, exposed);
231 painter->restore();
235 void SakWidget::redrawPixmaps() {
236 if (m_redrawCachedPixmap) {
237 drawBasicShape(m_cachedPixmap);
238 QPainter p(&m_cachedPixmap);
239 p.setRenderHints(QPainter::Antialiasing, true);
240 QPen pen;
241 pen.setColor(m_task.fgColor);
242 p.setPen(pen);
243 if (!m_ic.isNull()) {
244 p.drawPixmap((int)(m_rect.width() - m_ic.width())/2, (int)(m_rect.height() - m_ic.height())/2, m_ic);
245 } else if ( m_text && !m_sideB) {
246 QFont f = p.font();
247 QFontMetricsF metrix(f);
248 f.setPixelSize( (int)m_rect.width() / m_task.title.count() );
249 p.setFont(f);
250 p.drawText(m_rect, Qt::AlignCenter, m_task.title);
253 // draw completion
254 QPointF dateInfoTopLeft(m_rect.width() - 100, m_rect.height() - 100);
255 if (m_task.dueDate.isValid()) {
256 p.setBrush(Qt::red);
257 int days = QDate::currentDate().daysTo(m_task.dueDate);
258 p.setPen(Qt::NoPen);
259 if (days <= 0) {
260 p.setBrush(Qt::red);
261 } else {
262 QConicalGradient g(dateInfoTopLeft + QPointF(32,32), 90);
263 g.setColorAt(0.0, Qt::red);
264 g.setColorAt(1.0, Qt::green);
265 p.setBrush(g);
266 days = qMin(30, days);
267 days *= 12;
270 p.drawPie(QRectF(dateInfoTopLeft, QSizeF(64, 64)), 90*16, -(360 - days)*16);
271 p.drawPixmap(dateInfoTopLeft, QPixmap(":/images/hourglass.png"));
273 if (m_task.estimatedHours) {
274 p.setPen(Qt::NoPen);
275 QLinearGradient g(QPointF(dateInfoTopLeft.x(),0), QPointF(dateInfoTopLeft.x()+64,0));
276 g.setColorAt(1.0, Qt::red);
277 g.setColorAt(0.0, Qt::green);
278 p.setBrush(Qt::gray);
279 QRectF infoRect(dateInfoTopLeft + QPointF(0,66), QSizeF(64, 8));
280 p.drawRoundedRect(infoRect,3,3);
281 p.setBrush(g);
282 double percentage = ((double)m_task.totHours / (double)m_task.estimatedHours) * 64.0;
283 p.drawRoundedRect(infoRect.adjusted(0,0,percentage-64,0), 3,3);
286 m_redrawCachedPixmap = false;
289 if (m_redrawCachedPixmapB) {
290 drawBasicShape(m_cachedPixmapB);
291 QPainter p(&m_cachedPixmapB);
292 p.setRenderHints(QPainter::Antialiasing, true);
293 QPen pen;
294 pen.setColor(m_task.fgColor);
295 p.setPen(pen);
296 if (!m_ic.isNull()) {
297 p.drawPixmap(QPoint(25, (int)m_rect.height() - 120), m_ic.scaled(100, 100, Qt::KeepAspectRatio));
299 QTransform t;
300 t.translate( m_rect.width() -10 , 10);
301 t.rotate( -180 , Qt::YAxis);
302 p.setTransform(t);
303 m_text->drawContents(&p);
304 m_redrawCachedPixmapB = false;