viewport.cpp 22.5 KB
Newer Older
DreamSourceLab's avatar
DreamSourceLab committed
1
/*
DreamSourceLab's avatar
DreamSourceLab committed
2 3
 * This file is part of the DSView project.
 * DSView is based on PulseView.
DreamSourceLab's avatar
DreamSourceLab committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
 * Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */


#include "view.h"
#include "viewport.h"
#include "ruler.h"

#include "signal.h"
DreamSourceLab's avatar
DreamSourceLab committed
29
#include "dsosignal.h"
30
#include "logicsignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
31
#include "../device/devinst.h"
DreamSourceLab's avatar
DreamSourceLab committed
32 33 34 35 36 37 38
#include "../data/logic.h"
#include "../data/logicsnapshot.h"
#include "../sigsession.h"

#include <QMouseEvent>
#include <QStyleOption>

39 40
#include <math.h>

DreamSourceLab's avatar
DreamSourceLab committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#include <boost/foreach.hpp>

using namespace boost;
using namespace std;

namespace pv {
namespace view {

Viewport::Viewport(View &parent) :
	QWidget(&parent),
        _view(parent),
    _total_receive_len(0),
    _zoom_rect_visible(false),
    _measure_shown(false),
    _cur_sample(0),
    _nxt_sample(1),
    _cur_preX(0),
    _cur_aftX(1),
    _cur_midY(0)
{
	setMouseTracking(true);
	setAutoFillBackground(true);
	setBackgroundRole(QPalette::Base);

    //setFixedSize(QSize(600, 400));
    _mm_width = "#####";
    _mm_period = "#####";
    _mm_freq = "#####";
69
    _mm_duty = "#####";
DreamSourceLab's avatar
DreamSourceLab committed
70 71 72 73
    _measure_en = true;
    triggered = false;
    timer_cnt = 0;

DreamSourceLab's avatar
DreamSourceLab committed
74 75
    connect(&_view, SIGNAL(traces_moved()),
        this, SLOT(on_traces_moved()));
DreamSourceLab's avatar
DreamSourceLab committed
76 77 78 79 80 81 82
    connect(&trigger_timer, SIGNAL(timeout()),
            this, SLOT(on_trigger_timer()));
}

int Viewport::get_total_height() const
{
	int h = 0;
DreamSourceLab's avatar
DreamSourceLab committed
83

84 85
    const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces) {
DreamSourceLab's avatar
DreamSourceLab committed
86 87 88 89
        assert(t);
        h += (int)(t->get_signalHeight());
    }
    h += 2 * View::SignalMargin;
DreamSourceLab's avatar
DreamSourceLab committed
90 91 92 93

	return h;
}

DreamSourceLab's avatar
DreamSourceLab committed
94 95 96 97 98
QPoint Viewport::get_mouse_point() const
{
    return _mouse_point;
}

DreamSourceLab's avatar
DreamSourceLab committed
99 100 101 102 103
void Viewport::paintEvent(QPaintEvent *event)
{
    (void)event;

    using pv::view::Signal;
DreamSourceLab's avatar
DreamSourceLab committed
104

DreamSourceLab's avatar
DreamSourceLab committed
105 106 107 108 109
    QStyleOption o;
    o.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);

110 111
    const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
112 113
    {
        assert(t);
DreamSourceLab's avatar
DreamSourceLab committed
114
        t->paint_back(p, 0, _view.get_view_width());
DreamSourceLab's avatar
DreamSourceLab committed
115
    }
DreamSourceLab's avatar
DreamSourceLab committed
116

117
    p.setRenderHint(QPainter::Antialiasing, false);
DreamSourceLab's avatar
DreamSourceLab committed
118 119
    if (_view.session().get_device()->dev_inst()->mode == LOGIC ||
        _view.session().get_instant()) {
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
120 121 122 123 124 125 126 127 128 129 130 131 132
        switch(_view.session().get_capture_state()) {
        case SigSession::Init:
            break;

        case SigSession::Stopped:
            paintSignals(p);
            break;

        case SigSession::Running:
            //p.setRenderHint(QPainter::Antialiasing);
            paintProgress(p);
            break;
        }
DreamSourceLab's avatar
DreamSourceLab committed
133
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
134 135 136
        paintSignals(p);
    }

137
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
138 139 140
    {
        assert(t);
        if (t->enabled())
DreamSourceLab's avatar
DreamSourceLab committed
141
            t->paint_fore(p, 0, _view.get_view_width());
DreamSourceLab's avatar
DreamSourceLab committed
142 143
    }

144
    //p.setRenderHint(QPainter::Antialiasing, false);
DreamSourceLab's avatar
DreamSourceLab committed
145 146
    if (_view.get_signalHeight() != _curSignalHeight)
            _curSignalHeight = _view.get_signalHeight();
DreamSourceLab's avatar
DreamSourceLab committed
147

DreamSourceLab's avatar
DreamSourceLab committed
148 149 150 151 152
	p.end();
}

