view.cpp 28.1 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
 *
 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
6
 * Copyright (C) 2013 DreamSourceLab <support@dreamsourcelab.com>
DreamSourceLab's avatar
DreamSourceLab committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * 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 <assert.h>
#include <limits.h>
#include <math.h>

#include <boost/foreach.hpp>

Diego F. Asanza's avatar
Diego F. Asanza committed
30
#include <QApplication>
DreamSourceLab's avatar
DreamSourceLab committed
31 32 33 34
#include <QEvent>
#include <QMouseEvent>
#include <QScrollBar>

DreamSourceLab's avatar
DreamSourceLab committed
35
#include "groupsignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
36
#include "decodetrace.h"
DreamSourceLab's avatar
DreamSourceLab committed
37
#include "header.h"
DreamSourceLab's avatar
DreamSourceLab committed
38
#include "devmode.h"
DreamSourceLab's avatar
DreamSourceLab committed
39 40
#include "ruler.h"
#include "signal.h"
DreamSourceLab's avatar
DreamSourceLab committed
41
#include "dsosignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
42 43
#include "view.h"
#include "viewport.h"
DreamSourceLab's avatar
DreamSourceLab committed
44
#include "mathtrace.h"
DreamSourceLab's avatar
DreamSourceLab committed
45

DreamSourceLab's avatar
DreamSourceLab committed
46
#include "../device/devinst.h"
DreamSourceLab's avatar
DreamSourceLab committed
47 48 49
#include "pv/sigsession.h"
#include "pv/data/logic.h"
#include "pv/data/logicsnapshot.h"
50
#include "pv/dialogs/calibration.h"
DreamSourceLab's avatar
DreamSourceLab committed
51 52 53 54 55 56 57 58 59 60 61

using namespace boost;
using namespace std;

namespace pv {
namespace view {

const int View::LabelMarginWidth = 70;
const int View::RulerHeight = 50;

const int View::MaxScrollValue = INT_MAX / 2;
62
const int View::MaxHeightUnit = 20;
DreamSourceLab's avatar
DreamSourceLab committed
63 64 65 66 67 68 69 70 71

//const int View::SignalHeight = 30;s
const int View::SignalMargin = 10;
const int View::SignalSnapGridSize = 10;

const QColor View::CursorAreaColour(220, 231, 243);

const QSizeF View::LabelPadding(4, 4);

DreamSourceLab's avatar
DreamSourceLab committed
72
View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget *parent) :
DreamSourceLab's avatar
DreamSourceLab committed
73
    QScrollArea(parent),
DreamSourceLab's avatar
DreamSourceLab committed
74
	_session(session),
DreamSourceLab's avatar
DreamSourceLab committed
75
    _sampling_bar(sampling_bar),
DreamSourceLab's avatar
DreamSourceLab committed
76 77 78 79 80 81 82 83
    _scale(1e-8),
    _preScale(1e-6),
    _maxscale(1e9),
    _minscale(1e-15),
	_offset(0),
    _preOffset(0),
	_updating_scroll(false),
	_show_cursors(false),
DreamSourceLab's avatar
DreamSourceLab committed
84
    _trig_pos(0),
DreamSourceLab's avatar
DreamSourceLab committed
85
    _hover_point(-1, -1)
DreamSourceLab's avatar
DreamSourceLab committed
86 87 88 89 90 91 92 93
{
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

	connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
		this, SLOT(h_scroll_value_changed(int)));
	connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
		this, SLOT(v_scroll_value_changed(int)));

DreamSourceLab's avatar
DreamSourceLab committed
94 95 96 97 98 99 100 101 102 103 104 105 106
    // trace viewport map
    _trace_view_map[SR_CHANNEL_LOGIC] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_GROUP] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_DECODER] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_ANALOG] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_DSO] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_FFT] = FFT_VIEW;

    _active_viewport = NULL;
    _ruler = new Ruler(*this);
    _header = new Header(*this);
    _devmode = new DevMode(this, session);

DreamSourceLab's avatar
DreamSourceLab committed
107
    setViewportMargins(headerWidth(), RulerHeight, 0, 0);
DreamSourceLab's avatar
DreamSourceLab committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    //setViewport(_viewport);

    // windows splitter
    _time_viewport = new Viewport(*this, TIME_VIEW);
    _time_viewport->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    _time_viewport->setMinimumHeight(100);
    connect(_time_viewport, SIGNAL(measure_updated()),
            this, SLOT(on_measure_updated()));
    _fft_viewport = new Viewport(*this, FFT_VIEW);
    _fft_viewport->setVisible(false);
    _fft_viewport->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    _fft_viewport->setMinimumHeight(100);
    connect(_fft_viewport, SIGNAL(measure_updated()),
            this, SLOT(on_measure_updated()));

    _vsplitter = new QSplitter(this);
    _vsplitter->setOrientation(Qt::Vertical);
    _vsplitter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    _viewport_list.push_back(_time_viewport);
    _vsplitter->addWidget(_time_viewport);
    _vsplitter->setCollapsible(0, false);
    _vsplitter->setStretchFactor(0, 2);
    _viewport_list.push_back(_fft_viewport);
    _vsplitter->addWidget(_fft_viewport);
    _vsplitter->setCollapsible(1, false);
    _vsplitter->setStretchFactor(1, 1);

    _viewcenter = new QWidget(this);
    _viewcenter->setContentsMargins(0,0,0,0);
    QGridLayout* layout = new QGridLayout(_viewcenter);
    layout->setContentsMargins(0,0,0,0);
    _viewcenter->setLayout(layout);
    layout->addWidget(_vsplitter, 0, 0);
    QWidget* bottom = new QWidget(this);
    bottom->setFixedHeight(10);
    layout->addWidget(bottom, 1, 0);
    setViewport(_viewcenter);
    connect(_vsplitter, SIGNAL(splitterMoved(int,int)),
        this, SLOT(splitterMoved(int, int)));
