source: src/mvc/delegate.cpp @ 8cb5c4f

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

some 'delegate' drawing optimizations

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