void Viewport::paintSignals(QPainter &p)
{
153
    const vector< boost::shared_ptr<Trace> > traces(_view.get_traces());
DreamSourceLab's avatar
DreamSourceLab committed
154 155 156 157 158 159 160 161 162 163 164 165
    if (_view.scale() != _curScale ||
        _view.offset() != _curOffset ||
        _view.get_signalHeight() != _curSignalHeight ||
        _view.need_update()) {
        _curScale = _view.scale();
        _curOffset = _view.offset();
        _curSignalHeight = _view.get_signalHeight();

        pixmap = QPixmap(size());
        pixmap.fill(Qt::transparent);
        QPainter dbp(&pixmap);
        dbp.initFrom(this);
166
        //p.setRenderHint(QPainter::Antialiasing, false);
167
        BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
168 169 170
        {
            assert(t);
            if (t->enabled())
DreamSourceLab's avatar
DreamSourceLab committed
171
                t->paint_mid(dbp, 0, _view.get_view_width());
DreamSourceLab's avatar
DreamSourceLab committed
172
        }
DreamSourceLab's avatar
DreamSourceLab committed
173

DreamSourceLab's avatar
DreamSourceLab committed
174 175 176 177 178 179 180 181
        _view.set_need_update(false);
    }
    p.drawPixmap(0, 0, pixmap);

    // plot cursors
    if (_view.cursors_shown()) {
        list<Cursor*>::iterator i = _view.get_cursorList().begin();
        double cursorX;
182
        const double samples_per_pixel = _view.session().get_device()->get_sample_rate() * _view.scale();
DreamSourceLab's avatar
DreamSourceLab committed
183
        while (i != _view.get_cursorList().end()) {
184
            cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
DreamSourceLab's avatar
DreamSourceLab committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
            if (rect().contains(_view.hover_point().x(), _view.hover_point().y()) &&
                    qAbs(cursorX - _view.hover_point().x()) <= HitCursorMargin)
                (*i)->paint(p, rect(), 1);
            else
                (*i)->paint(p, rect(), 0);
            i++;
        }
    }
    if (_view.trig_cursor_shown()) {
        _view.get_trig_cursor()->paint(p, rect(), 0);
    }
    if (_view.search_cursor_shown()) {
        _view.get_search_cursor()->paint(p, rect(), 0);
    }

    // plot zoom rect
    if (_zoom_rect_visible) {
        p.setPen(Qt::NoPen);
DreamSourceLab's avatar
DreamSourceLab committed
203
        p.setBrush(Trace::dsLightBlue);
DreamSourceLab's avatar
DreamSourceLab committed
204 205 206 207 208 209 210 211 212 213 214 215 216
        p.drawRect(_zoom_rect);
    }

    //plot measure arrow
    if (_measure_shown) {
        paintMeasure(p);
    }
}

