source: src/mvc/delegate.cpp @ 3329d39

qt5
Last change on this file since 3329d39 was ca90cb1, checked in by uzakmat <uzakmat@…>, 12 years ago

A header with the proper copyright/lincence statement was added into each source/header file.

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