]> git.mxchange.org Git - flightgear.git/blob - src/GUI/AircraftItemDelegate.cxx
Enable anti-aliasing in the airport diagram
[flightgear.git] / src / GUI / AircraftItemDelegate.cxx
1 // AircraftItemDelegate.cxx - part of GUI launcher using Qt5
2 //
3 // Written by James Turner, started March 2015.
4 //
5 // Copyright (C) 2014 James Turner <zakalawe@mac.com>
6 //
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.
11 //
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.
16 //
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.
20
21
22 #include "AircraftItemDelegate.hxx"
23
24 #include <QDebug>
25 #include <QPainter>
26 #include <QLinearGradient>
27 #include <QListView>
28 #include <QMouseEvent>
29
30 #include "AircraftModel.hxx"
31
32 AircraftItemDelegate::AircraftItemDelegate(QListView* view) :
33     m_view(view)
34 {
35     view->viewport()->installEventFilter(this);
36
37     m_leftArrowIcon.load(":/left-arrow-icon");
38     m_rightArrowIcon.load(":/right-arrow-icon");
39 }
40
41 void AircraftItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option,
42     const QModelIndex & index) const
43 {
44     // selection feedback rendering
45     if (option.state & QStyle::State_Selected) {
46         QLinearGradient grad(option.rect.topLeft(), option.rect.bottomLeft());
47         grad.setColorAt(0.0, QColor(152, 163, 180));
48         grad.setColorAt(1.0, QColor(90, 107, 131));
49
50         QBrush backgroundBrush(grad);
51         painter->fillRect(option.rect, backgroundBrush);
52
53         painter->setPen(QColor(90, 107, 131));
54         painter->drawLine(option.rect.topLeft(), option.rect.topRight());
55
56     }
57
58     QRect contentRect = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
59
60     QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
61     painter->drawPixmap(contentRect.topLeft(), thumbnail);
62
63     // draw 1px frame
64     painter->setPen(QColor(0x7f, 0x7f, 0x7f));
65     painter->setBrush(Qt::NoBrush);
66     painter->drawRect(contentRect.left(), contentRect.top(), thumbnail.width(), thumbnail.height());
67
68     int variantCount = index.data(AircraftVariantCountRole).toInt();
69     int currentVariant =index.data(AircraftVariantRole).toInt();
70     QString description = index.data(Qt::DisplayRole).toString();
71     contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
72
73     painter->setPen(Qt::black);
74     QFont f;
75     f.setPointSize(18);
76     painter->setFont(f);
77
78     QRect descriptionRect = contentRect.adjusted(ARROW_SIZE, 0, -ARROW_SIZE, 0),
79         actualBounds;
80
81     if (variantCount > 0) {
82         bool canLeft = (currentVariant > 0);
83         bool canRight =  (currentVariant < variantCount );
84
85         QRect leftArrowRect = leftCycleArrowRect(option.rect, index);
86         if (canLeft) {
87             painter->drawPixmap(leftArrowRect.topLeft() + QPoint(2, 2), m_leftArrowIcon);
88         }
89
90         QRect rightArrowRect = rightCycleArrowRect(option.rect, index);
91         if (canRight) {
92             painter->drawPixmap(rightArrowRect.topLeft() + QPoint(2, 2), m_rightArrowIcon);
93         }
94     }
95
96     painter->drawText(descriptionRect, Qt::TextWordWrap, description, &actualBounds);
97
98     QString authors = index.data(AircraftAuthorsRole).toString();
99
100     f.setPointSize(12);
101     painter->setFont(f);
102
103     QRect authorsRect = descriptionRect;
104     authorsRect.moveTop(actualBounds.bottom() + MARGIN);
105     painter->drawText(authorsRect, Qt::TextWordWrap,
106                       QString("by: %1").arg(authors),
107                       &actualBounds);
108
109     QRect r = contentRect;
110     r.setWidth(contentRect.width() / 2);
111     r.moveTop(actualBounds.bottom() + MARGIN);
112     r.setHeight(24);
113
114     drawRating(painter, "Flight model:", r, index.data(AircraftRatingRole).toInt());
115     r.moveTop(r.bottom());
116     drawRating(painter, "Systems:", r, index.data(AircraftRatingRole + 1).toInt());
117
118     r.moveTop(actualBounds.bottom() + MARGIN);
119     r.moveLeft(r.right());
120     drawRating(painter, "Cockpit:", r, index.data(AircraftRatingRole + 2).toInt());
121     r.moveTop(r.bottom());
122     drawRating(painter, "Exterior model:", r, index.data(AircraftRatingRole + 3).toInt());
123 }
124
125 QSize AircraftItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
126 {
127     return QSize(500, 128 + (MARGIN * 2));
128 }
129
130 bool AircraftItemDelegate::eventFilter( QObject*, QEvent* event )
131 {
132     if ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease )
133     {
134         QMouseEvent* me = static_cast< QMouseEvent* >( event );
135         QModelIndex index = m_view->indexAt( me->pos() );
136         int variantCount = index.data(AircraftVariantCountRole).toInt();
137         int variantIndex = index.data(AircraftVariantRole).toInt();
138
139         if ( (event->type() == QEvent::MouseButtonRelease) && (variantCount > 0) )
140         {
141             QRect vr = m_view->visualRect(index);
142             QRect leftCycleRect = leftCycleArrowRect(vr, index),
143                 rightCycleRect = rightCycleArrowRect(vr, index);
144
145             if ((variantIndex > 0) && leftCycleRect.contains(me->pos())) {
146                 m_view->model()->setData(index, variantIndex - 1, AircraftVariantRole);
147                 emit variantChanged(index);
148                 return true;
149             } else if ((variantIndex < variantCount) && rightCycleRect.contains(me->pos())) {
150                 m_view->model()->setData(index, variantIndex + 1, AircraftVariantRole);
151                 emit variantChanged(index);
152                 return true;
153             }
154         }
155     } // of mouse button press or release
156     
157     return false;
158 }
159
160
161 QRect AircraftItemDelegate::leftCycleArrowRect(const QRect& visualRect, const QModelIndex& index) const
162 {
163     QRect contentRect = visualRect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
164     QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
165     contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
166
167     QRect r = contentRect;
168     r.setRight(r.left() + ARROW_SIZE);
169     r.setBottom(r.top() + ARROW_SIZE);
170     return r;
171
172 }
173
174 QRect AircraftItemDelegate::rightCycleArrowRect(const QRect& visualRect, const QModelIndex& index) const
175 {
176     QRect contentRect = visualRect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
177     QPixmap thumbnail = index.data(Qt::DecorationRole).value<QPixmap>();
178     contentRect.setLeft(contentRect.left() + MARGIN + thumbnail.width());
179
180     QRect r = contentRect;
181     r.setLeft(r.right() - ARROW_SIZE);
182     r.setBottom(r.top() + ARROW_SIZE);
183     return r;
184
185 }
186
187 void AircraftItemDelegate::drawRating(QPainter* painter, QString label, const QRect& box, int value) const
188 {
189     const int DOT_SIZE = 10;
190     const int DOT_MARGIN = 4;
191
192     QRect dotBox = box;
193     dotBox.setLeft(box.right() - (DOT_MARGIN * 6 + DOT_SIZE * 5));
194
195     painter->setPen(Qt::black);
196     QRect textBox = box;
197     textBox.setRight(dotBox.left() - DOT_MARGIN);
198     painter->drawText(textBox, Qt::AlignVCenter | Qt::AlignRight, label);
199
200     painter->setPen(Qt::NoPen);
201     QRect dot(dotBox.left() + DOT_MARGIN,
202               dotBox.center().y() - (DOT_SIZE / 2),
203               DOT_SIZE,
204               DOT_SIZE);
205     for (int i=0; i<5; ++i) {
206         painter->setBrush((i < value) ? QColor(0x3f, 0x3f, 0x3f) : QColor(0xaf, 0xaf, 0xaf));
207         painter->drawEllipse(dot);
208         dot.moveLeft(dot.right() + DOT_MARGIN);
209     }
210 }