void Viewport::paintProgress(QPainter &p)
{
    using pv::view::Signal;

DreamSourceLab's avatar
DreamSourceLab committed
217
    const quint64 _total_sample_len = _view.session().get_device()->get_sample_limit();
218
    double progress = -(_total_receive_len * 1.0 / _total_sample_len * 360 * 16);
DreamSourceLab's avatar
DreamSourceLab committed
219
    int captured_progress = 0;
DreamSourceLab's avatar
DreamSourceLab committed
220 221

    p.setPen(Qt::gray);
DreamSourceLab's avatar
DreamSourceLab committed
222 223 224
    p.setBrush(Qt::NoBrush);
    const QPoint cenPos = QPoint(_view.get_view_width() / 2, height() / 2);
    const int radius = min(0.3 * _view.get_view_width(), 0.3 * height());
DreamSourceLab's avatar
DreamSourceLab committed
225
    p.drawEllipse(cenPos, radius - 2, radius - 2);
DreamSourceLab's avatar
DreamSourceLab committed
226
    p.setPen(QPen(Trace::dsGreen, 4, Qt::SolidLine));
DreamSourceLab's avatar
DreamSourceLab committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    p.drawArc(cenPos.x() - radius, cenPos.y() - radius, 2* radius, 2 * radius, 180 * 16, progress);

    p.setPen(Qt::gray);
    const QPoint logoPoints[] = {
        QPoint(cenPos.x() - 0.75 * radius, cenPos.y()),
        QPoint(cenPos.x() - 0.75 * radius, cenPos.y() + 0.15 * radius),
        QPoint(cenPos.x() - 0.6 * radius, cenPos.y()),
        QPoint(cenPos.x() - 0.6 * radius, cenPos.y() + 0.3 * radius),
        QPoint(cenPos.x() - 0.45 * radius, cenPos.y()),
        QPoint(cenPos.x() - 0.45 * radius, cenPos.y() + 0.45 * radius),
        QPoint(cenPos.x() - 0.3 * radius, cenPos.y()),
        QPoint(cenPos.x() - 0.3 * radius, cenPos.y() + 0.3 * radius),
        QPoint(cenPos.x() - 0.15 * radius, cenPos.y()),
        QPoint(cenPos.x() - 0.15 * radius, cenPos.y() + 0.15 * radius),
        QPoint(cenPos.x() + 0.15 * radius, cenPos.y()),
        QPoint(cenPos.x() + 0.15 * radius, cenPos.y() - 0.15 * radius),
        QPoint(cenPos.x() + 0.3 * radius, cenPos.y()),
        QPoint(cenPos.x() + 0.3 * radius, cenPos.y() - 0.3 * radius),
        QPoint(cenPos.x() + 0.45 * radius, cenPos.y()),
        QPoint(cenPos.x() + 0.45 * radius, cenPos.y() - 0.45 * radius),
        QPoint(cenPos.x() + 0.6 * radius, cenPos.y()),
        QPoint(cenPos.x() + 0.6 * radius, cenPos.y() - 0.3 * radius),
        QPoint(cenPos.x() + 0.75 * radius, cenPos.y()),
        QPoint(cenPos.x() + 0.75 * radius, cenPos.y() - 0.15 * radius)
    };
    const int logoRadius = 10;
    p.drawLine(logoPoints[0], logoPoints[1]);
    p.drawLine(logoPoints[2], logoPoints[3]);
    p.drawLine(logoPoints[4], logoPoints[5]);
    p.drawLine(logoPoints[6], logoPoints[7]);
    p.drawLine(logoPoints[8], logoPoints[9]);
    p.drawLine(logoPoints[10], logoPoints[11]);
    p.drawLine(logoPoints[12], logoPoints[13]);
    p.drawLine(logoPoints[14], logoPoints[15]);
    p.drawLine(logoPoints[16], logoPoints[17]);
    p.drawLine(logoPoints[18], logoPoints[19]);
    p.drawEllipse(logoPoints[1].x() - 0.5 * logoRadius, logoPoints[1].y(),
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[3].x() - 0.5 * logoRadius, logoPoints[3].y(),
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[5].x() - 0.5 * logoRadius, logoPoints[5].y(),
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[7].x() - 0.5 * logoRadius, logoPoints[7].y(),
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[9].x() - 0.5 * logoRadius, logoPoints[9].y(),
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[11].x() - 0.5 * logoRadius, logoPoints[11].y() - logoRadius,
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[13].x() - 0.5 * logoRadius, logoPoints[13].y() - logoRadius,
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[15].x() - 0.5 * logoRadius, logoPoints[15].y() - logoRadius,
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[17].x() - 0.5 * logoRadius, logoPoints[17].y() - logoRadius,
            logoRadius, logoRadius);
    p.drawEllipse(logoPoints[19].x() - 0.5 * logoRadius, logoPoints[19].y() - logoRadius,
            logoRadius, logoRadius);

    if (!triggered) {
DreamSourceLab's avatar
DreamSourceLab committed
285 286 287 288
        const int width = _view.get_view_width();
        const QPoint cenLeftPos = QPoint(width / 2 - 0.05 * width, height() / 2);
        const QPoint cenRightPos = QPoint(width / 2 + 0.05 * width, height() / 2);
        const int trigger_radius = min(0.02 * width, 0.02 * height());
DreamSourceLab's avatar
DreamSourceLab committed
289 290

        p.setPen(Qt::NoPen);
DreamSourceLab's avatar
DreamSourceLab committed
291
        p.setBrush((timer_cnt % 3) == 0 ? Trace::dsLightBlue : Trace::dsGray);
DreamSourceLab's avatar
DreamSourceLab committed
292
        p.drawEllipse(cenLeftPos, trigger_radius, trigger_radius);
DreamSourceLab's avatar
DreamSourceLab committed
293
        p.setBrush((timer_cnt % 3) == 1 ? Trace::dsLightBlue : Trace::dsGray);
DreamSourceLab's avatar
DreamSourceLab committed
294
        p.drawEllipse(cenPos, trigger_radius, trigger_radius);
DreamSourceLab's avatar
DreamSourceLab committed
295
        p.setBrush((timer_cnt % 3) == 2 ? Trace::dsLightBlue : Trace::dsGray);
DreamSourceLab's avatar
DreamSourceLab committed
296
        p.drawEllipse(cenRightPos, trigger_radius, trigger_radius);
DreamSourceLab's avatar
DreamSourceLab committed
297 298

        sr_status status;
DreamSourceLab's avatar
DreamSourceLab committed
299
        if (sr_status_get(_view.session().get_device()->dev_inst(), &status, SR_STATUS_TRIG_BEGIN, SR_STATUS_TRIG_END) == SR_OK){
DreamSourceLab's avatar
DreamSourceLab committed
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
            const bool triggred = status.trig_hit & 0x01;
            const uint32_t captured_cnt = (status.captured_cnt0 +
                                          (status.captured_cnt1 << 8) +
                                          (status.captured_cnt2 << 16) +
                                          (status.captured_cnt3 << 24));
            captured_progress = captured_cnt * 100.0 / _total_sample_len;


            p.setPen(Trace::dsLightBlue);
            QFont font=p.font();
            font.setPointSize(10);
            font.setBold(true);
            p.setFont(font);
            QRect status_rect = QRect(cenPos.x() - radius, cenPos.y() + radius * 0.4, radius * 2, radius * 0.5);
            if (triggred)
                p.drawText(status_rect,
                           Qt::AlignCenter | Qt::AlignVCenter,
                           "Triggered! " + QString::number(captured_progress)+"% Captured");
            else
                p.drawText(status_rect,
                           Qt::AlignCenter | Qt::AlignVCenter,
                           "Waiting for Trigger! " + QString::number(captured_progress)+"% Captured");
        }

DreamSourceLab's avatar
DreamSourceLab committed
324 325
    } else {
        const int progress100 = ceil(progress / -3.6 / 16);
DreamSourceLab's avatar
DreamSourceLab committed
326
        p.setPen(Trace::dsGreen);
DreamSourceLab's avatar
DreamSourceLab committed
327 328 329 330 331 332
        QFont font=p.font();
        font.setPointSize(50);
        font.setBold(true);
        p.setFont(font);
        p.drawText(rect(), Qt::AlignCenter | Qt::AlignVCenter, QString::number(progress100)+"%");
    }
DreamSourceLab's avatar
DreamSourceLab committed
333 334 335 336 337

    p.setPen(QPen(Trace::dsLightBlue, 4, Qt::SolidLine));
    const int int_radius = max(radius - 4, 0);
    p.drawArc(cenPos.x() - int_radius, cenPos.y() - int_radius, 2* int_radius, 2 * int_radius, 180 * 16, -captured_progress*3.6*16);

DreamSourceLab's avatar
DreamSourceLab committed
338 339 340 341 342 343 344 345 346 347 348 349 350
}