DreamSourceLab's avatar
DreamSourceLab committed
148

149 150
    connect(&_session, SIGNAL(device_setted()),
            _devmode, SLOT(set_device()));
151 152 153 154
    connect(&_session, SIGNAL(signals_changed()),
        this, SLOT(signals_changed()));
    connect(&_session, SIGNAL(data_updated()),
        this, SLOT(data_updated()));
DreamSourceLab's avatar
DreamSourceLab committed
155 156
    connect(&_session, SIGNAL(receive_trigger(quint64)),
            this, SLOT(set_trig_pos(quint64)));
157 158
    connect(&_session, SIGNAL(show_region(uint64_t,uint64_t)),
            this, SLOT(show_region(uint64_t, uint64_t)));
DreamSourceLab's avatar
DreamSourceLab committed
159

DreamSourceLab's avatar
DreamSourceLab committed
160 161 162 163 164
    connect(_devmode, SIGNAL(mode_changed()),
            this, SIGNAL(mode_changed()));

    connect(_header, SIGNAL(traces_moved()),
        this, SLOT(on_traces_moved()));
DreamSourceLab's avatar
DreamSourceLab committed
165 166 167
    connect(_header, SIGNAL(header_updated()),
        this, SLOT(header_updated()));

DreamSourceLab's avatar
DreamSourceLab committed
168 169
    _time_viewport->installEventFilter(this);
    _fft_viewport->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
170 171
	_ruler->installEventFilter(this);
	_header->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
172
    _devmode->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
173

DreamSourceLab's avatar
DreamSourceLab committed
174
    _viewcenter->setObjectName(tr("ViewArea_center"));
DreamSourceLab's avatar
DreamSourceLab committed
175 176 177 178
    _ruler->setObjectName(tr("ViewArea_ruler"));
    _header->setObjectName(tr("ViewArea_header"));

    _show_trig_cursor = false;
179
    _trig_cursor = new Cursor(*this, Trace::dsLightRed, 0);
DreamSourceLab's avatar
DreamSourceLab committed
180 181
    _show_search_cursor = false;
    _search_pos = 0;
182
    _search_cursor = new Cursor(*this, Trace::dsLightBlue, _search_pos);
183 184 185

    _cali = new pv::dialogs::Calibration(this);
    _cali->hide();
DreamSourceLab's avatar
DreamSourceLab committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
}

SigSession& View::session()
{
	return _session;
}

double View::scale() const
{
	return _scale;
}

double View::offset() const
{
	return _offset;
}

double View::get_minscale() const
{
    return _minscale;
}

double View::get_maxscale() const
{
    return _maxscale;
}

void View::zoom(double steps)
{
DreamSourceLab's avatar
DreamSourceLab committed
215
    zoom(steps, get_view_width() / 2);
DreamSourceLab's avatar
DreamSourceLab committed
216 217
}

DreamSourceLab's avatar
DreamSourceLab committed
218
void View::set_update(Viewport *viewport, bool need_update)
DreamSourceLab's avatar
DreamSourceLab committed
219
{
DreamSourceLab's avatar
DreamSourceLab committed
220
    viewport->set_need_update(need_update);
DreamSourceLab's avatar
DreamSourceLab committed
221 222
}

DreamSourceLab's avatar
DreamSourceLab committed
223
void View::set_all_update(bool need_update)
DreamSourceLab's avatar
DreamSourceLab committed
224
{
DreamSourceLab's avatar
DreamSourceLab committed
225 226
    BOOST_FOREACH(Viewport *viewport, _viewport_list)
        viewport->set_need_update(need_update);
DreamSourceLab's avatar
DreamSourceLab committed
227 228
}

DreamSourceLab's avatar
DreamSourceLab committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
void View::update_sample(bool instant)
{
    _session.get_device()->set_config(NULL, NULL, SR_CONF_INSTANT, g_variant_new_boolean(instant));
    BOOST_FOREACH(const boost::shared_ptr<pv::view::Signal> s, _session.get_signals()) {
        boost::shared_ptr<pv::view::DsoSignal> dsoSig;
        if (dsoSig = dynamic_pointer_cast<pv::view::DsoSignal>(s)) {
            dsoSig->go_hDialCur();
            break;
        }
    }
}

void View::set_sample_rate(uint64_t sample_rate, bool force)
{
    if (_session.get_capture_state() != pv::SigSession::Stopped || force)
        _sampling_bar->set_sample_rate(sample_rate);
}

