Don't use deprecated QString::sprintf().
[sigrok:sigrok.git] / frontend / gui / channelrenderarea.cpp
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <QPainter>
22 #include <QPen>
23 #include <QColor>
24 #include "channelrenderarea.h"
25 #include "mainwindow.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 /* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */
32 #define __STDC_FORMAT_MACROS
33 #include <inttypes.h>
34 #include <stdint.h>
35 #include <sigrok.h>
36
37 #ifdef __cplusplus
38 }
39 #endif
40
41 /* TODO: Should move elsewhere. */
42 int getbit(uint8_t *buf, int numbyte, int chan)
43 {
44         if (chan < 8) {
45                 return ((buf[numbyte] & (1 << chan))) >> chan;
46         } else if (chan >= 8 && chan < 16) {
47                 return ((buf[numbyte + 1] & (1 << (chan - 8)))) >> (chan - 8);
48         } else {
49                 /* Error. Currently only 8bit and 16bit LAs are supported. */
50                 return -1;
51         }
52 }
53
54 /* WHEEL_DELTA was introduced in Qt 4.6, earlier versions don't have it. */
55 #ifndef WHEEL_DELTA
56 #define WHEEL_DELTA 120
57 #endif
58
59 extern uint8_t *sample_buffer;
60
61 ChannelRenderArea::ChannelRenderArea(QWidget *parent) : QWidget(parent)
62 {
63         channelNumber = -1;
64         channelColor = Qt::black;
65         numSamples = 0;
66         sampleStart = 0;
67         sampleEnd = 0;
68         zoomFactor = 1.0;
69         painterPath = new QPainterPath();
70 }
71
72 QSize ChannelRenderArea::minimumSizeHint() const
73 {
74         return QSize(300, 10);
75         // return QSize(Qt::PreferredSize, Qt::PreferredSize);
76 }
77
78 QSize ChannelRenderArea::sizeHint() const
79 {
80         return QSize(300, 10);
81         // return QSize(Qt::PreferredSize, Qt::PreferredSize);
82 }
83
84 void ChannelRenderArea::generatePainterPath(void)
85 {
86         int current_x, current_y, oldval, newval;
87         int low = this->height() - 2, high = 2, ch = getChannelNumber();
88         uint64_t ss = getSampleStart(), se = getSampleEnd();
89
90         if (sample_buffer == NULL)
91                 return;
92
93         delete painterPath;
94         painterPath = new QPainterPath();
95
96         current_x = 0;
97         oldval = getbit(sample_buffer, 0, ch);
98         current_y = (oldval) ? high : low;
99         painterPath->moveTo(current_x, current_y);
100
101         for (uint64_t i = ss + 1; i < se; ++i) {
102                 current_x += 2;
103                 newval = getbit(sample_buffer, i, ch);
104                 if (oldval != newval) {
105                         painterPath->lineTo(current_x, current_y);
106                         current_y = (newval) ? high : low;
107                         painterPath->lineTo(current_x, current_y);
108                         oldval = newval;
109                 }
110         }
111         painterPath->lineTo(current_x, current_y);
112
113         /* Force a redraw. */
114         this->update();
115 }
116
117 void ChannelRenderArea::resizeEvent(QResizeEvent *event)
118 {
119         /* Quick hack to prevent compiler warning. */
120         event = event;
121
122         /* Quick hack to force a redraw upon resize. */
123         generatePainterPath();
124 }
125
126 void ChannelRenderArea::paintEvent(QPaintEvent *event)
127 {
128         QPainter painter(this);
129
130         /* Quick hack to prevent compiler warning. */
131         event = event;
132
133         if (sample_buffer == NULL)
134                 return;
135
136         /* TODO: Use Qt::black etc. */
137         QPen pen(this->getChannelColor(), 1, Qt::SolidLine, Qt::SquareCap,
138                  Qt::BevelJoin);
139         painter.setPen(pen);
140
141         // painter.fillRect(0, 0, this->width(), this->height(), QColor(Qt::gray));
142         // painter.setRenderHint(QPainter::Antialiasing, false);
143
144         painter.drawPath(*painterPath);
145
146         // painter.scale(getZoomFactor(), getZoomFactor());
147 }
148
149 void ChannelRenderArea::wheelEvent(QWheelEvent *event)
150 {
151         uint64_t sampleStartNew, sampleEndNew;
152         float zoomFactorNew;
153
154         /* FIXME: Make this constant user-configurable. */
155         zoomFactorNew = getZoomFactor()
156                         + 0.01 * (event->delta() / WHEEL_DELTA);
157         if (zoomFactorNew < 0)
158                 zoomFactorNew = 0;
159         if (zoomFactorNew > 2)
160                 zoomFactorNew = 2; /* FIXME: Don't hardcode. */
161         setZoomFactor(zoomFactorNew);
162
163         sampleStartNew = 0; /* FIXME */
164         sampleEndNew = getNumSamples() * zoomFactorNew;
165         if (sampleEndNew > getNumSamples())
166                 sampleEndNew = getNumSamples();
167
168         setSampleStart(sampleStartNew);
169         setSampleEnd(sampleEndNew);
170
171 #if 0
172         uint64_t sampleStartNew, sampleEndNew;
173
174         sampleStartNew = getSampleStart() + event->delta() / WHEEL_DELTA;
175         sampleEndNew = getSampleEnd() + event->delta() / WHEEL_DELTA;
176
177         /* TODO: More checks. */
178
179 #if 1
180         if (sampleStartNew < 0 || sampleEndNew < 0)
181                 return;
182         if (sampleStartNew > 512 * 1000 || sampleEndNew > 512 * 1000 /* FIXME */)
183                 return;
184 #endif
185
186         setSampleStart(sampleStartNew);
187         setSampleEnd(sampleEndNew); /* FIXME: Use len? */
188 #endif
189
190         repaint();
191 }
192
193 void ChannelRenderArea::setChannelColor(QColor color)
194 {
195         channelColor = color;
196 }
197
198 QColor ChannelRenderArea::getChannelColor(void)
199 {
200         return channelColor;
201 }
202
203 void ChannelRenderArea::setChannelNumber(int ch)
204 {
205         channelNumber = ch;
206 }
207
208 int ChannelRenderArea::getChannelNumber(void)
209 {
210         return channelNumber;
211 }
212
213 void ChannelRenderArea::setNumSamples(uint64_t s)
214 {
215         numSamples = s;
216 }
217
218 uint64_t ChannelRenderArea::getNumSamples(void)
219 {
220         return numSamples;
221 }
222
223 void ChannelRenderArea::setSampleStart(uint64_t s)
224 {
225         QString str;
226
227         sampleStart = s;
228
229         emit(sampleStartChanged(sampleStart));
230         emit(sampleStartChanged(QString::number(sampleStart)));
231 }
232
233 uint64_t ChannelRenderArea::getSampleStart(void)
234 {
235         return sampleStart;
236 }
237
238 void ChannelRenderArea::setSampleEnd(uint64_t e)
239 {
240         QString str;
241
242         sampleEnd = e;
243
244         emit(sampleEndChanged(sampleEnd));
245         emit(sampleEndChanged(QString::number(sampleEnd)));
246 }
247
248 uint64_t ChannelRenderArea::getSampleEnd(void)
249 {
250         return sampleEnd;
251 }
252
253 void ChannelRenderArea::setZoomFactor(float z)
254 {
255         QString str;
256
257         zoomFactor = z;
258
259         emit(zoomFactorChanged(zoomFactor));
260         emit(zoomFactorChanged(QString::number(zoomFactor)));
261 }
262
263 float ChannelRenderArea::getZoomFactor(void)
264 {
265         return zoomFactor;
266 }