void Viewport::mousePressEvent(QMouseEvent *event)
{
	assert(event);

	_mouse_down_point = event->pos();
	_mouse_down_offset = _view.offset();

    if (event->buttons() & Qt::LeftButton) {
        if (_view.cursors_shown()) {
            list<Cursor*>::iterator i = _view.get_cursorList().begin();
            double cursorX;
351
            const double samples_per_pixel = _view.session().get_device()->get_sample_rate() * _view.scale();
DreamSourceLab's avatar
DreamSourceLab committed
352
            while (i != _view.get_cursorList().end()) {
353
                cursorX = (*i)->index()/samples_per_pixel - (_view.offset() / _view.scale());
DreamSourceLab's avatar
DreamSourceLab committed
354 355 356 357 358 359 360 361 362 363 364 365 366
                if ((*i)->grabbed())
                    _view.get_ruler()->rel_grabbed_cursor();
                else if (qAbs(cursorX - event->pos().x()) <= HitCursorMargin) {
                    _view.get_ruler()->set_grabbed_cursor(*i);
                    break;
                }
                i++;
            }

        }
//        if (!_view.get_ruler()->get_grabbed_cursor()) {
//            _zoom_rect_visible = true;
//        }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
367

368 369
        const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
        BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
370
            assert(s);
371
            boost::shared_ptr<DsoSignal> dsoSig;
DreamSourceLab's avatar
DreamSourceLab committed
372
            if ((dsoSig = dynamic_pointer_cast<DsoSignal>(s)) &&
DreamSourceLab's avatar
DreamSourceLab committed
373
                 dsoSig->get_trig_rect(0, _view.get_view_width()).contains(_mouse_point)) {
DreamSourceLab's avatar
DreamSourceLab committed
374
                _drag_sig = s;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
375 376 377
                break;
            }
        }
DreamSourceLab's avatar
DreamSourceLab committed
378

DreamSourceLab's avatar
DreamSourceLab committed
379 380 381 382 383 384 385
        update();
    }
}