void View::set_sample_limit(uint64_t sample_limit, bool force)
{
    if (_session.get_capture_state() != pv::SigSession::Stopped || force)
        _sampling_bar->set_sample_limit(sample_limit);
}

DreamSourceLab's avatar
DreamSourceLab committed
253 254 255 256 257 258 259
void View::zoom(double steps, int offset)
{
    //if (_session.get_capture_state() == SigSession::Stopped) {
        _preScale = _scale;
        _preOffset = _offset;

        const double cursor_offset = _offset + _scale * offset;
DreamSourceLab's avatar
DreamSourceLab committed
260
        if (_session.get_device()->dev_inst()->mode != DSO) {
DreamSourceLab's avatar
DreamSourceLab committed
261
            _scale *= std::pow(3.0/2.0, -steps);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
262
            _scale = max(min(_scale, _maxscale), _minscale);
DreamSourceLab's avatar
DreamSourceLab committed
263
        }else {
264
            const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
DreamSourceLab's avatar
DreamSourceLab committed
265
            bool setted = false;
266 267
            BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
                boost::shared_ptr<DsoSignal> dsoSig;
DreamSourceLab's avatar
DreamSourceLab committed
268 269
                if (dsoSig = dynamic_pointer_cast<DsoSignal>(s)) {
                    if(steps > 0.5)
DreamSourceLab's avatar
DreamSourceLab committed
270
                        dsoSig->go_hDialPre(setted);
DreamSourceLab's avatar
DreamSourceLab committed
271
                    else if (steps < -0.5)
DreamSourceLab's avatar
DreamSourceLab committed
272 273 274 275
                        dsoSig->go_hDialNext(setted);
                    else
                        break;
                    setted = true;
DreamSourceLab's avatar
DreamSourceLab committed
276
                }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
277 278
            }
        }
279

DreamSourceLab's avatar
DreamSourceLab committed
280 281
        _offset = cursor_offset - _scale * offset;
        _offset = max(min(_offset, get_max_offset()), get_min_offset());
DreamSourceLab's avatar
DreamSourceLab committed
282 283

        if (_scale != _preScale || _offset != _preOffset) {
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
284
            _header->update();
DreamSourceLab's avatar
DreamSourceLab committed
285
            _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
286
            viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
287 288 289 290 291 292 293 294 295 296 297 298
            update_scroll();
        }
    //}
}


void View::set_scale_offset(double scale, double offset)
{
    //if (_session.get_capture_state() == SigSession::Stopped) {
        _preScale = _scale;
        _preOffset = _offset;

DreamSourceLab's avatar
DreamSourceLab committed
299
        _scale = max(min(scale, _maxscale), _minscale);
300
        _offset = max(min(offset, get_max_offset()), get_min_offset());
DreamSourceLab's avatar
DreamSourceLab committed
301 302 303

        if (_scale != _preScale || _offset != _preOffset) {
            update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
304
            _header->update();
DreamSourceLab's avatar
DreamSourceLab committed
305
            _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
306
            viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
307 308 309 310 311 312 313 314 315 316 317 318 319
        }
    //}
}

void View::set_preScale_preOffset()
{
    //assert(_preScale <= _maxscale);
    //assert(_preScale >= _minscale);
    //assert(_preOffset >= 0);

    set_scale_offset(_preScale, _preOffset);
}

DreamSourceLab's avatar
DreamSourceLab committed
320
vector< boost::shared_ptr<Trace> > View::get_traces(int type)
DreamSourceLab's avatar
DreamSourceLab committed
321
{
DreamSourceLab's avatar
DreamSourceLab committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
//    const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
//    const vector< boost::shared_ptr<GroupSignal> > groups(_session.get_group_signals());
//#ifdef ENABLE_DECODE
//    const vector< boost::shared_ptr<DecodeTrace> > decode_sigs(
//        _session.get_decode_signals());
//    vector< boost::shared_ptr<Trace> > traces(
//        sigs.size() + groups.size() + decode_sigs.size());
//#else
//    vector< boost::shared_ptr<Trace> > traces(sigs.size() + groups.size());
//#endif

//    vector< boost::shared_ptr<Trace> >::iterator i = traces.begin();
//    i = copy(sigs.begin(), sigs.end(), i);
//#ifdef ENABLE_DECODE
//    i = copy(decode_sigs.begin(), decode_sigs.end(), i);
//#endif
//    i = copy(groups.begin(), groups.end(), i);

//    stable_sort(traces.begin(), traces.end(), compare_trace_v_offsets);
//    return traces;

343
    const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
DreamSourceLab's avatar
DreamSourceLab committed
344
    const vector< boost::shared_ptr<GroupSignal> > groups(_session.get_group_signals());
DreamSourceLab's avatar
DreamSourceLab committed
345
#ifdef ENABLE_DECODE
346
    const vector< boost::shared_ptr<DecodeTrace> > decode_sigs(
DreamSourceLab's avatar
DreamSourceLab committed
347 348
        _session.get_decode_signals());
#endif
DreamSourceLab's avatar
DreamSourceLab committed
349
    const vector< boost::shared_ptr<MathTrace> > maths(_session.get_math_signals());
DreamSourceLab's avatar
DreamSourceLab committed
350

DreamSourceLab's avatar
DreamSourceLab committed
351 352 353 354 355
    vector< boost::shared_ptr<Trace> > traces;
    BOOST_FOREACH(boost::shared_ptr<Trace> t, sigs) {
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }
DreamSourceLab's avatar
DreamSourceLab committed
356
#ifdef ENABLE_DECODE
DreamSourceLab's avatar
DreamSourceLab committed
357 358 359 360
    BOOST_FOREACH(boost::shared_ptr<Trace> t, decode_sigs) {
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }
DreamSourceLab's avatar
DreamSourceLab committed
361
#endif
DreamSourceLab's avatar
DreamSourceLab committed
362 363 364 365 366 367 368 369 370
    BOOST_FOREACH(boost::shared_ptr<Trace> t, groups) {
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }

    BOOST_FOREACH(boost::shared_ptr<Trace> t, maths) {
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }
DreamSourceLab's avatar
DreamSourceLab committed
371 372 373 374 375

    stable_sort(traces.begin(), traces.end(), compare_trace_v_offsets);
    return traces;
}

