source: src/mvc/delegate.cpp @ d7986a6

qt5
Last change on this file since d7986a6 was d7986a6, checked in by pavelpa <pavelpa@…>, 12 years ago

gradient for treeview items

  • Property mode set to 100644
File size: 14.6 KB
Line 
1#include "delegate.h"
2#include "eventmodel.h"
3#include <track.h>
4
5#include <QDebug>
6#include <QPainter>
7
8const int RADIUS = 10;
9const int SPACER = 10;
10
11const double scaleFactor1 = 0.4;
12const double scaleFactor2 = 0.8;
13
14Delegate::Delegate(QTreeView *aParent)
15    : QItemDelegate(aParent)
16    , mViewPtr(aParent)
17{
18    mControls.clear();
19    defineControls();
20}
21
22Delegate::~Delegate()
23{
24    QListIterator<ControlId> i(mControls.keys());
25    while (i.hasNext())
26    {
27        delete mControls[i.next()]->image();
28    }
29}
30
31void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
32{
33    if(!mViewPtr)
34        return;
35
36    painter->save();
37    QColor bkgrColor = Qt::cyan;
38    //QColor bkgrColor = QColor(0xAA,0xAA,0xAA);
39    QColor conflictColor = Qt::yellow;
40
41    QPen borderPen(bkgrColor.darker());
42    if(hasParent(index))
43    {
44        int aux = option.rect.height() - mControls[FavouriteControlOn]->drawPoint().y() - mControls[FavouriteControlOn]->image()->height();
45        // font SMALL
46        QFont fontSmall = option.font;
47        fontSmall.setBold(false);
48        fontSmall.setPixelSize(aux*0.2);
49        QFontMetrics fmSmall(fontSmall);
50        // font SMALL bold
51        QFont fontSmallB = fontSmall;
52        fontSmallB.setBold(true);
53        QFontMetrics fmSmallB(fontSmallB);
54
55        // font BIG
56        QFont fontBig = option.font;
57        fontBig.setBold(false);
58        fontBig.setPixelSize(aux*0.33);
59        QFontMetrics fmBig(fontBig);
60        // font BIG bold
61        QFont fontBigB = fontBig;
62        fontBigB.setBold(true);
63        QFontMetrics fmBigB(fontBigB);
64
65        //int spacer = (fmSmall.boundingRect("999").width() < SPACER) ? SPACER : fmSmall.boundingRect("999").width();
66
67        //Time conflicts are colored differently
68        if(static_cast<Event*>(index.internalPointer())->hasTimeConflict())
69            bkgrColor = conflictColor;
70
71        QLinearGradient itemGradient(option.rect.topLeft(), option.rect.bottomLeft());
72        itemGradient.setColorAt(0.0, Qt::white);
73        itemGradient.setColorAt(0.25, bkgrColor);
74        itemGradient.setColorAt(0.5, bkgrColor);
75        itemGradient.setColorAt(0.75, bkgrColor);
76        itemGradient.setColorAt(1.0, Qt::white);
77
78        if(isLast(index))
79        {
80            QPainterPath endPath;
81            endPath.moveTo(option.rect.topLeft());
82            endPath.lineTo(option.rect.bottomLeft()-QPoint(0, RADIUS));
83            endPath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 180, 90);
84            endPath.lineTo(option.rect.bottomRight()-QPoint(RADIUS, 0));
85            endPath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, 90);
86            endPath.lineTo(option.rect.topRight());
87
88            //painter->setBrush( bkgrColor );
89            painter->setBrush(itemGradient);
90            painter->setPen(borderPen);
91            painter->drawPath(endPath);
92
93            painter->setFont(option.font);
94        }
95        else // middle elements
96        {
97            //painter->setBrush( bkgrColor );
98            painter->setBrush(itemGradient);
99            painter->setPen(Qt::NoPen);
100            painter->drawRect(option.rect);
101
102            painter->setPen(borderPen);
103            // vertical lines
104            painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());
105            painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
106            // horizontal lines
107            painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
108
109            painter->setFont(option.font);
110        }
111
112        // draw Controls
113        // favourite
114        if(static_cast<Event*>(index.internalPointer())->isFavourite())
115            painter->drawImage(mControls[FavouriteControlOn]->drawPoint(option.rect),*mControls[FavouriteControlOn]->image());
116        else
117            painter->drawImage(mControls[FavouriteControlOff]->drawPoint(option.rect),*mControls[FavouriteControlOff]->image());
118#ifdef MAEMO
119        // alarm
120        if(static_cast<Event*>(index.internalPointer())->hasAlarm())
121            painter->drawImage(mControls[AlarmControlOn]->drawPoint(option.rect),*mControls[AlarmControlOn]->image());
122        else
123            painter->drawImage(mControls[AlarmControlOff]->drawPoint(option.rect),*mControls[AlarmControlOff]->image());
124#endif
125        // map
126        painter->drawImage(mControls[MapControl]->drawPoint(option.rect),*mControls[MapControl]->image());
127        // Time conflict
128        if(static_cast<Event*>(index.internalPointer())->hasTimeConflict())
129            painter->drawImage(mControls[WarningControl]->drawPoint(option.rect),*mControls[WarningControl]->image());
130
131        // draw texts
132        Event *event = static_cast<Event*>(index.internalPointer());
133        QPointF titlePointF(mControls[FavouriteControlOn]->drawPoint(option.rect));
134        titlePointF.setX(option.rect.x()+SPACER);
135        titlePointF.setY(titlePointF.y()+mControls[FavouriteControlOn]->image()->height());
136        QTime start = event->start().time();
137        painter->setFont(fontBig);
138        painter->drawText(titlePointF,start.toString("hh:mm") + "-" + start.addSecs(event->duration()).toString("hh:mm") + ", " + event->room());
139        // title
140        titlePointF.setY(titlePointF.y()+fmBig.height()-fmBig.descent());
141        painter->setFont(fontBigB);
142        QString title = event->title();
143        if(fmBigB.boundingRect(title).width() > (option.rect.width()-2*SPACER)) // the title won't fit the screen
144        {
145            // chop words from the end
146            while( (fmBigB.boundingRect(title + "...").width() > (option.rect.width()-2*SPACER)) && !title.isEmpty())
147            {
148                title.chop(1);
149                // chop characters one-by-one from the end
150                while( (!title.at(title.length()-1).isSpace()) && !title.isEmpty())
151                {
152                    title.chop(1);
153                }
154            }
155            title += "...";
156        }
157        painter->drawText(titlePointF,title);
158        // persons
159        titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent());
160        painter->setFont(fontSmall);
161        painter->drawText(titlePointF,"Presenter(s): " + event->persons().join(" and "));
162        // track
163        titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent());
164        painter->drawText(titlePointF,"Track: " + Track::retrieveTrackName(event->trackId()));
165    }
166    else // doesn't have parent - time-groups' elements (top items)
167    {
168        QFont fontSmall = option.font;
169        fontSmall.setBold(true);
170        fontSmall.setPixelSize(option.rect.height()*scaleFactor1);
171        QFontMetrics fmSmall(fontSmall);
172
173        QFont fontBig = option.font;
174        fontBig.setBold(true);
175        fontBig.setPixelSize(option.rect.height()*scaleFactor2);
176        QFontMetrics fmBig(fontBig);
177
178        int spacer = (fmSmall.boundingRect("999").width() < SPACER) ? SPACER : fmSmall.boundingRect("999").width();
179
180        QLinearGradient titleGradient(option.rect.topLeft(), option.rect.topRight());
181        //titleGradient.setColorAt(0.0, Qt::white);
182        titleGradient.setColorAt(0.0, bkgrColor);
183        titleGradient.setColorAt(0.5, Qt::white);
184        titleGradient.setColorAt(1.0, bkgrColor);
185
186        QPainterPath titlePath;
187        if(isExpanded(index))
188        {
189            titlePath.moveTo(option.rect.bottomLeft());
190            titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
191            titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
192            titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
193            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
194            titlePath.lineTo(option.rect.bottomRight());
195            titlePath.closeSubpath();
196        }
197        else
198        {
199            titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS));
200            titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90);
201            titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0));
202            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90);
203            titlePath.lineTo(option.rect.bottomRight()-QPoint(0, RADIUS));
204            titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 0, -90);
205            titlePath.lineTo(option.rect.bottomLeft()+QPoint(RADIUS, 0));
206            titlePath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, -90);     
207            titlePath.closeSubpath();
208        }
209
210        painter->setBrush(titleGradient);
211        painter->setPen(borderPen);
212        painter->drawPath(titlePath);
213
214        // draw icons
215        painter->setFont(fontSmall);
216        QImage *image = mControls[FavouriteControlOn]->image();
217        QPoint drawPoint =
218            option.rect.topRight()
219            - QPoint(
220                    spacer + image->width(),
221                    - option.rect.height()/2 + image->height()/2);
222        painter->drawImage(drawPoint,*image);
223        painter->drawText(drawPoint+QPoint(image->width()+2, image->height() - 2),
224                QString::number(numberOfFavourities(index)));
225#ifdef MAEMO
226        drawPoint.setX(drawPoint.x() - spacer - image->width());
227        painter->drawImage(drawPoint,*mControls[AlarmControlOn]->image());
228        painter->drawText(drawPoint+QPoint(image->width()+2, image->height() - 2),
229                QString::number(numberOfAlarms(index)));
230#endif
231        // draw texts
232        QString numEvents = QString::number(index.model()->rowCount(index)).append("/");
233        drawPoint.setX(drawPoint.x() - spacer - fmSmall.boundingRect(numEvents).width());
234        drawPoint.setY(drawPoint.y()+image->height() - 2);
235        painter->drawText(drawPoint,numEvents);
236
237        QPointF titlePointF = QPoint(
238                option.rect.x()+SPACER,
239                option.rect.y()+option.rect.height()-fmBig.descent());
240        painter->setFont(fontBig);
241
242        painter->drawText(titlePointF,qVariantValue<QString>(index.data()));
243    }
244
245    //// HIGHLIGHTING SELECTED ITEM
246    //if (option.state & QStyle::State_Selected)
247        //painter->fillRect(option.rect, option.palette.highlight());
248
249    painter->restore();
250}
251
252QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
253{
254    Q_UNUSED(option)
255
256    if (index.internalId() == 0) // time group
257    {
258        return QSize(40,40);
259    }
260    else // event
261    {
262        return QSize(100,100);
263    }
264}
265
266bool Delegate::hasParent( const QModelIndex &index ) const
267{
268    if( index.parent().isValid() )
269        return true;
270    else
271        return false;
272}
273 
274bool Delegate::isLast( const QModelIndex &index ) const
275{
276    if(!hasParent(index))
277        return false; // what should be returned here?
278
279    if(index.row() >= (index.model()->rowCount(index.parent())-1))
280        return true;
281    else
282        return false;
283}
284
285bool Delegate::isExpanded( const QModelIndex &index ) const
286{
287    if( !mViewPtr )
288        return false;
289    else
290        return mViewPtr->isExpanded( index );
291}
292
293Delegate::ControlId Delegate::whichControlClicked(const QModelIndex &aIndex, const QPoint &aPoint) const
294{
295    if(!hasParent(aIndex)) // time-group item (root item)
296        return ControlNone;
297
298    QListIterator<ControlId> i(mControls.keys());
299    while (i.hasNext())
300    {
301        ControlId id = i.next();
302        if(mControls[id]->drawRect(static_cast<QTreeView*>(parent())->visualRect(aIndex)).contains(aPoint))
303        {
304            if(id == WarningControl)
305            {
306                if(static_cast<Event*>(aIndex.internalPointer())->hasTimeConflict())
307                    return id;
308            }
309            else
310                return id;
311        }
312    }
313
314    return ControlNone;
315}
316
317void Delegate::defineControls()
318{
319    Control *control;
320    QPoint p(0,0);
321    // FAVOURITE ICONs
322    // on
323    control = new Control(FavouriteControlOn,QString(":icons/favourite-onBig.png"));
324    p = QPoint(0,SPACER);
325    p.setX(p.x()-control->image()->width()-SPACER);
326    control->setDrawPoint(p);
327    mControls.insert(FavouriteControlOn,control);
328    // off
329    control = new Control(FavouriteControlOff,QString(":icons/favourite-offBig.png"));
330    p = QPoint(0,SPACER);
331    p.setX(p.x()-control->image()->width()-SPACER);
332    control->setDrawPoint(p);
333    mControls.insert(FavouriteControlOff,control);
334
335#ifdef MAEMO
336    // ALARM ICONs
337    // on
338    control = new Control(AlarmControlOn,QString(":icons/alarm-onBig.png"));
339    p = mControls[FavouriteControlOn]->drawPoint();
340    p.setX(p.x()-control->image()->width()-SPACER);
341    control->setDrawPoint(p);
342    mControls.insert(AlarmControlOn,control);
343    // off
344    control = new Control(AlarmControlOff,QString(":icons/alarm-offBig.png"));
345    p = mControls[FavouriteControlOff]->drawPoint();
346    p.setX(p.x()-control->image()->width()-SPACER);
347    control->setDrawPoint(p);
348    mControls.insert(AlarmControlOff,control);
349
350    // MAP ICON
351    control = new Control(MapControl,QString(":icons/compassBig.png"));
352    p = mControls[AlarmControlOn]->drawPoint();
353    p.setX(p.x()-control->image()->width()-SPACER);
354    control->setDrawPoint(p);
355    mControls.insert(MapControl,control);
356#else
357    // MAP ICON
358    control = new Control(MapControl,QString(":icons/compassBig.png"));
359    p = mControls[FavouriteControlOn]->drawPoint();
360    p.setX(p.x()-control->image()->width()-SPACER);
361    control->setDrawPoint(p);
362    mControls.insert(MapControl,control);
363#endif
364
365    // WARNING ICON
366    control = new Control(WarningControl,QString(":icons/exclamation.png"));
367    p = mControls[MapControl]->drawPoint();
368    p.setX(p.x()-control->image()->width()-SPACER);
369    control->setDrawPoint(p);
370    mControls.insert(WarningControl,control);
371}
372
373bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const
374{
375    if( (aPoint.x()>=aRect.left() && aPoint.x()<=aRect.right()) && (aPoint.y()>=aRect.top() && aPoint.y()<=aRect.bottom()) )
376        return true;
377
378    return false;
379}
380
381int Delegate::numberOfFavourities(const QModelIndex &index) const
382{
383    if(index.parent().isValid()) // it's event, not time-group
384        return 0;
385
386    int nrofFavs = 0;
387    for(int i=0; i<index.model()->rowCount(index); i++)
388        if(static_cast<Event*>(index.child(i,0).internalPointer())->isFavourite())
389            nrofFavs++;
390
391    return nrofFavs;
392}
393
394int Delegate::numberOfAlarms(const QModelIndex &index) const
395{
396    if(index.parent().isValid()) // it's event, not time-group
397        return 0;
398
399    int nrofAlarms = 0;
400    for(int i=0; i<index.model()->rowCount(index); i++)
401        if(static_cast<Event*>(index.child(i,0).internalPointer())->hasAlarm())
402            nrofAlarms++;
403
404    return nrofAlarms;
405}
406
Note: See TracBrowser for help on using the repository browser.