void Viewport::mouseMoveEvent(QMouseEvent *event)
{
	assert(event);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
386
    _mouse_point = event->pos();
DreamSourceLab's avatar
DreamSourceLab committed
387 388 389 390 391 392
    if (event->buttons() & Qt::RightButton) {
        _zoom_rect = QRectF(_mouse_down_point, event->pos());
        _zoom_rect_visible = true;
	}

    if (event->buttons() & Qt::LeftButton) {
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
393
        if (_drag_sig) {
394
            boost::shared_ptr<view::DsoSignal> dsoSig;
DreamSourceLab's avatar
DreamSourceLab committed
395 396 397 398 399 400 401 402
            if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(_drag_sig))
                dsoSig->set_trig_vpos(_mouse_point.y());
        } else {
            _view.set_scale_offset(_view.scale(),
                _mouse_down_offset +
                (_mouse_down_point - event->pos()).x() *
                _view.scale());
            measure();
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
403
        }
DreamSourceLab's avatar
DreamSourceLab committed
404
    }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
405

DreamSourceLab's avatar
DreamSourceLab committed
406 407
    if (!(event->buttons() || Qt::NoButton)) {
        uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
DreamSourceLab's avatar
DreamSourceLab committed
408 409
        TimeMarker* grabbed_marker = _view.get_ruler()->get_grabbed_cursor();
        if (_view.cursors_shown() && grabbed_marker) {
DreamSourceLab's avatar
DreamSourceLab committed
410 411
            const double cur_time = _view.offset() + _view.hover_point().x() * _view.scale();
            const double pos = cur_time * sample_rate;
412
            const double pos_delta = pos - (uint64_t)pos;
413
            if ( pos_delta < 0.5)
414
                grabbed_marker->set_index((uint64_t)floor(pos));
DreamSourceLab's avatar
DreamSourceLab committed
415
            else
416
                grabbed_marker->set_index((uint64_t)ceil(pos));
DreamSourceLab's avatar
DreamSourceLab committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430
        }
        measure();
    }

    update();
}