376 377
bool View::compare_trace_v_offsets(const boost::shared_ptr<Trace> &a,
    const boost::shared_ptr<Trace> &b)
DreamSourceLab's avatar
DreamSourceLab committed
378 379 380
{
    assert(a);
    assert(b);
381 382 383 384
    if (a->get_type() != b->get_type())
        return a->get_type() > b->get_type();
    else
        return a->get_v_offset() < b->get_v_offset();
DreamSourceLab's avatar
DreamSourceLab committed
385 386
}

DreamSourceLab's avatar
DreamSourceLab committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
bool View::cursors_shown() const
{
	return _show_cursors;
}

bool View::trig_cursor_shown() const
{
    return _show_trig_cursor;
}

bool View::search_cursor_shown() const
{
    return _show_search_cursor;
}

void View::show_cursors(bool show)
{
	_show_cursors = show;
	_ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
406
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
407 408 409 410 411 412
}

void View::show_trig_cursor(bool show)
{
    _show_trig_cursor = show;
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
413
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
414 415 416 417 418 419
}

void View::show_search_cursor(bool show)
{
    _show_search_cursor = show;
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
420
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
421 422 423 424
}

void View::set_trig_pos(quint64 trig_pos)
{
425
    const double time = trig_pos * 1.0 / _session.cur_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
426
    _trig_pos = trig_pos;
427
    _trig_cursor->set_index(trig_pos);
428 429 430 431
    if (ds_trigger_get_en()) {
        _show_trig_cursor = true;
        set_scale_offset(_scale,  time - _scale * get_view_width() / 2);
    }
432 433

    _trigger_time = QDateTime::currentDateTime();
434
    const int64_t secs = time - _session.cur_sampletime();
435 436
    _trigger_time = _trigger_time.addSecs(secs);

DreamSourceLab's avatar
DreamSourceLab committed
437
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
438
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
439 440 441 442 443 444
}

void View::set_search_pos(uint64_t search_pos)
{
    //assert(search_pos >= 0);

445
    const double time = search_pos * 1.0 / _session.cur_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
446
    _search_pos = search_pos;
447
    _search_cursor->set_index(search_pos);
DreamSourceLab's avatar
DreamSourceLab committed
448
    set_scale_offset(_scale,  time - _scale * get_view_width() / 2);
DreamSourceLab's avatar
DreamSourceLab committed
449
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
450
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
}

uint64_t View::get_trig_pos()
{
    return _trig_pos;
}

uint64_t View::get_search_pos()
{
    return _search_pos;
}

const QPointF& View::hover_point() const
{
	return _hover_point;
}

