]> git.cworth.org Git - apitrace/blob - gui/graphing/heatmapview.cpp
Merge remote-tracking branch 'github/master' into d2d
[apitrace] / gui / graphing / heatmapview.cpp
1 #include "heatmapview.h"
2
3 #include <qmath.h>
4 #include <QToolTip>
5 #include <QPainter>
6 #include <QMouseEvent>
7
8 HeatmapView::HeatmapView(QWidget* parent) :
9     GraphView(parent),
10     m_data(NULL)
11 {
12     m_rowHeight = 20;
13     setMouseTracking(true);
14 }
15
16
17 void HeatmapView::setDataProvider(HeatmapDataProvider* data)
18 {
19     delete m_data;
20     m_data = data;
21
22     if (m_data) {
23         m_data->setSelectionState(m_selectionState);
24
25         setDefaultView(m_data->start(), m_data->end());
26
27         m_viewWidthMin = 1000;
28
29         m_graphBottom = 0;
30         m_graphTop = (m_data->headerRows() + m_data->dataRows()) * m_rowHeight;
31     } else {
32         setDefaultView(0, 0);
33         m_graphBottom = m_graphTop = 0;
34     }
35
36     update();
37 }
38
39
40 void HeatmapView::setSelectionState(SelectionState* state)
41 {
42     if (m_data) {
43         m_data->setSelectionState(state);
44     }
45
46     GraphView::setSelectionState(state);
47 }
48
49
50 void HeatmapView::mouseMoveEvent(QMouseEvent *e)
51 {
52     GraphView::mouseMoveEvent(e);
53
54     if (e->buttons() || !m_data) {
55         QToolTip::hideText();
56         return;
57     }
58
59     qint64 index = itemAtPosition(e->pos());
60
61     if (index >= 0) {
62         QToolTip::showText(e->globalPos(), m_data->itemTooltip(index));
63     } else {
64         QToolTip::hideText();
65     }
66 }
67
68
69 void HeatmapView::mouseDoubleClickEvent(QMouseEvent *e)
70 {
71     if (m_data && e->button() == Qt::LeftButton) {
72         qint64 index = itemAtPosition(e->pos());
73
74         if (index >= 0) {
75             m_data->itemDoubleClicked(index);
76             return;
77         }
78     }
79
80     GraphView::mouseDoubleClickEvent(e);
81 }
82
83
84 void HeatmapView::paintEvent(QPaintEvent *)
85 {
86     if (!m_data) {
87         return;
88     }
89
90     QPainter painter(this);
91     painter.fillRect(0, m_data->headerRows() * m_rowHeight, width(), height(), Qt::white);
92
93     /* Draw data rows */
94     painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
95     int rowStart = m_viewBottom / m_rowHeight;
96     int rowEnd = qMin<int>(qCeil(m_viewTop / (double)m_rowHeight), m_data->dataRows());
97
98     for (unsigned i = rowStart; i < rowEnd; ++i) {
99         HeatmapRowIterator* itr = m_data->dataRowIterator(i, m_viewLeft, m_viewRight, width());
100         paintRow(painter, itr);
101         painter.translate(0, m_rowHeight);
102         delete itr;
103     }
104
105     /* Draw Header */
106     painter.resetTransform();
107     painter.fillRect(0, 0, width(), m_data->headerRows() * m_rowHeight, Qt::white);
108
109     for (unsigned i = 0; i < m_data->headerRows(); ++i) {
110         HeatmapRowIterator* itr = m_data->headerRowIterator(i, m_viewLeft, m_viewRight, width());
111         paintRow(painter, itr);
112         painter.translate(0, m_rowHeight);
113         delete itr;
114     }
115
116     /* Draw Axis Lines */
117     painter.resetTransform();
118     painter.setPen(Qt::black);
119     painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
120     painter.drawLine(0, m_rowHeight * 2, width(), m_rowHeight * 2);
121
122     painter.setPen(QColor(240, 240, 240));
123     painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
124
125     for (unsigned i = rowStart; i < rowEnd; ++i) {
126         painter.drawLine(0, m_rowHeight, width(), m_rowHeight);
127         painter.translate(0, m_rowHeight);
128     }
129
130     /* Draw selection borders */
131     painter.resetTransform();
132     painter.setPen(Qt::green);
133
134     if (m_selectionState->type == SelectionState::Horizontal) {
135         double dxdt = width() / (double)m_viewWidth;
136         double scroll = m_viewLeft * dxdt;
137         double left = (m_selectionState->start * dxdt) - scroll;
138         double right = (m_selectionState->end * dxdt) - scroll;
139
140         /* Highlight time */
141         if (left >= 0 && left <= width()) {
142             painter.drawLine(left, 0, left, height());
143         }
144
145         if (right >= 0 && right <= width()) {
146             painter.drawLine(right, 0, right, height());
147         }
148     } else if (m_selectionState->type == SelectionState::Vertical) {
149         /* Highlight row */
150         int row = m_selectionState->start;
151
152         for (unsigned i = rowStart; i < rowEnd; ++i) {
153             if (m_data->dataRowAt(i) == row) {
154                 row = i - rowStart;
155
156                 painter.translate(0, m_data->headerRows() * m_rowHeight - m_viewBottom % m_rowHeight);
157                 painter.drawLine(0, (row + 1) * m_rowHeight, width(), (row + 1) * m_rowHeight);
158
159                 if (row > 0) {
160                     painter.drawLine(0, row * m_rowHeight, width(), row * m_rowHeight);
161                 }
162
163                 break;
164             }
165         }
166     }
167 }
168
169
170 void HeatmapView::paintRow(QPainter& painter, HeatmapRowIterator* itr)
171 {
172     bool selection = m_selectionState ? m_selectionState->type != SelectionState::None : false;
173
174     while (itr->next())
175     {
176         double heat = itr->heat();
177         int width = itr->width();
178         int x = itr->step();
179
180         /* Gamma correction */
181         heat = qPow(heat, 1.0 / 2.0);
182
183         if (width == 1) {
184             /* Draw single line */
185             if (selection) {
186                 double selectedHeat = itr->selectedHeat();
187
188                 if (selectedHeat >= 0.999) {
189                     heat = 255.0 - qBound(0.0, heat * 255.0, 255.0);
190
191                     if (itr->isGpu()) {
192                         painter.setPen(QColor(255, heat, heat));
193                     } else {
194                         painter.setPen(QColor(heat, heat, 255));
195                     }
196
197                     painter.drawLine(x, 0, x, m_rowHeight - 1);
198                 } else {
199                     heat = 255.0 - qBound(0.0, heat * 100.0, 100.0);
200                     painter.setPen(QColor(heat, heat, heat));
201                     painter.drawLine(x, 0, x, m_rowHeight - 1);
202
203                     if (selectedHeat > 0.001) {
204                         selectedHeat = qPow(selectedHeat, 1.0 / 2.0);
205                         selectedHeat = qBound(0.0, selectedHeat * 255.0, 255.0);
206
207                         if (itr->isGpu()) {
208                             painter.setPen(QColor(255, 0, 0, selectedHeat));
209                         } else {
210                             painter.setPen(QColor(0, 0, 255, selectedHeat));
211                         }
212
213                         painter.drawLine(x, 0, x, m_rowHeight - 1);
214                     }
215                 }
216             } else {
217                 heat = qBound(0.0, heat * 255.0, 255.0);
218
219                 if (itr->isGpu()) {
220                     painter.setPen(QColor(255, 255 - heat, 255 - heat));
221                 } else {
222                     painter.setPen(QColor(255 - heat, 255 - heat, 255));
223                 }
224
225                 painter.drawLine(x, 0, x, m_rowHeight - 1);
226             }
227         } else {
228             double selectedHeat = itr->selectedHeat();
229
230             if (selection && selectedHeat < 0.9) {
231                 painter.fillRect(x, 0, width, m_rowHeight, QColor(255 - 100, 255 - 100, 255 - 100));
232             } else if (itr->isGpu()) {
233                 painter.fillRect(x, 0, width, m_rowHeight, QColor(255, 0, 0));
234             } else {
235                 painter.fillRect(x, 0, width, m_rowHeight, QColor(0, 0, 255));
236             }
237
238             if (width > 6) {
239                 painter.setPen(Qt::white);
240                 QString elided = painter.fontMetrics().elidedText(itr->label(), Qt::ElideRight, width - 1);
241
242                 painter.drawText(x + 1, 0, width - 1, m_rowHeight - 1,
243                                  Qt::AlignLeft | Qt::AlignVCenter,
244                                  elided);
245             }
246         }
247     }
248 }
249
250
251 qint64 HeatmapView::itemAtPosition(QPoint pos)
252 {
253     if (!m_data) {
254         return -1;
255     }
256
257     double t = m_viewWidth / (double)width();
258     t *= pos.x();
259     t += m_viewLeft;
260
261     qint64 time = (qint64)t;
262     qint64 index;
263
264     if (pos.y() < m_data->headerRows() * m_rowHeight) {
265         int row = pos.y() / m_rowHeight;
266         index = m_data->headerItemAt(row, time);
267     } else {
268         int row = pos.y();
269         row -= m_data->headerRows() * m_rowHeight;
270         row += m_viewBottom;
271         row /= m_rowHeight;
272         index = m_data->dataItemAt(row, time);
273     }
274
275     return index;
276 }