void Viewport::mouseReleaseEvent(QMouseEvent *event)
{
    assert(event);

    if (_zoom_rect_visible) {
        _zoom_rect_visible = false;
        const double newOffset = _view.offset() + (min(event->pos().x(), _mouse_down_point.x()) + 0.5) * _view.scale();
DreamSourceLab's avatar
DreamSourceLab committed
431
        const double newScale = max(min(_view.scale() * (event->pos().x() - _mouse_down_point.x()) / _view.get_view_width(),
DreamSourceLab's avatar
DreamSourceLab committed
432 433 434 435 436
                                        _view.get_maxscale()), _view.get_minscale());
        if (newScale != _view.scale())
            _view.set_scale_offset(newScale, newOffset);
    }

DreamSourceLab's avatar
DreamSourceLab committed
437 438 439
    if(_drag_sig)
        _drag_sig.reset();

DreamSourceLab's avatar
DreamSourceLab committed
440 441 442 443 444 445
    update();
}

void Viewport::mouseDoubleClickEvent(QMouseEvent *event)
{
    assert (event);
DreamSourceLab's avatar
DreamSourceLab committed
446 447
    (void)event;

DreamSourceLab's avatar
DreamSourceLab committed
448 449 450 451 452
    if (_view.session().get_device()->dev_inst()->mode == LOGIC) {
        if (_view.scale() == _view.get_maxscale())
            _view.set_preScale_preOffset();
        else
            _view.set_scale_offset(_view.get_maxscale(), 0);
DreamSourceLab's avatar
DreamSourceLab committed
453

DreamSourceLab's avatar
DreamSourceLab committed
454 455
        update();
    }
DreamSourceLab's avatar
DreamSourceLab committed
456 457 458 459 460 461 462 463
}

void Viewport::wheelEvent(QWheelEvent *event)
{
	assert(event);

	if (event->orientation() == Qt::Vertical) {
		// Vertical scrolling is interpreted as zooming in/out
DreamSourceLab's avatar
DreamSourceLab committed
464 465
        const double offset = (_view.session().get_capture_state() == SigSession::Running) ? 0 : event->x();
        _view.zoom(event->delta() / 80, offset);
DreamSourceLab's avatar
DreamSourceLab committed
466 467 468 469 470 471 472 473 474 475 476 477 478
	} else if (event->orientation() == Qt::Horizontal) {
		// Horizontal scrolling is interpreted as moving left/right
		_view.set_scale_offset(_view.scale(),
				       event->delta() * _view.scale()
				       + _view.offset());
	}

    measure();
}