void View::normalize_layout()
{
DreamSourceLab's avatar
DreamSourceLab committed
470
    const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
DreamSourceLab's avatar
DreamSourceLab committed
471 472

	int v_min = INT_MAX;
473
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
474
        v_min = min(t->get_v_offset(), v_min);
DreamSourceLab's avatar
DreamSourceLab committed
475 476

	const int delta = -min(v_min, 0);
477
    BOOST_FOREACH(boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
478
        t->set_v_offset(t->get_v_offset() + delta);
DreamSourceLab's avatar
DreamSourceLab committed
479

DreamSourceLab's avatar
DreamSourceLab committed
480
    verticalScrollBar()->setSliderPosition(delta);
DreamSourceLab's avatar
DreamSourceLab committed
481 482 483 484 485 486 487 488 489 490 491
	v_scroll_value_changed(verticalScrollBar()->sliderPosition());
}


int View::get_spanY()
{
    return _spanY;
}

int View::get_signalHeight()
{
DreamSourceLab's avatar
DreamSourceLab committed
492
    return _signalHeight;
DreamSourceLab's avatar
DreamSourceLab committed
493 494 495 496
}

void View::get_scroll_layout(double &length, double &offset) const
{
497
    const set< boost::shared_ptr<data::SignalData> > data_set = _session.get_data();
DreamSourceLab's avatar
DreamSourceLab committed
498
    if (data_set.empty())
DreamSourceLab's avatar
DreamSourceLab committed
499 500
		return;

501
    length = _session.cur_sampletime() / _scale;
DreamSourceLab's avatar
DreamSourceLab committed
502 503 504 505 506
	offset = _offset / _scale;
}

void View::update_scroll()
{
DreamSourceLab's avatar
DreamSourceLab committed
507
    assert(_viewcenter);
DreamSourceLab's avatar
DreamSourceLab committed
508

DreamSourceLab's avatar
DreamSourceLab committed
509
    const QSize areaSize = _viewcenter->size();
DreamSourceLab's avatar
DreamSourceLab committed
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532

	// Set the horizontal scroll bar
	double length = 0, offset = 0;
	get_scroll_layout(length, offset);
	length = max(length - areaSize.width(), 0.0);

	horizontalScrollBar()->setPageStep(areaSize.width() / 2);

	_updating_scroll = true;

	if (length < MaxScrollValue) {
		horizontalScrollBar()->setRange(0, length);
		horizontalScrollBar()->setSliderPosition(offset);
	} else {
		horizontalScrollBar()->setRange(0, MaxScrollValue);
		horizontalScrollBar()->setSliderPosition(
			_offset * MaxScrollValue / (_scale * length));
	}

	_updating_scroll = false;

	// Set the vertical scrollbar
	verticalScrollBar()->setPageStep(areaSize.height());
DreamSourceLab's avatar
DreamSourceLab committed
533
    verticalScrollBar()->setRange(0,0);
DreamSourceLab's avatar
DreamSourceLab committed
534 535
}

536
void View::update_scale_offset()
DreamSourceLab's avatar
DreamSourceLab committed
537
{
538
    const uint64_t sample_rate = _session.cur_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
539 540 541
    assert(sample_rate > 0);

    if (_session.get_device()->dev_inst()->mode != DSO) {
542 543
        //_scale = (1.0 / sample_rate) / WellPixelsPerSample;
        _maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
DreamSourceLab's avatar
DreamSourceLab committed
544
    } else {
545
        _scale = _session.get_device()->get_time_base() * 10.0 / get_view_width() * std::pow(10.0, -9.0);
DreamSourceLab's avatar
DreamSourceLab committed
546 547
        _maxscale = 1e9;
    }
548
    _minscale = (1.0 / sample_rate) / MaxPixelsPerSample;
549 550 551 552

    _scale = max(min(_scale, _maxscale), _minscale);
    _offset = max(min(_offset, get_max_offset()), get_min_offset());

DreamSourceLab's avatar
DreamSourceLab committed
553
    _preScale = _scale;
554
    _preOffset = _offset;
DreamSourceLab's avatar
DreamSourceLab committed
555

556
    _trig_cursor->set_index(_trig_pos);
DreamSourceLab's avatar
DreamSourceLab committed
557 558

    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
559
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
560 561 562 563 564
}

void View::signals_changed()
{
    int total_rows = 0;
565
    uint8_t max_height = MaxHeightUnit;
DreamSourceLab's avatar
DreamSourceLab committed
566 567 568 569 570 571 572 573
    vector< boost::shared_ptr<Trace> > time_traces;
    vector< boost::shared_ptr<Trace> > fft_traces;
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, get_traces(ALL_VIEW)) {
        if (_trace_view_map[t->get_type()] == TIME_VIEW)
            time_traces.push_back(t);
        else if (_trace_view_map[t->get_type()] == FFT_VIEW)
            if (t->enabled())
                fft_traces.push_back(t);
DreamSourceLab's avatar
DreamSourceLab committed
574
    }
DreamSourceLab's avatar
DreamSourceLab committed
575

DreamSourceLab's avatar
DreamSourceLab committed
576 577 578 579 580 581 582 583 584 585 586 587
    if (!fft_traces.empty()) {
        if (!_fft_viewport->isVisible()) {
            _fft_viewport->setVisible(true);
            _fft_viewport->clear_measure();
            _viewport_list.push_back(_fft_viewport);
            _vsplitter->refresh();
        }
        BOOST_FOREACH(boost::shared_ptr<Trace> t, fft_traces) {
            t->set_view(this);
            t->set_viewport(_fft_viewport);
            t->set_totalHeight(_fft_viewport->height());
            t->set_v_offset(_fft_viewport->geometry().bottom());
588 589
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 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
        _fft_viewport->setVisible(false);
        _vsplitter->refresh();

        // Find the decoder in the stack
        std::list< Viewport *>::iterator iter = _viewport_list.begin();
        for(int i = 0; i < _viewport_list.size(); i++, iter++)
            if ((*iter) == _fft_viewport)
                break;
        // Delete the element
        if (iter != _viewport_list.end())
            _viewport_list.erase(iter);
    }

    if (!time_traces.empty() && _time_viewport) {
        BOOST_FOREACH(const boost::shared_ptr<Trace> t, time_traces) {
            assert(t);
            if (dynamic_pointer_cast<DsoSignal>(t) ||
                t->enabled())
                total_rows += t->rows_size();
        }

        const double height = (_time_viewport->height()
                               - horizontalScrollBar()->height()
                               - 2 * SignalMargin * time_traces.size()) * 1.0 / total_rows;

        if (_session.get_device()->dev_inst()->mode == LOGIC) {
            GVariant* gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_MAX_HEIGHT_VALUE);
            if (gvar != NULL) {
                max_height = (g_variant_get_byte(gvar) + 1) * MaxHeightUnit;
                g_variant_unref(gvar);
            }
            _signalHeight = (int)((height <= 0) ? 1 : (height >= max_height) ? max_height : height);
        } else if (_session.get_device()->dev_inst()->mode == DSO) {
            _signalHeight = (_header->height()
                             - horizontalScrollBar()->height()
                             - 2 * SignalMargin * time_traces.size()) * 1.0 / total_rows;
        } else {
            _signalHeight = (int)((height <= 0) ? 1 : height);
        }
        _spanY = _signalHeight + 2 * SignalMargin;
        int next_v_offset = SignalMargin;
        BOOST_FOREACH(boost::shared_ptr<Trace> t, time_traces) {
            t->set_view(this);
            t->set_viewport(_time_viewport);
            const double traceHeight = _signalHeight*t->rows_size();
            t->set_totalHeight((int)traceHeight);
            t->set_v_offset(next_v_offset + 0.5 * traceHeight + SignalMargin);
            next_v_offset += traceHeight + 2 * SignalMargin;

            boost::shared_ptr<view::DsoSignal> dsoSig;
            if (dsoSig = dynamic_pointer_cast<view::DsoSignal>(t))
                dsoSig->set_scale(dsoSig->get_view_rect().height() / 256.0f);
        }
        _time_viewport->clear_measure();
644
    }
DreamSourceLab's avatar
DreamSourceLab committed
645 646 647

    header_updated();
    normalize_layout();
648
    data_updated();
DreamSourceLab's avatar
DreamSourceLab committed
649 650 651 652 653 654 655 656
}

