X-Git-Url: https://git.toastfreeware.priv.at/toast/confclerk.git/blobdiff_plain/b6cd05cc3942ee4b7eff3b6de19eaa780e5f3174..102d186c946286839819bc3623fdddfcf5216877:/src/mvc/delegate.cpp diff --git a/src/mvc/delegate.cpp b/src/mvc/delegate.cpp index d085db9..ae44cf6 100644 --- a/src/mvc/delegate.cpp +++ b/src/mvc/delegate.cpp @@ -1,11 +1,35 @@ +/* + * Copyright (C) 2010 Ixonos Plc. + * Copyright (C) 2011-2017 Philipp Spitzer, gregor herrmann, Stefan Stahl + * + * This file is part of ConfClerk. + * + * ConfClerk is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 2 of the License, or (at your option) + * any later version. + * + * ConfClerk is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * ConfClerk. If not, see . + */ #include "delegate.h" #include "eventmodel.h" +#include "track.h" #include #include -const int RADIUS = 10; -const int SPACER = RADIUS; +#include "room.h" + +const int SPACER = 10; + +const double scaleFactor1 = 0.4; +const double scaleFactor2 = 0.8; Delegate::Delegate(QTreeView *aParent) : QItemDelegate(aParent) @@ -26,129 +50,194 @@ Delegate::~Delegate() void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - if(!mViewPtr) + if (!mViewPtr) return; painter->save(); - QColor bkgrColor = Qt::cyan; - QPen borderPen(bkgrColor.darker()); + QColor textColor = option.palette.color(QPalette::Text); + if(hasParent(index)) { - if(isLast(index)) - { - QLinearGradient lastGradient(option.rect.topLeft(), option.rect.bottomLeft()); - lastGradient.setColorAt(0.0, Qt::white); - lastGradient.setColorAt(0.5, bkgrColor); - lastGradient.setColorAt(1.0, Qt::white); - - QPainterPath endPath; - endPath.moveTo(option.rect.topLeft()); - endPath.lineTo(option.rect.bottomLeft()-QPoint(0, RADIUS)); - endPath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 180, 90); - endPath.lineTo(option.rect.bottomRight()-QPoint(RADIUS, 0)); - endPath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, 90); - endPath.lineTo(option.rect.topRight()); - - //painter->setBrush( bkgrColor ); - painter->setBrush(lastGradient); - painter->setPen(borderPen); - painter->drawPath(endPath); - - painter->setFont(option.font); + Event *event = static_cast(index.internalPointer()); + + // determine severity of conflict + Favourite eventTimeConflict = event->timeConflict(); // cache value as event->timeConflict is expensive + enum ConflictSeverity {csNone, csWeak, csStrong} conflictSeverity = csNone; + switch (event->favourite()) { + case Favourite_strong: + conflictSeverity = (eventTimeConflict == Favourite_strong) ? csStrong : csNone; + break; + case Favourite_weak: + conflictSeverity = (eventTimeConflict == Favourite_no) ? csNone : csWeak; + break; + case Favourite_no: + conflictSeverity = csNone; + break; } - else // middle elements - { - - QLinearGradient middleGradient(option.rect.topLeft(), option.rect.bottomLeft()); - middleGradient.setColorAt(0.0, Qt::white); - middleGradient.setColorAt(0.25, bkgrColor); - middleGradient.setColorAt(0.5, Qt::white); - middleGradient.setColorAt(0.75, bkgrColor); - middleGradient.setColorAt(1.0, Qt::white); - //painter->setBrush( bkgrColor ); - painter->setBrush(middleGradient); + // entry horizontal layout: + // * spacer (aka y position of image) + // * image + // * rest is text, which is 1 line of title with big letters and 2 lines of Presenter and Track + int aux = option.rect.height() - SPACER - mControls[FavouriteControlStrong]->image()->height(); + + // font SMALL + QFont fontSmall = option.font; + fontSmall.setBold(false); + fontSmall.setPixelSize(aux*0.2); + QFontMetrics fmSmall(fontSmall); + // font SMALL bold + QFont fontSmallB = fontSmall; + fontSmallB.setBold(true); + + // font BIG + QFont fontBig = option.font; + fontBig.setBold(false); + fontBig.setPixelSize(aux*0.33); + QFontMetrics fmBig(fontBig); + + // font BIG bold + QFont fontBigB = fontBig; + fontBigB.setBold(true); + QFontMetrics fmBigB(fontBigB); + + // background (in case of time conflicts) + if (conflictSeverity != csNone) { + painter->setBrush(conflictSeverity == csStrong ? Qt::yellow : QColor("lightyellow")); painter->setPen(Qt::NoPen); painter->drawRect(option.rect); + } - painter->setPen(borderPen); - // vertical lines - painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft()); - painter->drawLine(option.rect.topRight(), option.rect.bottomRight()); - // horizontal lines - painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); - - painter->setFont(option.font); + // background (without time conflicts) + else { + QStyleOption styleOption; + styleOption.rect = option.rect; + qApp->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &styleOption, painter, mViewPtr); } // draw Controls - // favourite - if(static_cast(index.internalPointer())->isFavourite()) - painter->drawImage(mControls[FavouriteControlOn]->drawPoint(option.rect),*mControls[FavouriteControlOn]->image()); - else - painter->drawImage(mControls[FavouriteControlOff]->drawPoint(option.rect),*mControls[FavouriteControlOff]->image()); - // alarm - if(static_cast(index.internalPointer())->hasAlarm()) - painter->drawImage(mControls[AlarmControlOn]->drawPoint(option.rect),*mControls[AlarmControlOn]->image()); - else - painter->drawImage(mControls[AlarmControlOff]->drawPoint(option.rect),*mControls[AlarmControlOff]->image()); - // map - painter->drawImage(mControls[MapControl]->drawPoint(option.rect),*mControls[MapControl]->image()); - } - else // doesn't have parent - time-groups' elements (top items) - { - QLinearGradient titleGradient(option.rect.topLeft(), option.rect.topRight()); - //titleGradient.setColorAt(0.0, Qt::white); - titleGradient.setColorAt(0.0, bkgrColor); - titleGradient.setColorAt(0.5, Qt::white); - titleGradient.setColorAt(1.0, bkgrColor); - - QPainterPath titlePath; - if(isExpanded(index)) - { - titlePath.moveTo(option.rect.bottomLeft()); - titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS)); - titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90); - titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0)); - titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90); - titlePath.lineTo(option.rect.bottomRight()); - titlePath.closeSubpath(); + foreach(Control* c, mControls.values()) { + c->setEnabled(false); } + switch (event->favourite()) { + case Favourite_strong: + mControls[FavouriteControlStrong]->paint(painter, option.rect); + break; + case Favourite_weak: + mControls[FavouriteControlWeak]->paint(painter, option.rect); + break; + case Favourite_no: + mControls[FavouriteControlNo]->paint(painter, option.rect); + break; + } + + if(event->hasAlarm()) + mControls[AlarmControlOn]->paint(painter, option.rect); else + mControls[AlarmControlOff]->paint(painter, option.rect); + + if(eventTimeConflict != Favourite_no) + mControls[WarningControl]->paint(painter, option.rect); + + // draw texts + // it starts just below the image + // ("position of text" is lower-left angle of the first letter, + // so the first line is actually at the same height as the image) + painter->setPen(QPen(conflictSeverity != csNone ? Qt::black : textColor)); + QPointF titlePointF(option.rect.x() + SPACER, + option.rect.y() + SPACER + mControls[FavouriteControlStrong]->image()->height()); + QTime start = event->start().time(); + painter->setFont(fontBig); + painter->drawText(titlePointF,start.toString("hh:mm") + "-" + start.addSecs(event->duration()).toString("hh:mm") + ", " + event->roomName()); + + // title + titlePointF.setY(titlePointF.y()+fmBig.height()-fmBig.descent()); + painter->setFont(fontBigB); + QString title = event->title(); + if(fmBigB.boundingRect(title).width() > (option.rect.width()-2*SPACER)) // the title won't fit the screen { - titlePath.lineTo(option.rect.topLeft()+QPoint(0, RADIUS)); - titlePath.arcTo(option.rect.left(), option.rect.top(), 2*RADIUS, 2*RADIUS, 180, -90); - titlePath.lineTo(option.rect.topRight()-QPoint(RADIUS, 0)); - titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.top(), 2*RADIUS, 2*RADIUS, 90, -90); - titlePath.lineTo(option.rect.bottomRight()-QPoint(0, RADIUS)); - titlePath.arcTo(option.rect.right()-2*RADIUS, option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 0, -90); - titlePath.lineTo(option.rect.bottomLeft()+QPoint(RADIUS, 0)); - titlePath.arcTo(option.rect.left(), option.rect.bottom()-2*RADIUS, 2*RADIUS, 2*RADIUS, 270, -90); - titlePath.closeSubpath(); + // chop words from the end + while( (fmBigB.boundingRect(title + "...").width() > (option.rect.width()-2*SPACER)) && !title.isEmpty()) + { + title.chop(1); + // chop characters one-by-one from the end + while( (!title.at(title.length()-1).isSpace()) && !title.isEmpty()) + { + title.chop(1); + } + } + title += "..."; } + painter->drawText(titlePointF,title); - painter->setBrush(titleGradient); - painter->setPen(borderPen); - painter->drawPath(titlePath); + // persons + titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent()); + painter->setFont(fontSmall); + QString presenterPrefix = event->persons().count() < 2 ? "Presenter" : "Presenters"; + painter->drawText(titlePointF,presenterPrefix + ": " + event->persons().join(" and ")); - QFont font = option.font; - font.setBold(true); - painter->setFont(font); + // track + titlePointF.setY(titlePointF.y()+fmSmall.height()-fmSmall.descent()); + painter->drawText(titlePointF,"Track: " + Track::retrieveTrackName(event->trackId())); } - //// HIGHLIGHTING SELECTED ITEM - //if (option.state & QStyle::State_Selected) - //painter->fillRect(option.rect, option.palette.highlight()); - - // draw title - QPointF titlePointF(option.rect.x()+SPACER,option.rect.y()+option.rect.height()-10); - QString text; - if(index.parent().isValid()) // event - text = qVariantValue(index.data()) + ": " + static_cast(index.internalPointer())->title(); - else // group - text = qVariantValue(index.data()); - painter->drawText(titlePointF,text); + else // doesn't have parent - time-groups' elements (top items) + { + int numFav = numberOfFavourities(index); + int numAlarm = numberOfAlarms(index); + + QStyleOptionButton styleOptionButton; + styleOptionButton.rect = option.rect; + if (isExpanded(index)) styleOptionButton.state = QStyle::State_Sunken; + // styleOptionButton.text = qVariantValue(index.data()); + qApp->style()->drawPrimitive(QStyle::PE_PanelButtonCommand, &styleOptionButton, painter, mViewPtr); + // qApp->style()->drawControl(QStyle::CE_PushButtonLabel, &styleOptionButton, painter, mViewPtr); + // qApp->style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &styleOptionButton, painter, mViewPtr); + + QFont fontSmall = option.font; + fontSmall.setBold(true); + fontSmall.setPixelSize(option.rect.height()*scaleFactor1); + QFontMetrics fmSmall(fontSmall); + + QFont fontBig = option.font; + fontBig.setBold(true); + fontBig.setPixelSize(option.rect.height()*scaleFactor2); + QFontMetrics fmBig(fontBig); + + int spacer = (fmSmall.boundingRect("999").width() < SPACER) ? SPACER : fmSmall.boundingRect("999").width(); + + // draw icons + painter->setPen(QPen(textColor)); + painter->setFont(fontSmall); + QImage *image = mControls[numFav ? FavouriteControlStrong : FavouriteControlNo]->image(); + QPoint drawPoint = + option.rect.topRight() + - QPoint( + spacer + image->width(), + - option.rect.height()/2 + image->height()/2); + painter->drawImage(drawPoint,*image); + painter->drawText(drawPoint+QPoint(image->width()+2, image->height() - 2), + QString::number(numFav)); + + drawPoint.setX(drawPoint.x() - spacer - image->width()); + image = mControls[numAlarm ? AlarmControlOn : AlarmControlOff]->image(); + painter->drawImage(drawPoint,*image); + painter->drawText(drawPoint+QPoint(image->width()+2, image->height() - 2), + QString::number(numAlarm)); + + // draw texts + QString numEvents = QString::number(index.model()->rowCount(index)).append("/"); + drawPoint.setX(drawPoint.x() - spacer - fmSmall.boundingRect(numEvents).width()); + drawPoint.setY(drawPoint.y()+image->height() - 2); + painter->drawText(drawPoint,numEvents); + + QPointF titlePointF = QPoint( + option.rect.x()+SPACER, + option.rect.y()+option.rect.height()-fmBig.descent()); + painter->setFont(fontBig); + painter->drawText(titlePointF,index.data().value()); + } painter->restore(); } @@ -159,7 +248,7 @@ QSize Delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex & if (index.internalId() == 0) // time group { - return QSize(30,30); + return QSize(40,40); } else // event { @@ -203,52 +292,60 @@ Delegate::ControlId Delegate::whichControlClicked(const QModelIndex &aIndex, con while (i.hasNext()) { ControlId id = i.next(); - if(mControls[id]->drawRect(static_cast(parent())->visualRect(aIndex)).contains(aPoint)) + Control *control = mControls[id]; + if (control->enabled() + and control->drawRect(static_cast(parent())->visualRect(aIndex)).contains(aPoint)) + { return id; + } } return ControlNone; } +Delegate::Control::Control(ControlId aControlId, const QString &aImageName, const Control* prev_control) + : mId(aControlId) + , mImage(new QImage(aImageName)) + , mDrawPoint(QPoint(0,0)) + , mEnabled(false) +{ + QPoint p; + if (prev_control == NULL) { + p = QPoint(0, SPACER); + } else { + p = prev_control->drawPoint(); + } + p.setX(p.x()-image()->width()-SPACER); + setDrawPoint(p); +} + +void Delegate::Control::paint(QPainter* painter, const QRect rect) +{ + painter->drawImage(drawPoint(rect),*image()); + setEnabled(true); +} + void Delegate::defineControls() { - Control *control; - QPoint p(0,0); // FAVOURITE ICONs - // on - control = new Control(FavouriteControlOn,QString(":icons/favourite-on.png")); - p = QPoint(0,0); - p.setX(p.x()-control->image()->width()-SPACER); - control->setDrawPoint(p); - mControls.insert(FavouriteControlOn,control); - // off - control = new Control(FavouriteControlOff,QString(":icons/favourite-off.png")); - p = QPoint(0,0); - p.setX(p.x()-control->image()->width()-SPACER); - control->setDrawPoint(p); - mControls.insert(FavouriteControlOff,control); + // strong + mControls.insert(FavouriteControlStrong, new Control(FavouriteControlStrong, QString(":icons/favourite-strong.png"), NULL)); + // weak + mControls.insert(FavouriteControlWeak, new Control(FavouriteControlWeak, QString(":icons/favourite-weak.png"), NULL)); + // no + mControls.insert(FavouriteControlNo, new Control(FavouriteControlNo, QString(":icons/favourite-no.png"), NULL)); // ALARM ICONs // on - control = new Control(AlarmControlOn,QString(":icons/alarm-on.png")); - p = mControls[FavouriteControlOn]->drawPoint(); - p.setX(p.x()-control->image()->width()-SPACER); - control->setDrawPoint(p); - mControls.insert(AlarmControlOn,control); + mControls.insert(AlarmControlOn, + new Control(AlarmControlOn, QString(":icons/alarm-on.png"), mControls[FavouriteControlStrong])); // off - control = new Control(AlarmControlOff,QString(":icons/alarm-off.png")); - p = mControls[FavouriteControlOff]->drawPoint(); - p.setX(p.x()-control->image()->width()-SPACER); - control->setDrawPoint(p); - mControls.insert(AlarmControlOff,control); - - // MAP ICON - control = new Control(MapControl,QString(":icons/compass.png")); - p = mControls[AlarmControlOn]->drawPoint(); - p.setX(p.x()-control->image()->width()-SPACER); - control->setDrawPoint(p); - mControls.insert(MapControl,control); -} + mControls.insert(AlarmControlOff, + new Control(AlarmControlOff, QString(":icons/alarm-off.png"), mControls[FavouriteControlNo])); + // WARNING ICON + mControls.insert(WarningControl, + new Control(WarningControl, QString(":icons/dialog-warning.png"), mControls[AlarmControlOff])); + } bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const { @@ -258,3 +355,29 @@ bool Delegate::isPointFromRect(const QPoint &aPoint, const QRect &aRect) const return false; } +int Delegate::numberOfFavourities(const QModelIndex &index) const +{ + if(index.parent().isValid()) // it's event, not time-group + return 0; + + int nrofFavs = 0; + for(int i=0; irowCount(index); i++) + if(static_cast(index.model()->index(i, 0, index).internalPointer())->favourite() != Favourite_no) + nrofFavs++; + + return nrofFavs; +} + +int Delegate::numberOfAlarms(const QModelIndex &index) const +{ + if(index.parent().isValid()) // it's event, not time-group + return 0; + + int nrofAlarms = 0; + for(int i=0; irowCount(index); i++) + if(static_cast(index.model()->index(i, 0, index).internalPointer())->hasAlarm()) + nrofAlarms++; + + return nrofAlarms; +} +