void Viewport::leaveEvent(QEvent *)
{
    _measure_shown = false;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
479
    _mouse_point = QPoint(-1, -1);
DreamSourceLab's avatar
DreamSourceLab committed
480 481 482 483
    //_view.show_cursors(false);
    update();
}

DreamSourceLab's avatar
DreamSourceLab committed
484
void Viewport::on_traces_moved()
DreamSourceLab's avatar
DreamSourceLab committed
485 486 487 488 489 490 491 492 493 494 495
{
	update();
}

void Viewport::set_receive_len(quint64 length)
{
    if (length == 0) {
        _total_receive_len = 0;
        start_trigger_timer(333);
    } else {
        stop_trigger_timer();
DreamSourceLab's avatar
DreamSourceLab committed
496 497
        if (_total_receive_len + length > _view.session().get_device()->get_sample_limit())
            _total_receive_len = _view.session().get_device()->get_sample_limit();
DreamSourceLab's avatar
DreamSourceLab committed
498 499 500 501 502 503 504 505
        else
            _total_receive_len += length;
    }
    update();
}

void Viewport::measure()
{
506 507 508 509
   const uint64_t sample_rate = _view.session().get_device()->get_sample_rate();
   const vector< boost::shared_ptr<Signal> > sigs(_view.session().get_signals());
   BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
       assert(s);
510
       boost::shared_ptr<view::LogicSignal> logicSig;
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
       if (logicSig = dynamic_pointer_cast<view::LogicSignal>(s)) {
           if (logicSig->measure(_view.hover_point(), _cur_sample, _nxt_sample, _thd_sample)) {
               _measure_shown = true;

               _mm_width = _view.get_ruler()->format_real_time(_nxt_sample - _cur_sample, sample_rate);
               _mm_period = _thd_sample != 0 ? _view.get_ruler()->format_real_time(_thd_sample - _cur_sample, sample_rate) : "#####";
               _mm_freq = _thd_sample != 0 ? _view.get_ruler()->format_real_freq(_thd_sample - _cur_sample, sample_rate) : "#####";

               const double pixels_offset =  _view.offset() / _view.scale();
               const double samples_per_pixel = sample_rate * _view.scale();
               _cur_preX = _cur_sample / samples_per_pixel - pixels_offset;
               _cur_aftX = _nxt_sample / samples_per_pixel - pixels_offset;
               _cur_thdX = _thd_sample / samples_per_pixel - pixels_offset;
               _cur_midY = logicSig->get_y();

526
               _mm_duty = _thd_sample != 0 ? QString::number((_nxt_sample - _cur_sample) * 100.0 / (_thd_sample - _cur_sample), 'f', 2)+"%" :
527 528 529 530 531 532 533 534 535 536 537
                                             "#####";
               mouse_measure();
               return;
           } else {
               _mm_width = "#####";
               _mm_period = "#####";
               _mm_freq = "#####";
               _mm_duty = "#####";
           }
           mouse_measure();
       }
DreamSourceLab's avatar
DreamSourceLab committed
538 539
    }

540 541
    _measure_shown = false;
    return;
DreamSourceLab's avatar
DreamSourceLab committed
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
}