bool View::eventFilter(QObject *object, QEvent *event)
{
	const QEvent::Type type = event->type();
	if (type == QEvent::MouseMove) {

		const QMouseEvent *const mouse_event = (QMouseEvent*)event;
DreamSourceLab's avatar
DreamSourceLab committed
657
        if (object == _ruler || object == _time_viewport || object == _fft_viewport) {
DreamSourceLab's avatar
DreamSourceLab committed
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
            //_hover_point = QPoint(mouse_event->x(), 0);
            double cur_periods = (mouse_event->pos().x() * _scale + _offset) / _ruler->get_min_period();
            double integer_x = (round(cur_periods) * _ruler->get_min_period() - _offset ) / _scale;
            double cur_deviate_x = qAbs(mouse_event->pos().x() - integer_x);
            if (cur_deviate_x < 10)
                _hover_point = QPointF(integer_x, mouse_event->pos().y());
            else
                _hover_point = mouse_event->pos();
        } else if (object == _header)
			_hover_point = QPoint(0, mouse_event->y());
		else
			_hover_point = QPoint(-1, -1);

		hover_point_changed();

	} else if (type == QEvent::Leave) {
		_hover_point = QPoint(-1, -1);
		hover_point_changed();
	}

	return QObject::eventFilter(object, event);
}

bool View::viewportEvent(QEvent *e)
{
	switch(e->type()) {
	case QEvent::Paint:
	case QEvent::MouseButtonPress:
	case QEvent::MouseButtonRelease:
	case QEvent::MouseButtonDblClick:
	case QEvent::MouseMove:
	case QEvent::Wheel:
		return false;

	default:
		return QAbstractScrollArea::viewportEvent(e);
	}
}

int View::headerWidth()
{
    int headerWidth;
700
    int maxNameWidth = 25;
DreamSourceLab's avatar
DreamSourceLab committed
701 702
    int maxLeftWidth = 0;
    int maxRightWidth = 0;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
703

DreamSourceLab's avatar
v0.21  
DreamSourceLab committed
704 705 706
    QFont font = QApplication::font();
    QFontMetrics fm(font);

DreamSourceLab's avatar
DreamSourceLab committed
707
    const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
DreamSourceLab's avatar
DreamSourceLab committed
708
    if (!traces.empty()){
709
        BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces) {
DreamSourceLab's avatar
DreamSourceLab committed
710 711 712
            maxNameWidth = max(fm.boundingRect(t->get_name()).width(), maxNameWidth);
            maxLeftWidth = max(t->get_leftWidth(), maxLeftWidth);
            maxRightWidth = max(t->get_rightWidth(), maxRightWidth);
DreamSourceLab's avatar
DreamSourceLab committed
713 714 715 716 717 718 719 720 721 722 723 724
        }
    }
    maxNameWidth = max(_header->get_nameEditWidth(), maxNameWidth);
    headerWidth = maxLeftWidth + maxNameWidth + maxRightWidth;

    setViewportMargins(headerWidth, RulerHeight, 0, 0);

    return headerWidth;
}

