fixed: icons overlapped
[toast/confclerk.git] / src / mvc / delegate.cpp
1 #include "delegate.h"
2 #include "eventmodel.h"
3
4 #include <QDebug>
5 #include <QPainter>
6
7 const int RADIUS = 10;
8 const int SPACER = 15;
9
10 Delegate::Delegate(QTreeView *aParent)
11     : QItemDelegate(aParent)
12     , mViewPtr(aParent)
13 {
14     mControls.clear();
15     defineControls();
16 }
17
18 Delegate::~Delegate()
19 {
20     QListIterator<ControlId> i(mControls.keys());
21     while (i.hasNext())
22     {
23         delete mControls[i.next()]->image();
24     }
25 }
26
27 void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
28 {
29     if(!mViewPtr)
30         return;
31
32     painter->save();
33
34     QColor bkgrColor = Qt::cyan;
35     QPen borderPen(bkgrColor.darker());
36     if(hasParent(index))
37     {
38         if(isLast(index))
39         {
40             QLinearGradient lastGradient(option.rect.topLeft(), option.rect.bottomLeft());
41             lastGradient.setColorAt(0.0, Qt::white);
42             lastGradient.setColorAt(0.5, bkgrColor);
43             lastGradient.setColorAt(1.0, Qt::white);
44
45             QPainterPath endPath;
46             endPath.moveTo(option.rect.topLeft());
47             endPath.lineTo(option.rect.bottomLeft()-QPoint(0, RADIUS));
48             endPath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 180, 90);
49             endPath.lineTo(option.rect.bottomRight()-QPoint(RADIUS, 0));
50             endPath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, 90);
51             endPath.lineTo(option.rect.topRight());
52
53             //painter->setBrush( bkgrColor );
54             painter->setBrush(lastGradient);
55             painter->setPen(borderPen);
56             painter->drawPath(endPath);
57
58             painter->setFont(option.font);
59         }
60         else // middle elements
61         {
62
63             QLinearGradient middleGradient(option.rect.topLeft(), option.rect.bottomLeft());
64             middleGradient.setColorAt(0.0, Qt::white);
65             middleGradient.setColorAt(0.25, bkgrColor);
66             middleGradient.setColorAt(0.5, Qt::white);
67             middleGradient.setColorAt(0.75, bkgrColor);
68             middleGradient.setColorAt(1.0, Qt::white);
69
70             //painter->setBrush( bkgrColor );
71             painter->setBrush(middleGradient);
72             painter->setPen(Qt::NoPen);
73             painter->drawRect(option.rect);
74
75             painter->setPen(borderPen);
76             // vertical lines
77             painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());
78             painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
79             // horizontal lines
80             painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
81
82             painter->setFont(option.font);
83         }
84
85         // draw Controls
86         // favourite
87         if(static_cast<Event*>(index.internalPointer())->isFavourite())
88             painter->drawImage(mControls[FavouriteControlOn]->drawPoint(option.rect),*mControls[FavouriteControlOn]->image());
89         else
90             painter->drawImage(mControls[FavouriteControlOff]->drawPoint(option.rect),*mControls[FavouriteControlOff]->image());
91         // alarm
92         if(static_cast<Event*>(index.internalPointer())->hasAlarm())
93             painter->drawImage(mControls[AlarmControlOn]->drawPoint(option.rect),*mControls[AlarmControlOn]->image());
94         else
95             painter->drawImage(mControls[AlarmControlOff]->drawPoint(option.rect),*mControls[AlarmControlOff]->image());
96         // map
97         painter->drawImage(mControls[MapControl]->drawPoint(option.rect),*mControls[MapControl]->image());
98     }
99     else // doesn't have parent - time-groups' elements (top items)
100     {
101         QLinearGradient titleGradient(option.rect.topLeft(), option.rect.topRight());
102         //titleGradient.setColorAt(0.0, Qt::white);
103         titleGradient.setColorAt(0.0, bkgrColor);
104         titleGradient.setColorAt(0.5, Qt::white);
105         titleGradient.setColorAt(1.0, bkgrColor);
106
107         QPainterPath titlePath;
108         if(isExpanded(index))
109         {
110             titlePath.moveTo(option.rect.bottomLeft());
111             titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
112             titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
113             titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
114             titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
115             titlePath.lineTo(option.rect.bottomRight());
116             titlePath.closeSubpath();
117         }
118         else
119         {
120             titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
121             titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
122             titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
123             titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
124             titlePath.lineTo(option.rect.bottomRight()-QPoint(0, RADIUS));
125             titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 0, -90);
126             titlePath.lineTo(option.rect.bottomLeft()+QPoint(RADIUS, 0));
127             titlePath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, -90);      
128             titlePath.closeSubpath();
129         }
130
131         painter->setBrush(titleGradient);
132         painter->setPen(borderPen);
133         painter->drawPath(titlePath);
134
135         QFont font = option.font;
136         font.setBold(true);
137         painter->setFont(font);
138
139         // draw icons 
140         QPoint drawPoint =
141             option.rect.topRight()
142             - QPoint(
143                     SPACER + mControls[FavouriteControlOn]->image()->width(),
144                     - option.rect.height()/2 + mControls[FavouriteControlOn]->image()->height()/2);
145         painter->drawImage(drawPoint,*mControls[FavouriteControlOn]->image());
146         painter->drawText(drawPoint+QPoint(mControls[FavouriteControlOn]->image()->width()+2, option.rect.height()/2),
147                 QString::number(numberOfFavourities(index)));
148         drawPoint.setX(drawPoint.x() - SPACER - mControls[FavouriteControlOn]->image()->width());
149         painter->drawImage(drawPoint,*mControls[AlarmControlOn]->image());
150         painter->drawText(drawPoint+QPoint(mControls[FavouriteControlOn]->image()->width()+2, option.rect.height()/2),
151                 QString::number(numberOfAlarms(index)));
152         // draw texts
153         drawPoint.setX(drawPoint.x() - SPACER -mControls[AlarmControlOn]->image()->width() - 35);
154         drawPoint.setY(drawPoint.y() + option.rect.height()/2);
155         painter->drawText(drawPoint,QString("Events: ") + QString::number(index.model()->rowCount(index)));
156     }
157
158     //// HIGHLIGHTING SELECTED ITEM
159     //if (option.state & QStyle::State_Selected)
160         //painter->fillRect(option.rect, option.palette.highlight());
161
162     // draw title
163     QPointF titlePointF(option.rect.x()+SPACER,option.rect.y()+option.rect.height()-10);
164     QString text;
165     if(index.parent().isValid()) // event
166         text = qVariantValue<QString>(index.data()) + ": " + static_cast<Event*>(index.internalPointer())->title();
167     else // group
168         text = qVariantValue<QString>(index.data());
169     painter->drawText(titlePointF,text);
170
171     painter->restore();
172 }
173
174 QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
175 {
176     Q_UNUSED(option)
177
178     if (index.internalId() == 0) // time group
179     {
180         return QSize(30,30);
181     }
182     else // event
183     {
184         return QSize(100,100);
185     }
186 }
187
188 bool Delegate::hasParent( const QModelIndex &index ) const
189 {
190     if( index.parent().isValid() )
191         return true;
192     else
193         return false;
194 }
195   
196 bool Delegate::isLast( const QModelIndex &index ) const
197 {
198     if(!hasParent(index))
199         return false; // what should be returned here?
200
201     if(index.row() >= (index.model()->rowCount(index.parent())-1))
202         return true;
203     else
204         return false;
205 }
206
207 bool Delegate::isExpanded( const QModelIndex &index ) const
208 {
209     if( !mViewPtr )
210         return false;
211     else
212         return mViewPtr->isExpanded( index );
213 }
214
215 Delegate::ControlId Delegate::whichControlClicked(const QModelIndex &aIndex, const QPoint &aPoint) const
216 {
217     if(!hasParent(aIndex)) // time-group item (root item)
218         return ControlNone;
219
220     QListIterator<ControlId> i(mControls.keys());
221     while (i.hasNext())
222     {
223         ControlId id = i.next();
224         if(mControls[id]->drawRect(static_cast<QTreeView*>(parent())->visualRect(aIndex)).contains(aPoint))
225             return id;
226     }
227
228     return ControlNone;
229 }
230
231 void Delegate::defineControls()
232 {
233     Control *control;
234     QPoint p(0,0);
235     // FAVOURITE ICONs
236     // on
237     control = new Control(FavouriteControlOn,QString(":icons/favourite-on.png"));
238     p = QPoint(0,SPACER);
239     p.setX(p.x()-control->image()->width()-SPACER);
240     control->setDrawPoint(p);
241     mControls.insert(FavouriteControlOn,control);
242     // off
243     control = new Control(FavouriteControlOff,QString(":icons/favourite-off.png"));
244     p = QPoint(0,SPACER);
245     p.setX(p.x()-control->image()->width()-SPACER);
246     control->setDrawPoint(p);
247     mControls.insert(FavouriteControlOff,control);
248
249     // ALARM ICONs
250     // on
251     control = new Control(AlarmControlOn,QString(":icons/alarm-on.png"));
252     p = mControls[FavouriteControlOn]->drawPoint();
253     p.setX(p.x()-control->image()->width()-SPACER);
254     control->setDrawPoint(p);
255     mControls.insert(AlarmControlOn,control);
256     // off
257     control = new Control(AlarmControlOff,QString(":icons/alarm-off.png"));
258     p = mControls[FavouriteControlOff]->drawPoint();
259     p.setX(p.x()-control->image()->width()-SPACER);
260     control->setDrawPoint(p);
261     mControls.insert(AlarmControlOff,control);
262
263     // MAP ICON
264     control = new Control(MapControl,QString(":icons/compass.png"));
265     p = mControls[AlarmControlOn]->drawPoint();
266     p.setX(p.x()-control->image()->width()-SPACER);
267     control->setDrawPoint(p);
268     mControls.insert(MapControl,control);
269 }
270
271 bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const
272 {
273     if( (aPoint.x()>=aRect.left() && aPoint.x()<=aRect.right()) && (aPoint.y()>=aRect.top() && aPoint.y()<=aRect.bottom()) )
274         return true;
275
276     return false;
277 }
278
279 int Delegate::numberOfFavourities(const QModelIndex &index) const
280 {
281     if(index.parent().isValid()) // it's event, not time-group
282         return 0;
283
284     int nrofFavs = 0;
285     for(int i=0; i<index.model()->rowCount(index); i++)
286         if(static_cast<Event*>(index.child(i,0).internalPointer())->isFavourite())
287             nrofFavs++;
288
289     return nrofFavs;
290 }
291
292 int Delegate::numberOfAlarms(const QModelIndex &index) const
293 {
294     if(index.parent().isValid()) // it's event, not time-group
295         return 0;
296
297     int nrofAlarms = 0;
298     for(int i=0; i<index.model()->rowCount(index); i++)
299         if(static_cast<Event*>(index.child(i,0).internalPointer())->hasAlarm())
300             nrofAlarms++;
301
302     return nrofAlarms;
303 }
304