void Viewport::paintMeasure(QPainter &p)
{
    p.setPen(QColor(17, 133, 209,  255));
    p.drawLine(QLineF(_cur_preX, _cur_midY, _cur_aftX, _cur_midY));
    p.drawLine(QLineF(_cur_preX, _cur_midY, _cur_preX + 2, _cur_midY - 2));
    p.drawLine(QLineF(_cur_preX, _cur_midY, _cur_preX + 2, _cur_midY + 2));
    p.drawLine(QLineF(_cur_aftX - 2, _cur_midY - 2, _cur_aftX, _cur_midY));
    p.drawLine(QLineF(_cur_aftX - 2, _cur_midY + 2, _cur_aftX, _cur_midY));
    if (_thd_sample != 0) {
        p.drawLine(QLineF(_cur_aftX, _cur_midY, _cur_thdX, _cur_midY));
        p.drawLine(QLineF(_cur_aftX, _cur_midY, _cur_aftX + 2, _cur_midY - 2));
        p.drawLine(QLineF(_cur_aftX, _cur_midY, _cur_aftX + 2, _cur_midY + 2));
        p.drawLine(QLineF(_cur_thdX - 2, _cur_midY - 2, _cur_thdX, _cur_midY));
        p.drawLine(QLineF(_cur_thdX - 2, _cur_midY + 2, _cur_thdX, _cur_midY));
    }

    if (_measure_en) {
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
        int typical_width = p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, _mm_width).width();
        typical_width = max(typical_width, p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, _mm_period).width());
        typical_width = max(typical_width, p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, _mm_freq).width());
        typical_width = max(typical_width, p.boundingRect(0, 0, INT_MAX, INT_MAX,
            Qt::AlignLeft | Qt::AlignTop, _mm_duty).width());
        typical_width = typical_width + 100;

        const double width = _view.get_view_width();
        const double height = _view.viewport()->height();
        const double left = _view.hover_point().x();
        const double top = _view.hover_point().y();
        const double right = left + typical_width;
        const double bottom = top + 80;
        QPointF org_pos = QPointF(right > width ? left - typical_width : left, bottom > height ? top - 80 : top);
        QRectF measure_rect = QRectF(org_pos.x(), org_pos.y(), (double)typical_width, 80.0);
        QRectF measure1_rect = QRectF(org_pos.x(), org_pos.y(), (double)typical_width, 20.0);
        QRectF measure2_rect = QRectF(org_pos.x(), org_pos.y()+20, (double)typical_width, 20.0);
        QRectF measure3_rect = QRectF(org_pos.x(), org_pos.y()+40, (double)typical_width, 20.0);
        QRectF measure4_rect = QRectF(org_pos.x(), org_pos.y()+60, (double)typical_width, 20.0);
DreamSourceLab's avatar
DreamSourceLab committed
583 584 585 586 587 588 589 590 591 592 593 594

        p.setPen(Qt::NoPen);
        p.setBrush(QColor(17, 133, 209,  150));
        p.drawRect(measure_rect);

        p.setPen(Qt::black);
        p.drawText(measure1_rect, Qt::AlignRight | Qt::AlignVCenter,
                   "Width: " + _mm_width);
        p.drawText(measure2_rect, Qt::AlignRight | Qt::AlignVCenter,
                   "Period: " + _mm_period);
        p.drawText(measure3_rect, Qt::AlignRight | Qt::AlignVCenter,
                   "Frequency: " + _mm_freq);
595 596
        p.drawText(measure4_rect, Qt::AlignRight | Qt::AlignVCenter,
                   "Duty Cycle: " + _mm_duty);
DreamSourceLab's avatar
DreamSourceLab committed
597 598 599
    }
}

600
QString Viewport::get_measure(QString option)
DreamSourceLab's avatar
DreamSourceLab committed
601
{
602 603 604 605 606 607 608 609 610 611
    if(option.compare("width") == 0)
        return _mm_width;
    else if (option.compare("period") == 0)
        return _mm_period;
    else if (option.compare("frequency") == 0)
        return _mm_freq;
    else if (option.compare("duty") == 0)
        return _mm_duty;
    else
        return "#####";
DreamSourceLab's avatar
DreamSourceLab committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
}

void Viewport::set_measure_en(int enable)
{
    if (enable == 0)
        _measure_en = false;
    else
        _measure_en = true;
}

void Viewport::start_trigger_timer(int msec)
{
    assert(msec > 0);
    triggered = false;
    timer_cnt = 0;
    trigger_timer.start(msec);
}

void Viewport::stop_trigger_timer()
{
    triggered = true;
    timer_cnt = 0;
    trigger_timer.stop();
}

void Viewport::on_trigger_timer()
{
    timer_cnt++;
    update();
}

} // namespace view
} // namespace pv