void View::resizeEvent(QResizeEvent*)
{
DreamSourceLab's avatar
DreamSourceLab committed
725
    setViewportMargins(headerWidth(), RulerHeight, 0, 0);
DreamSourceLab's avatar
DreamSourceLab committed
726 727
    update_margins();
    update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
728
    signals_changed();
DreamSourceLab's avatar
DreamSourceLab committed
729
    if (_session.get_device()->dev_inst()->mode == DSO)
DreamSourceLab's avatar
DreamSourceLab committed
730
        _scale = _session.get_device()->get_time_base() * std::pow(10.0, -9.0) * DS_CONF_DSO_HDIVS / get_view_width();
DreamSourceLab's avatar
DreamSourceLab committed
731

732
    if (_session.get_device()->dev_inst()->mode != DSO)
733
        _maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
734 735 736
    else
        _maxscale = 1e9;

DreamSourceLab's avatar
DreamSourceLab committed
737 738 739
    _scale = min(_scale, _maxscale);

    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
740
    _header->header_resize();
DreamSourceLab's avatar
DreamSourceLab committed
741 742
    set_update(_time_viewport, true);
    set_update(_fft_viewport, true);
DreamSourceLab's avatar
DreamSourceLab committed
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
}

void View::h_scroll_value_changed(int value)
{
	if (_updating_scroll)
		return;

    _preOffset = _offset;

	const int range = horizontalScrollBar()->maximum();
	if (range < MaxScrollValue)
		_offset = _scale * value;
	else {
		double length = 0, offset;
		get_scroll_layout(length, offset);
		_offset = _scale * length * value / MaxScrollValue;
	}

761
    _offset = max(min(_offset, get_max_offset()), get_min_offset());
DreamSourceLab's avatar
DreamSourceLab committed
762 763 764

    if (_offset != _preOffset) {
        _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
765
        viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
766 767 768 769 770 771
    }
}

void View::v_scroll_value_changed(int value)
{
	_header->update();
DreamSourceLab's avatar
DreamSourceLab committed
772
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
773 774 775 776 777 778 779 780 781 782 783
}

void View::data_updated()
{
    setViewportMargins(headerWidth(), RulerHeight, 0, 0);
    update_margins();

	// Update the scroll bars
	update_scroll();

	// Repaint the view
DreamSourceLab's avatar
DreamSourceLab committed
784 785 786
    set_update(_time_viewport, true);
    set_update(_fft_viewport, true);
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
787 788 789 790
}

void View::update_margins()
{
DreamSourceLab's avatar
DreamSourceLab committed
791 792 793 794
    _ruler->setGeometry(_viewcenter->x(), 0,
        get_view_width(), _viewcenter->y());
    _header->setGeometry(0, _viewcenter->y(),
        _viewcenter->x(), _viewcenter->height());
DreamSourceLab's avatar
DreamSourceLab committed
795
    _devmode->setGeometry(0, 0,
DreamSourceLab's avatar
DreamSourceLab committed
796
        _viewcenter->x(), _viewcenter->y());
DreamSourceLab's avatar
DreamSourceLab committed
797 798 799 800 801 802 803 804 805 806
}

void View::header_updated()
{
    headerWidth();
    update_margins();

    // Update the scroll bars
    update_scroll();

DreamSourceLab's avatar
DreamSourceLab committed
807
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
808 809 810 811 812 813
    _header->update();
}

void View::marker_time_changed()
{
	_ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
814
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
815 816
}

DreamSourceLab's avatar
DreamSourceLab committed
817
void View::on_traces_moved()
DreamSourceLab's avatar
DreamSourceLab committed
818 819
{
	update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
820 821
    set_update(_time_viewport, true);
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
822
    //traces_moved();
DreamSourceLab's avatar
DreamSourceLab committed
823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
}

/*
 * cursorList
 */
std::list<Cursor*>& View::get_cursorList()
{
    return _cursorList;
}

Cursor* View::get_trig_cursor()
{
    return _trig_cursor;
}

Cursor* View::get_search_cursor()
{
    return _search_cursor;
}

Ruler* View::get_ruler()
{
    return _ruler;
}

848
void View::add_cursor(QColor color, uint64_t index)
DreamSourceLab's avatar
DreamSourceLab committed
849
{
850
    Cursor *newCursor = new Cursor(*this, color, index);
DreamSourceLab's avatar
DreamSourceLab committed
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
    _cursorList.push_back(newCursor);
    cursor_update();
}

void View::del_cursor(Cursor* cursor)
{
    assert(cursor);

    _cursorList.remove(cursor);
    delete cursor;
    cursor_update();
}

void View::set_cursor_middle(int index)
{
    assert(index < (int)_cursorList.size());

    list<Cursor*>::iterator i = _cursorList.begin();
    while (index-- != 0)
            i++;
871
    set_scale_offset(_scale, (*i)->index() * 1.0 / _session.cur_samplerate() - _scale * get_view_width() / 2);
DreamSourceLab's avatar
DreamSourceLab committed
872 873
}

DreamSourceLab's avatar
DreamSourceLab committed
874 875 876 877 878 879 880
void View::on_measure_updated()
{
    _active_viewport = dynamic_cast<Viewport *>(sender());
    measure_updated();
}

