source: src/mvc/delegate.cpp @ e7340e1

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

Conference map

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