1 // AircraftItemDelegate.cxx - part of GUI launcher using Qt5
3 // Written by James Turner, started March 2015.
5 // Copyright (C) 2014 James Turner <zakalawe@mac.com>
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "AircraftItemDelegate.hxx"
26 #include <QLinearGradient>
28 #include <QMouseEvent>
29 #include <QFontMetrics>
31 #include "AircraftModel.hxx"
33 AircraftItemDelegate::AircraftItemDelegate(QListView* view) :
36 view->viewport()->installEventFilter(this);
37 view->viewport()->setMouseTracking(true);
39 m_leftArrowIcon.load(":/left-arrow-icon");
40 m_rightArrowIcon.load(":/right-arrow-icon");
43 void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option,
44 const QModelIndex & index) const
46 painter->setRenderHint(QPainter::Antialiasing);
47 // selection feedback rendering
48 if (option.state & QStyle::State_Selected) {
49 QLinearGradient grad(option.rect.topLeft(), option.rect.bottomLeft());
50 grad.setColorAt(0.0, QColor(152, 163, 180));
51 grad.setColorAt(1.0, QColor(90, 107, 131));
53 QBrush backgroundBrush(grad);
54 painter->fillRect(option.rect, backgroundBrush);
56 painter->setPen(QColor(90, 107, 131));
57 painter->drawLine(option.rect.topLeft(), option.rect.topRight());
60 QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
62 QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
63 quint32 yPos = contentRect.center().y() - (thumbnail.height() / 2);
64 painter->drawPixmap(contentRect.left(), yPos, thumbnail);
67 painter->setPen(QColor(0x7f, 0x7f, 0x7f));
68 painter->setBrush(Qt::NoBrush);
69 painter->drawRect(contentRect.left(), yPos, thumbnail.width(), thumbnail.height());
71 int variantCount = index.data(AircraftVariantCountRole).toInt();
72 int currentVariant =index.data(AircraftVariantRole).toInt();
73 QString description = index.data(Qt::DisplayRole).toString();
74 contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
76 painter->setPen(Qt::black);
81 QRect descriptionRect = contentRect.adjusted(ARROW_SIZE, 0, -ARROW_SIZE, 0),
84 if (variantCount > 0) {
85 bool canLeft = (currentVariant > 0);
86 bool canRight = (currentVariant < variantCount );
88 QRect leftArrowRect = leftCycleArrowRect(option.rect, index);
90 painter->drawPixmap(leftArrowRect.topLeft() + QPoint(2, 2), m_leftArrowIcon);
93 QRect rightArrowRect = rightCycleArrowRect(option.rect, index);
95 painter->drawPixmap(rightArrowRect.topLeft() + QPoint(2, 2), m_rightArrowIcon);
99 painter->drawText(descriptionRect, Qt::TextWordWrap, description, &actualBounds);
101 QString authors = index.data(AircraftAuthorsRole).toString();
106 if (!authors.isEmpty()) {
107 QRect authorsRect = descriptionRect;
108 authorsRect.moveTop(actualBounds.bottom() + MARGIN);
109 painter->drawText(authorsRect, Qt::TextWordWrap,
110 QString("by: %1").arg(authors),
114 QString longDescription = index.data(AircraftLongDescriptionRole).toString();
115 if (!longDescription.isEmpty()) {
116 QRect longDescriptionRect = descriptionRect;
117 longDescriptionRect.moveTop(actualBounds.bottom() + MARGIN);
118 painter->drawText(longDescriptionRect, Qt::TextWordWrap,
119 longDescription, &actualBounds);
122 QRect r = contentRect;
123 r.setWidth(contentRect.width() / 3);
124 r.moveTop(actualBounds.bottom() + MARGIN);
125 r.moveLeft(r.right());
128 drawRating(painter, "Flight model:", r, index.data(AircraftRatingRole).toInt());
129 r.moveTop(r.bottom());
130 drawRating(painter, "Systems:", r, index.data(AircraftRatingRole + 1).toInt());
132 r.moveTop(actualBounds.bottom() + MARGIN);
133 r.moveLeft(r.right());
134 drawRating(painter, "Cockpit:", r, index.data(AircraftRatingRole + 2).toInt());
135 r.moveTop(r.bottom());
136 drawRating(painter, "Exterior model:", r, index.data(AircraftRatingRole + 3).toInt());
138 QVariant v = index.data(AircraftPackageStatusRole);
139 AircraftItemStatus status = static_cast<AircraftItemStatus>(v.toInt());
140 status = PackageNotInstalled;
141 if (status != PackageInstalled) {
142 painter->setBrush(Qt::NoBrush);
143 QRect buttonRect = packageButtonRect(option.rect, index);
144 painter->setPen(Qt::NoPen);
145 painter->setBrush(QColor(27, 122, 211));
146 painter->drawRoundedRect(buttonRect, 5, 5);
147 painter->setPen(Qt::white);
149 if (status == PackageNotInstalled) {
150 painter->drawText(buttonRect, Qt::AlignCenter, "Install");
151 } else if (status == PackageUpdateAvailable) {
152 painter->drawText(buttonRect, Qt::AlignCenter, "Update");
157 QSize AircraftItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
159 QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
160 QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
161 contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
165 QFontMetrics metrics(f);
167 int textHeight = metrics.boundingRect(contentRect, Qt::TextWordWrap,
168 index.data().toString()).height();
171 QFontMetrics smallMetrics(f);
173 QString authors = index.data(AircraftAuthorsRole).toString();
174 if (!authors.isEmpty()) {
175 textHeight += MARGIN;
176 textHeight += smallMetrics.boundingRect(contentRect, Qt::TextWordWrap, authors).height();
179 QString desc = index.data(AircraftLongDescriptionRole).toString();
180 if (!desc.isEmpty()) {
181 textHeight += MARGIN;
182 textHeight += smallMetrics.boundingRect(contentRect, Qt::TextWordWrap, desc).height();
186 textHeight += 48; // (24px per rating box)
188 textHeight = qMax(textHeight, 128);
190 return QSize(option.rect.width(), textHeight + (MARGIN * 2));
193 bool AircraftItemDelegate::eventFilter( QObject*, QEvent* event )
195 if ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease )
197 QMouseEvent* me = static_cast< QMouseEvent* >( event );
198 QModelIndex index = m_view->indexAt( me->pos() );
199 int variantCount = index.data(AircraftVariantCountRole).toInt();
200 int variantIndex = index.data(AircraftVariantRole).toInt();
202 if ( (event->type() == QEvent::MouseButtonRelease) && (variantCount > 0) )
204 QRect vr = m_view->visualRect(index);
205 QRect leftCycleRect = leftCycleArrowRect(vr, index),
206 rightCycleRect = rightCycleArrowRect(vr, index);
208 if ((variantIndex > 0) && leftCycleRect.contains(me->pos())) {
209 m_view->model()->setData(index, variantIndex - 1, AircraftVariantRole);
210 emit variantChanged(index);
212 } else if ((variantIndex < variantCount) && rightCycleRect.contains(me->pos())) {
213 m_view->model()->setData(index, variantIndex + 1, AircraftVariantRole);
214 emit variantChanged(index);
218 } else if ( event->type() == QEvent::MouseMove ) {
219 QMouseEvent* me = static_cast< QMouseEvent* >( event );
220 QModelIndex index = m_view->indexAt( me->pos() );
221 QRect vr = m_view->visualRect(index);
223 if (packageButtonRect(vr, index).contains(me->pos())) {
224 qDebug() << "mouse inside button";
233 QRect AircraftItemDelegate::leftCycleArrowRect(const QRect& visualRect, const QModelIndex& index) const
235 QRect contentRect = visualRect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
236 QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
237 contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
239 QRect r = contentRect;
240 r.setRight(r.left() + ARROW_SIZE);
241 r.setBottom(r.top() + ARROW_SIZE);
246 QRect AircraftItemDelegate::rightCycleArrowRect(const QRect& visualRect, const QModelIndex& index) const
248 QRect contentRect = visualRect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
249 QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
250 contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
252 QRect r = contentRect;
253 r.setLeft(r.right() - ARROW_SIZE);
254 r.setBottom(r.top() + ARROW_SIZE);
259 QRect AircraftItemDelegate::packageButtonRect(const QRect& visualRect, const QModelIndex& index) const
261 QRect contentRect = visualRect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
262 QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
263 contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
265 return QRect(contentRect.left() + ARROW_SIZE, contentRect.bottom() - 24, 60, 24);
268 void AircraftItemDelegate::drawRating(QPainter* painter, QString label, const QRect& box, int value) const
270 const int DOT_SIZE = 10;
271 const int DOT_MARGIN = 4;
274 dotBox.setLeft(box.right() - (DOT_MARGIN * 6 + DOT_SIZE * 5));
276 painter->setPen(Qt::black);
278 textBox.setRight(dotBox.left() - DOT_MARGIN);
279 painter->drawText(textBox, Qt::AlignVCenter | Qt::AlignRight, label);
281 painter->setPen(Qt::NoPen);
282 QRect dot(dotBox.left() + DOT_MARGIN,
283 dotBox.center().y() - (DOT_SIZE / 2),
286 for (int i=0; i<5; ++i) {
287 painter->setBrush((i < value) ? QColor(0x3f, 0x3f, 0x3f) : QColor(0xaf, 0xaf, 0xaf));
288 painter->drawEllipse(dot);
289 dot.moveLeft(dot.right() + DOT_MARGIN);