QString View::get_measure(QString option)
DreamSourceLab's avatar
DreamSourceLab committed
881
{
DreamSourceLab's avatar
DreamSourceLab committed
882 883 884 885
    if (_active_viewport) {
        return _active_viewport->get_measure(option);
    }
    return "#####";
DreamSourceLab's avatar
DreamSourceLab committed
886 887 888 889
}

QString View::get_cm_time(int index)
{
890
    return _ruler->format_real_time(get_cursor_samples(index), _session.cur_samplerate());
DreamSourceLab's avatar
DreamSourceLab committed
891 892 893 894 895 896 897
}

QString View::get_cm_delta(int index1, int index2)
{
    if (index1 == index2)
        return "0";

898 899 900
    uint64_t samples1 = get_cursor_samples(index1);
    uint64_t samples2 = get_cursor_samples(index2);
    uint64_t delta_sample = (samples1 > samples2) ? samples1 - samples2 : samples2 - samples1;
901
    return _ruler->format_real_time(delta_sample, _session.cur_samplerate());
DreamSourceLab's avatar
DreamSourceLab committed
902 903
}

DreamSourceLab's avatar
DreamSourceLab committed
904 905
uint64_t View::get_cursor_samples(int index)
{
906
    assert(index < (int)_cursorList.size());
DreamSourceLab's avatar
DreamSourceLab committed
907

908 909 910 911 912 913 914 915
    int curIndex = 0;
    for (list<Cursor*>::iterator i = _cursorList.begin();
         i != _cursorList.end(); i++) {
        if (index == curIndex) {
            return (*i)->index();
        }
        curIndex++;
    }
DreamSourceLab's avatar
DreamSourceLab committed
916 917
}

DreamSourceLab's avatar
DreamSourceLab committed
918 919 920 921 922 923 924
void View::on_cursor_moved()
{
    cursor_moved();
}

void View::set_measure_en(int enable)
{
DreamSourceLab's avatar
DreamSourceLab committed
925 926
    BOOST_FOREACH(Viewport *viewport, _viewport_list)
            viewport->set_measure_en(enable);
DreamSourceLab's avatar
DreamSourceLab committed
927 928 929 930
}

void View::on_state_changed(bool stop)
{
DreamSourceLab's avatar
DreamSourceLab committed
931 932 933 934
    if (stop) {
        BOOST_FOREACH(Viewport *viewport, _viewport_list)
            viewport->stop_trigger_timer();
    }
935
    update_scale_offset();
DreamSourceLab's avatar
DreamSourceLab committed
936 937
}

DreamSourceLab's avatar
DreamSourceLab committed
938
int View::get_view_width()
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
939
{
DreamSourceLab's avatar
DreamSourceLab committed
940 941
    int view_width = 0;
    if (_session.get_device()->dev_inst()->mode == DSO) {
942 943
        const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
        BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
DreamSourceLab's avatar
DreamSourceLab committed
944 945 946
            view_width = max((double)view_width, s->get_view_rect().width());
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
947
        view_width = _viewcenter->width();
DreamSourceLab's avatar
DreamSourceLab committed
948
    }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
949

DreamSourceLab's avatar
DreamSourceLab committed
950
    return view_width;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
951 952
}

953 954 955 956 957 958 959 960 961
int View::get_view_height()
{
    int view_height = 0;
    if (_session.get_device()->dev_inst()->mode == DSO) {
        const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
        BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
            view_height = max((double)view_height, s->get_view_rect().height());
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
962
        view_height = _viewcenter->height();
963 964 965 966 967
    }

    return view_height;
}

968 969 970 971 972 973 974
double View::get_min_offset()
{
    return -(_scale * (get_view_width() * (1 - MaxViewRate)));
}

double View::get_max_offset()
{
975
    return _session.cur_sampletime()
976 977 978
            - _scale * (get_view_width() * MaxViewRate);
}

979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
// -- calibration dialog
void View::show_calibration()
{
    _cali->set_device(_session.get_device());
    _cali->show();
}

void View::hide_calibration()
{
    _cali->hide();
}

void View::update_calibration()
{
    if (_cali->isVisible()) {
        _cali->set_device(_session.get_device());
    }
}

998 999 1000 1001 1002
QString View::trigger_time()
{
    return _trigger_time.toString("yyyy-MM-dd hh:mm:ss ddd");
}

1003 1004 1005
void View::show_region(uint64_t start, uint64_t end)
{
    assert(start <= end);
1006
    const double ideal_scale = (end-start) * 2.0 / _session.cur_samplerate() / get_view_width();
1007
    const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
1008
    const double new_off = (start + end)  * 0.5 / _session.cur_samplerate() - new_scale * get_view_width() / 2;
1009 1010 1011
    set_scale_offset(new_scale, new_off);
}

DreamSourceLab's avatar
DreamSourceLab committed
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
void View::viewport_update()
{
    _viewcenter->update();
    BOOST_FOREACH(Viewport *viewport, _viewport_list)
        viewport->update();
}

void View::splitterMoved(int pos, int index)
{
    (void)pos;
    (void)index;
    signals_changed();
}

DreamSourceLab's avatar
DreamSourceLab committed
1026 1027
} // namespace view
} // namespace pv