view.cpp 34.2 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
 *
 * 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
29
#include <QApplication>
DreamSourceLab's avatar
DreamSourceLab committed
30 31 32 33
#include <QEvent>
#include <QMouseEvent>
#include <QScrollBar>

DreamSourceLab's avatar
DreamSourceLab committed
34
#include "groupsignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
35
#include "decodetrace.h"
DreamSourceLab's avatar
DreamSourceLab committed
36
#include "header.h"
DreamSourceLab's avatar
DreamSourceLab committed
37
#include "devmode.h"
DreamSourceLab's avatar
DreamSourceLab committed
38 39
#include "ruler.h"
#include "signal.h"
DreamSourceLab's avatar
DreamSourceLab committed
40
#include "dsosignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
41 42
#include "view.h"
#include "viewport.h"
Andy Dneg's avatar
Andy Dneg committed
43 44 45
#include "spectrumtrace.h"
#include "lissajoustrace.h"
#include "analogsignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
46

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

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;
64
const int View::MaxHeightUnit = 20;
DreamSourceLab's avatar
DreamSourceLab committed
65 66

//const int View::SignalHeight = 30;s
Andy Dneg's avatar
Andy Dneg committed
67
const int View::SignalMargin = 7;
DreamSourceLab's avatar
DreamSourceLab committed
68 69 70 71 72 73
const int View::SignalSnapGridSize = 10;

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

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

Andy Dneg's avatar
Andy Dneg committed
74 75 76 77 78 79 80 81
const QColor View::Red = QColor(213, 15, 37, 255);
const QColor View::Orange = QColor(238, 178, 17, 255);
const QColor View::Blue = QColor(17, 133, 209,  255);
const QColor View::Green = QColor(0, 153, 37, 255);
const QColor View::Purple = QColor(109, 50, 156, 255);
const QColor View::LightBlue = QColor(17, 133, 209, 200);


DreamSourceLab's avatar
DreamSourceLab committed
82
View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget *parent) :
DreamSourceLab's avatar
DreamSourceLab committed
83
    QScrollArea(parent),
DreamSourceLab's avatar
DreamSourceLab committed
84
	_session(session),
DreamSourceLab's avatar
DreamSourceLab committed
85
    _sampling_bar(sampling_bar),
86
    _scale(10),
DreamSourceLab's avatar
DreamSourceLab committed
87 88 89 90 91 92 93
    _preScale(1e-6),
    _maxscale(1e9),
    _minscale(1e-15),
	_offset(0),
    _preOffset(0),
	_updating_scroll(false),
	_show_cursors(false),
94
    _search_hit(false),
Andy Dneg's avatar
Andy Dneg committed
95
    _show_xcursors(false),
DreamSourceLab's avatar
DreamSourceLab committed
96
    _hover_point(-1, -1),
Andy Dneg's avatar
Andy Dneg committed
97 98 99
    _dso_auto(true),
    _show_lissajous(false),
    _back_ready(false)
DreamSourceLab's avatar
DreamSourceLab committed
100 101 102 103 104 105 106 107
{
    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
108 109 110 111 112 113 114
    // 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;
Andy Dneg's avatar
Andy Dneg committed
115 116
    _trace_view_map[SR_CHANNEL_LISSAJOUS] = TIME_VIEW;
    _trace_view_map[SR_CHANNEL_MATH] = TIME_VIEW;
DreamSourceLab's avatar
DreamSourceLab committed
117 118 119 120 121 122

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

DreamSourceLab's avatar
DreamSourceLab committed
123
    setViewportMargins(headerWidth(), RulerHeight, 0, 0);
DreamSourceLab's avatar
DreamSourceLab committed
124 125 126 127 128 129 130 131
    //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()));
132
    connect(_time_viewport, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int)));
DreamSourceLab's avatar
DreamSourceLab committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    _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);
156
    layout->setSpacing(0);
DreamSourceLab's avatar
DreamSourceLab committed
157 158 159
    layout->setContentsMargins(0,0,0,0);
    _viewcenter->setLayout(layout);
    layout->addWidget(_vsplitter, 0, 0);
Andy Dneg's avatar
Andy Dneg committed
160
    _viewbottom = new ViewStatus(_session, *this);
161 162
    _viewbottom->setFixedHeight(StatusHeight);
    layout->addWidget(_viewbottom, 1, 0);
DreamSourceLab's avatar
DreamSourceLab committed
163 164 165
    setViewport(_viewcenter);
    connect(_vsplitter, SIGNAL(splitterMoved(int,int)),
        this, SLOT(splitterMoved(int, int)));
DreamSourceLab's avatar
DreamSourceLab committed
166

167 168
    connect(&_session, SIGNAL(device_setted()),
            _devmode, SLOT(set_device()));
169
    connect(&_session, SIGNAL(signals_changed()),
170
        this, SLOT(signals_changed()), Qt::DirectConnection);
171 172
    connect(&_session, SIGNAL(data_updated()),
        this, SLOT(data_updated()));
DreamSourceLab's avatar
DreamSourceLab committed
173
    connect(&_session, SIGNAL(receive_trigger(quint64)),
174
            this, SLOT(receive_trigger(quint64)));
175 176 177 178
    connect(&_session, SIGNAL(frame_ended()),
            this, SLOT(receive_end()));
    connect(&_session, SIGNAL(frame_began()),
            this, SLOT(frame_began()));
179 180
    connect(&_session, SIGNAL(show_region(uint64_t, uint64_t, bool)),
            this, SLOT(show_region(uint64_t, uint64_t, bool)));
181 182
    connect(&_session, SIGNAL(show_wait_trigger()),
            _time_viewport, SLOT(show_wait_trigger()));
183 184
    connect(&_session, SIGNAL(repeat_hold(int)),
            this, SLOT(repeat_show()));
DreamSourceLab's avatar
DreamSourceLab committed
185

Andy Dneg's avatar
Andy Dneg committed
186 187
    connect(_devmode, SIGNAL(dev_changed(bool)),
            this, SLOT(dev_changed(bool)), Qt::DirectConnection);
DreamSourceLab's avatar
DreamSourceLab committed
188 189 190

    connect(_header, SIGNAL(traces_moved()),
        this, SLOT(on_traces_moved()));
DreamSourceLab's avatar
DreamSourceLab committed
191 192 193
    connect(_header, SIGNAL(header_updated()),
        this, SLOT(header_updated()));

DreamSourceLab's avatar
DreamSourceLab committed
194 195
    _time_viewport->installEventFilter(this);
    _fft_viewport->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
196 197
	_ruler->installEventFilter(this);
	_header->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
198
    _devmode->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
199

DreamSourceLab's avatar
DreamSourceLab committed
200
    _viewcenter->setObjectName(tr("ViewArea_center"));
DreamSourceLab's avatar
DreamSourceLab committed
201 202 203
    _ruler->setObjectName(tr("ViewArea_ruler"));
    _header->setObjectName(tr("ViewArea_header"));

Andy Dneg's avatar
Andy Dneg committed
204 205 206
    QColor fore(QWidget::palette().color(QWidget::foregroundRole()));
    fore.setAlpha(View::BackAlpha);

DreamSourceLab's avatar
DreamSourceLab committed
207
    _show_trig_cursor = false;
Andy Dneg's avatar
Andy Dneg committed
208
    _trig_cursor = new Cursor(*this, View::Red, 0);
DreamSourceLab's avatar
DreamSourceLab committed
209 210
    _show_search_cursor = false;
    _search_pos = 0;
Andy Dneg's avatar
Andy Dneg committed
211
    _search_cursor = new Cursor(*this, fore, _search_pos);
212 213 214

    _cali = new pv::dialogs::Calibration(this);
    _cali->hide();
DreamSourceLab's avatar
DreamSourceLab committed
215 216 217 218 219 220 221 222 223 224 225 226
}

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

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

227
int64_t View::offset() const
DreamSourceLab's avatar
DreamSourceLab committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241
{
	return _offset;
}

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

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

242
void View::capture_init()
243 244 245 246 247
{
    if (_session.get_device()->dev_inst()->mode == DSO)
        show_trig_cursor(true);
    else if (!_session.isRepeating())
        show_trig_cursor(false);
248 249

    _maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
250 251
    if (_session.get_device()->dev_inst()->mode == ANALOG)
        set_scale_offset(_maxscale, 0);
252
    status_clear();
Andy Dneg's avatar
Andy Dneg committed
253
    _trig_time_setted = false;
254 255
}

DreamSourceLab's avatar
DreamSourceLab committed
256 257
void View::zoom(double steps)
{
DreamSourceLab's avatar
DreamSourceLab committed
258
    zoom(steps, get_view_width() / 2);
DreamSourceLab's avatar
DreamSourceLab committed
259 260
}

DreamSourceLab's avatar
DreamSourceLab committed
261
void View::set_update(Viewport *viewport, bool need_update)
DreamSourceLab's avatar
DreamSourceLab committed
262
{
DreamSourceLab's avatar
DreamSourceLab committed
263
    viewport->set_need_update(need_update);
DreamSourceLab's avatar
DreamSourceLab committed
264 265
}

DreamSourceLab's avatar
DreamSourceLab committed
266
void View::set_all_update(bool need_update)
DreamSourceLab's avatar
DreamSourceLab committed
267
{
Andy Dneg's avatar
Andy Dneg committed
268 269
   _time_viewport->set_need_update(need_update);
   _fft_viewport->set_need_update(need_update);
DreamSourceLab's avatar
DreamSourceLab committed
270 271
}

272 273 274 275 276
double View::get_hori_res()
{
    return _sampling_bar->get_hori_res();
}

277
void View::update_hori_res()
DreamSourceLab's avatar
DreamSourceLab committed
278
{
279
    if (_session.get_device()->dev_inst()->mode == DSO) {
280
        _sampling_bar->hori_knob(0);
281
    }
DreamSourceLab's avatar
DreamSourceLab committed
282 283
}

DreamSourceLab's avatar
DreamSourceLab committed
284 285
void View::zoom(double steps, int offset)
{
286 287
    _preScale = _scale;
    _preOffset = _offset;
DreamSourceLab's avatar
DreamSourceLab committed
288

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    if (_session.get_device()->dev_inst()->mode != DSO) {
        _scale *= std::pow(3.0/2.0, -steps);
        _scale = max(min(_scale, _maxscale), _minscale);
    } else {
        if (_session.get_capture_state() == SigSession::Running &&
            _session.get_instant())
            return;

        double hori_res = -1;
        if(steps > 0.5)
            hori_res = _sampling_bar->hori_knob(-1);
        else if (steps < -0.5)
            hori_res = _sampling_bar->hori_knob(1);

        if (hori_res > 0) {
            const double scale = _session.cur_view_time() / get_view_width();
            _scale = max(min(scale, _maxscale), _minscale);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
306
        }
307
    }
308

309 310
    _offset = floor((_offset + offset) * (_preScale / _scale) - offset);
    _offset = max(min(_offset, get_max_offset()), get_min_offset());
DreamSourceLab's avatar
DreamSourceLab committed
311

312 313 314 315 316 317
    if (_scale != _preScale || _offset != _preOffset) {
        _header->update();
        _ruler->update();
        viewport_update();
        update_scroll();
    }
DreamSourceLab's avatar
DreamSourceLab committed
318 319
}

320 321 322 323 324 325 326 327
void View::timebase_changed()
{
    if (_session.get_device()->dev_inst()->mode != DSO)
        return;

    double scale = this->scale();
    double hori_res = _sampling_bar->get_hori_res();
    if (hori_res > 0)
328
        scale = _session.cur_view_time() / get_view_width();
329 330 331
    set_scale_offset(scale, this->offset());
}

332
void View::set_scale_offset(double scale, int64_t offset)
DreamSourceLab's avatar
DreamSourceLab committed
333 334 335 336 337
{
    //if (_session.get_capture_state() == SigSession::Stopped) {
        _preScale = _scale;
        _preOffset = _offset;

DreamSourceLab's avatar
DreamSourceLab committed
338
        _scale = max(min(scale, _maxscale), _minscale);
339
        _offset = floor(max(min(offset, get_max_offset()), get_min_offset()));
DreamSourceLab's avatar
DreamSourceLab committed
340 341 342

        if (_scale != _preScale || _offset != _preOffset) {
            update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
343
            _header->update();
DreamSourceLab's avatar
DreamSourceLab committed
344
            _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
345
            viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
346 347 348 349 350 351 352 353 354 355 356 357 358
        }
    //}
}

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

    set_scale_offset(_preScale, _preOffset);
}

DreamSourceLab's avatar
DreamSourceLab committed
359
vector< boost::shared_ptr<Trace> > View::get_traces(int type)
DreamSourceLab's avatar
DreamSourceLab committed
360
{
361
    const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
DreamSourceLab's avatar
DreamSourceLab committed
362
    const vector< boost::shared_ptr<GroupSignal> > groups(_session.get_group_signals());
DreamSourceLab's avatar
DreamSourceLab committed
363
#ifdef ENABLE_DECODE
364
    const vector< boost::shared_ptr<DecodeTrace> > decode_sigs(
DreamSourceLab's avatar
DreamSourceLab committed
365 366
        _session.get_decode_signals());
#endif
Andy Dneg's avatar
Andy Dneg committed
367
    const vector< boost::shared_ptr<SpectrumTrace> > spectrums(_session.get_spectrum_traces());
DreamSourceLab's avatar
DreamSourceLab committed
368

DreamSourceLab's avatar
DreamSourceLab committed
369 370 371 372 373
    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
374
#ifdef ENABLE_DECODE
DreamSourceLab's avatar
DreamSourceLab committed
375 376 377 378
    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
379
#endif
DreamSourceLab's avatar
DreamSourceLab committed
380 381 382 383 384
    BOOST_FOREACH(boost::shared_ptr<Trace> t, groups) {
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }

Andy Dneg's avatar
Andy Dneg committed
385
    BOOST_FOREACH(boost::shared_ptr<Trace> t, spectrums) {
DreamSourceLab's avatar
DreamSourceLab committed
386 387 388
        if (type == ALL_VIEW || _trace_view_map[t->get_type()] == type)
            traces.push_back(t);
    }
DreamSourceLab's avatar
DreamSourceLab committed
389

Andy Dneg's avatar
Andy Dneg committed
390 391 392 393 394 395 396 397 398 399
    boost::shared_ptr<LissajousTrace> lissajous = _session.get_lissajous_trace();
    if (lissajous && lissajous->enabled() &&
        (type == ALL_VIEW || _trace_view_map[lissajous->get_type()] == type))
        traces.push_back(lissajous);

    boost::shared_ptr<MathTrace> math = _session.get_math_trace();
    if (math && math->enabled() &&
        (type == ALL_VIEW || _trace_view_map[math->get_type()] == type))
        traces.push_back(math);

DreamSourceLab's avatar
DreamSourceLab committed
400 401 402 403
    stable_sort(traces.begin(), traces.end(), compare_trace_v_offsets);
    return traces;
}

404 405
bool View::compare_trace_v_offsets(const boost::shared_ptr<Trace> &a,
    const boost::shared_ptr<Trace> &b)
DreamSourceLab's avatar
DreamSourceLab committed
406 407 408
{
    assert(a);
    assert(b);
409
    if (a->get_type() != b->get_type())
Andy Dneg's avatar
Andy Dneg committed
410 411 412
        return a->get_type() < b->get_type();
    else if (a->get_type() == SR_CHANNEL_DSO || a->get_type() == SR_CHANNEL_ANALOG)
        return a->get_index() < b->get_index();
413 414
    else
        return a->get_v_offset() < b->get_v_offset();
DreamSourceLab's avatar
DreamSourceLab committed
415 416
}

DreamSourceLab's avatar
DreamSourceLab committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
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
436
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
437 438 439 440 441 442
}

void View::show_trig_cursor(bool show)
{
    _show_trig_cursor = show;
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
443
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
444 445 446 447 448 449
}

void View::show_search_cursor(bool show)
{
    _show_search_cursor = show;
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
450
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
451 452
}

453 454
void View::status_clear()
{
455 456
    _time_viewport->clear_dso_xm();
    _time_viewport->clear_measure();
457 458 459
    _viewbottom->clear();
}

460
void View::repeat_unshow()
461
{
462
    _viewbottom->repeat_unshow();
463 464 465 466
}

void View::frame_began()
{
Andy Dneg's avatar
Andy Dneg committed
467
//    if (_session.get_device()->dev_inst()->mode == LOGIC)
468
//        _viewbottom->set_trig_time(_session.get_session_time());
469 470 471
    _search_hit = false;
    _search_pos = 0;
    set_search_pos(_search_pos, _search_hit);
472 473
}

Andy Dneg's avatar
Andy Dneg committed
474 475 476
void View::set_trig_time()
{
    if (!_trig_time_setted && _session.get_device()->dev_inst()->mode == LOGIC) {
477 478
        _session.set_session_time(QDateTime::currentDateTime());
        _viewbottom->set_trig_time(_session.get_session_time());
Andy Dneg's avatar
Andy Dneg committed
479 480 481 482 483 484 485 486 487
    }
    _trig_time_setted = true;
}

bool View::trig_time_setted()
{
    return _trig_time_setted;
}

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
void View::receive_end()
{
    if (_session.get_device()->dev_inst()->mode == LOGIC) {
        GVariant *gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_RLE);
        if (gvar != NULL) {
            bool rle = g_variant_get_boolean(gvar);
            g_variant_unref(gvar);
            if (rle) {
                gvar = _session.get_device()->get_config(NULL, NULL, SR_CONF_ACTUAL_SAMPLES);
                if (gvar != NULL) {
                    uint64_t actual_samples = g_variant_get_uint64(gvar);
                    g_variant_unref(gvar);
                    if (actual_samples != _session.cur_samplelimits()) {
                        _viewbottom->set_rle_depth(actual_samples);
                    }
                }
            }
        }
    }
507
    _time_viewport->unshow_wait_trigger();
508 509
}

510
void View::receive_trigger(quint64 trig_pos)
DreamSourceLab's avatar
DreamSourceLab committed
511
{
512
    const double time = trig_pos * 1.0 / _session.cur_snap_samplerate();
513
    _trig_cursor->set_index(trig_pos);
514 515 516
    if (ds_trigger_get_en() ||
        _session.get_device()->name() == "virtual-session" ||
        _session.get_device()->dev_inst()->mode == DSO) {
517
        _show_trig_cursor = true;
518
        set_scale_offset(_scale,  (time / _scale) - (get_view_width() / 2));
519
    }
520

DreamSourceLab's avatar
DreamSourceLab committed
521
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
522
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
523 524
}

525 526 527 528 529 530
void View::set_trig_pos(int percent)
{
    uint64_t index = _session.cur_samplelimits() * percent / 100;
    receive_trigger(index);
}

531
void View::set_search_pos(uint64_t search_pos, bool hit)
DreamSourceLab's avatar
DreamSourceLab committed
532 533
{
    //assert(search_pos >= 0);
Andy Dneg's avatar
Andy Dneg committed
534 535
    QColor fore(QWidget::palette().color(QWidget::foregroundRole()));
    fore.setAlpha(View::BackAlpha);
DreamSourceLab's avatar
DreamSourceLab committed
536

537
    const double time = search_pos * 1.0 / _session.cur_snap_samplerate();
DreamSourceLab's avatar
DreamSourceLab committed
538
    _search_pos = search_pos;
539
    _search_hit = hit;
540
    _search_cursor->set_index(search_pos);
Andy Dneg's avatar
Andy Dneg committed
541
    _search_cursor->set_colour(hit ? View::Blue : fore);
542 543 544 545 546 547

    if (hit) {
        set_scale_offset(_scale,  (time / _scale) - (get_view_width() / 2));
        _ruler->update();
        viewport_update();
    }
DreamSourceLab's avatar
DreamSourceLab committed
548 549 550 551 552 553 554
}

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

555 556 557 558 559
bool View::get_search_hit()
{
    return _search_hit;
}

560
const QPoint& View::hover_point() const
DreamSourceLab's avatar
DreamSourceLab committed
561 562 563 564 565 566
{
	return _hover_point;
}

void View::normalize_layout()
{
DreamSourceLab's avatar
DreamSourceLab committed
567
    const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
DreamSourceLab's avatar
DreamSourceLab committed
568 569

	int v_min = INT_MAX;
570
    BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
DreamSourceLab's avatar
DreamSourceLab committed
571
        v_min = min(t->get_v_offset(), v_min);
DreamSourceLab's avatar
DreamSourceLab committed
572 573

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

DreamSourceLab's avatar
DreamSourceLab committed
577
    verticalScrollBar()->setSliderPosition(delta);
DreamSourceLab's avatar
DreamSourceLab committed
578 579 580 581 582 583 584 585 586 587 588
	v_scroll_value_changed(verticalScrollBar()->sliderPosition());
}


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

int View::get_signalHeight()
{
DreamSourceLab's avatar
DreamSourceLab committed
589
    return _signalHeight;
DreamSourceLab's avatar
DreamSourceLab committed
590 591
}

592
void View::get_scroll_layout(int64_t &length, int64_t &offset) const
DreamSourceLab's avatar
DreamSourceLab committed
593
{
594
    const set< boost::shared_ptr<data::SignalData> > data_set = _session.get_data();
DreamSourceLab's avatar
DreamSourceLab committed
595
    if (data_set.empty())
DreamSourceLab's avatar
DreamSourceLab committed
596 597
		return;

598
    length = ceil(_session.cur_snap_sampletime() / _scale);
599
    offset = _offset;
DreamSourceLab's avatar
DreamSourceLab committed
600 601 602 603
}

void View::update_scroll()
{
DreamSourceLab's avatar
DreamSourceLab committed
604
    assert(_viewcenter);
DreamSourceLab's avatar
DreamSourceLab committed
605

Andy Dneg's avatar
Andy Dneg committed
606
    const QSize areaSize = QSize(get_view_width(), get_view_height());
DreamSourceLab's avatar
DreamSourceLab committed
607 608

	// Set the horizontal scroll bar
609 610
    int64_t length = 0;
    int64_t offset = 0;
DreamSourceLab's avatar
DreamSourceLab committed
611
	get_scroll_layout(length, offset);
612
    length = max(length - areaSize.width(), (int64_t)0);
DreamSourceLab's avatar
DreamSourceLab committed
613 614 615 616 617 618 619 620 621 622 623

	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(
DreamSourceLab's avatar
DreamSourceLab committed
624
            _offset * 1.0  / length * MaxScrollValue);
DreamSourceLab's avatar
DreamSourceLab committed
625 626 627 628 629 630
	}

	_updating_scroll = false;

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

634
void View::update_scale_offset()
DreamSourceLab's avatar
DreamSourceLab committed
635
{
DreamSourceLab's avatar
DreamSourceLab committed
636
    if (_session.get_device()->dev_inst()->mode != DSO) {
637
        _maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
638
        _minscale = (1.0 / _session.cur_snap_samplerate()) / MaxPixelsPerSample;
DreamSourceLab's avatar
DreamSourceLab committed
639
    } else {
640
        _scale = _session.cur_view_time() / get_view_width();
DreamSourceLab's avatar
DreamSourceLab committed
641
        _maxscale = 1e9;
642
        _minscale = 1e-15;
DreamSourceLab's avatar
DreamSourceLab committed
643
    }
644

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

DreamSourceLab's avatar
DreamSourceLab committed
648
    _preScale = _scale;
649
    _preOffset = _offset;
DreamSourceLab's avatar
DreamSourceLab committed
650

651
    //_trig_cursor->set_index(_session.get_trigger_pos());
DreamSourceLab's avatar
DreamSourceLab committed
652 653

    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
654
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
655 656
}

Andy Dneg's avatar
Andy Dneg committed
657
void View::dev_changed(bool close)
658
{
Andy Dneg's avatar
Andy Dneg committed
659 660
    if (!close) {
        if (_session.get_device()->name().contains("virtual"))
661
            _scale = WellSamplesPerPixel * 1.0 / _session.cur_snap_samplerate();
Andy Dneg's avatar
Andy Dneg committed
662 663
        _scale = max(min(_scale, _maxscale), _minscale);
    }
664

Andy Dneg's avatar
Andy Dneg committed
665
    device_changed(close);
666 667
}

DreamSourceLab's avatar
DreamSourceLab committed
668 669 670
void View::signals_changed()
{
    int total_rows = 0;
Andy Dneg's avatar
Andy Dneg committed
671
    int label_size = 0;
672
    uint8_t max_height = MaxHeightUnit;
DreamSourceLab's avatar
DreamSourceLab committed
673 674
    vector< boost::shared_ptr<Trace> > time_traces;
    vector< boost::shared_ptr<Trace> > fft_traces;
675

DreamSourceLab's avatar
DreamSourceLab committed
676 677 678 679 680 681
    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
682
    }
DreamSourceLab's avatar
DreamSourceLab committed
683

DreamSourceLab's avatar
DreamSourceLab committed
684 685 686 687 688 689 690 691 692 693 694 695
    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());
696 697
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
698 699 700
        _fft_viewport->setVisible(false);
        _vsplitter->refresh();

701
        // Find the _fft_viewport in the stack
Andy Dneg's avatar
Andy Dneg committed
702
        std::list< QWidget *>::iterator iter = _viewport_list.begin();
703
        for(unsigned int i = 0; i < _viewport_list.size(); i++, iter++)
DreamSourceLab's avatar
DreamSourceLab committed
704 705 706 707 708 709 710 711 712 713 714 715 716
            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();
Andy Dneg's avatar
Andy Dneg committed
717 718
            if (t->rows_size() != 0)
                label_size++;
DreamSourceLab's avatar
DreamSourceLab committed
719 720 721
        }

        const double height = (_time_viewport->height()
Andy Dneg's avatar
Andy Dneg committed
722
                               - 2 * SignalMargin * label_size) * 1.0 / total_rows;
DreamSourceLab's avatar
DreamSourceLab committed
723 724 725 726 727 728 729 730 731 732 733

        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()
Andy Dneg's avatar
Andy Dneg committed
734
                             - 2 * SignalMargin * label_size) * 1.0 / total_rows;
DreamSourceLab's avatar
DreamSourceLab committed
735 736 737 738 739 740 741 742
        } 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);
Andy Dneg's avatar
Andy Dneg committed
743 744
            if (t->rows_size() == 0)
                continue;
DreamSourceLab's avatar
DreamSourceLab committed
745 746 747 748 749 750
            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;
751
            if ((dsoSig = dynamic_pointer_cast<view::DsoSignal>(t))) {
752
                dsoSig->set_scale(dsoSig->get_view_rect().height());
753
            }
Andy Dneg's avatar
Andy Dneg committed
754 755 756 757 758

            boost::shared_ptr<view::AnalogSignal> analogSig;
            if ((analogSig = dynamic_pointer_cast<view::AnalogSignal>(t))) {
                analogSig->set_scale(analogSig->get_totalHeight());
            }
DreamSourceLab's avatar
DreamSourceLab committed
759 760
        }
        _time_viewport->clear_measure();
761
    }
DreamSourceLab's avatar
DreamSourceLab committed
762 763 764

    header_updated();
    normalize_layout();
765
    update_scale_offset();
766
    data_updated();
DreamSourceLab's avatar
DreamSourceLab committed
767 768 769 770 771 772 773
}

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
774
        if (object == _ruler || object == _time_viewport || object == _fft_viewport) {
DreamSourceLab's avatar
DreamSourceLab committed
775
            //_hover_point = QPoint(mouse_event->x(), 0);
776 777
            double cur_periods = (mouse_event->pos().x() + _offset) * _scale / _ruler->get_min_period();
            int integer_x = round(cur_periods) * _ruler->get_min_period() / _scale - _offset;
DreamSourceLab's avatar
DreamSourceLab committed
778
            double cur_deviate_x = qAbs(mouse_event->pos().x() - integer_x);
779 780
            if (_session.get_device()->dev_inst()->mode == LOGIC &&
                cur_deviate_x < 10)
781
                _hover_point = QPoint(integer_x, mouse_event->pos().y());
DreamSourceLab's avatar
DreamSourceLab committed
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
            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()
{
816
    int headerWidth = _header->get_nameEditWidth();
DreamSourceLab's avatar
v0.21  
DreamSourceLab committed
817

DreamSourceLab's avatar
DreamSourceLab committed
818
    const vector< boost::shared_ptr<Trace> > traces(get_traces(ALL_VIEW));
819 820 821 822
    if (!traces.empty()) {
        BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
            headerWidth = max(t->get_name_width() + t->get_leftWidth() + t->get_rightWidth(),
                              headerWidth);
DreamSourceLab's avatar
DreamSourceLab committed
823 824 825 826 827 828 829 830 831
    }

    setViewportMargins(headerWidth, RulerHeight, 0, 0);

    return headerWidth;
}

void View::resizeEvent(QResizeEvent*)
{
Andy Dneg's avatar
Andy Dneg committed
832
    reconstruct();
DreamSourceLab's avatar
DreamSourceLab committed
833
    setViewportMargins(headerWidth(), RulerHeight, 0, 0);
DreamSourceLab's avatar
DreamSourceLab committed
834 835
    update_margins();
    update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
836
    signals_changed();
DreamSourceLab's avatar
DreamSourceLab committed
837
    if (_session.get_device()->dev_inst()->mode == DSO)
838
        _scale = _session.cur_view_time() / get_view_width();
DreamSourceLab's avatar
DreamSourceLab committed
839

840
    if (_session.get_device()->dev_inst()->mode != DSO)
841
        _maxscale = _session.cur_sampletime() / (get_view_width() * MaxViewRate);
842 843 844
    else
        _maxscale = 1e9;

DreamSourceLab's avatar
DreamSourceLab committed
845 846 847
    _scale = min(_scale, _maxscale);

    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
848
    _header->header_resize();
DreamSourceLab's avatar
DreamSourceLab committed
849 850
    set_update(_time_viewport, true);
    set_update(_fft_viewport, true);
851
    resize();
DreamSourceLab's avatar
DreamSourceLab committed
852 853 854 855 856 857 858 859 860 861 862
}

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

    _preOffset = _offset;

	const int range = horizontalScrollBar()->maximum();
	if (range < MaxScrollValue)
863
        _offset = value;
DreamSourceLab's avatar
DreamSourceLab committed
864
	else {
865 866
        int64_t length = 0;
        int64_t offset = 0;
DreamSourceLab's avatar
DreamSourceLab committed
867
		get_scroll_layout(length, offset);
DreamSourceLab's avatar
DreamSourceLab committed
868
        _offset = floor(value * 1.0 / MaxScrollValue * length);
DreamSourceLab's avatar
DreamSourceLab committed
869 870
	}

871
    _offset = max(min(_offset, get_max_offset()), get_min_offset());
DreamSourceLab's avatar
DreamSourceLab committed
872 873 874

    if (_offset != _preOffset) {
        _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
875
        viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
876 877 878 879 880
    }
}

void View::v_scroll_value_changed(int value)
{
881
    (void)value;
DreamSourceLab's avatar
DreamSourceLab committed
882
	_header->update();
DreamSourceLab's avatar
DreamSourceLab committed
883
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
884 885 886 887 888 889 890 891 892 893
}

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

	// Update the scroll bars
	update_scroll();

894 895 896
    // update scale & offset
    update_scale_offset();

DreamSourceLab's avatar
DreamSourceLab committed
897
	// Repaint the view
898
    _time_viewport->unshow_wait_trigger();
DreamSourceLab's avatar
DreamSourceLab committed
899 900 901
    set_update(_time_viewport, true);
    set_update(_fft_viewport, true);
    viewport_update();
902
    _ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
903 904 905 906
}

void View::update_margins()
{
DreamSourceLab's avatar
DreamSourceLab committed
907 908 909 910
    _ruler->setGeometry(_viewcenter->x(), 0,
        get_view_width(), _viewcenter->y());
    _header->setGeometry(0, _viewcenter->y(),
        _viewcenter->x(), _viewcenter->height());
DreamSourceLab's avatar
DreamSourceLab committed
911
    _devmode->setGeometry(0, 0,
DreamSourceLab's avatar
DreamSourceLab committed
912
        _viewcenter->x(), _viewcenter->y());
DreamSourceLab's avatar
DreamSourceLab committed
913 914 915 916 917 918 919 920 921 922
}

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

    // Update the scroll bars
    update_scroll();

DreamSourceLab's avatar
DreamSourceLab committed
923
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
924 925 926 927 928 929
    _header->update();
}

void View::marker_time_changed()
{
	_ruler->update();
DreamSourceLab's avatar
DreamSourceLab committed
930
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
931 932
}

DreamSourceLab's avatar
DreamSourceLab committed
933
void View::on_traces_moved()
DreamSourceLab's avatar
DreamSourceLab committed
934 935
{
	update_scroll();
DreamSourceLab's avatar
DreamSourceLab committed
936 937
    set_update(_time_viewport, true);
    viewport_update();
DreamSourceLab's avatar
DreamSourceLab committed
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
}

/*
 * 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;
}

963
void View::add_cursor(QColor color, uint64_t index)
DreamSourceLab's avatar
DreamSourceLab committed
964
{
965
    Cursor *newCursor = new Cursor(*this, color, index);
DreamSourceLab's avatar
DreamSourceLab committed
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
    _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++;
986
    set_scale_offset(_scale, (*i)->index() / (_session.cur_snap_samplerate() * _scale) - (get_view_width() / 2));
DreamSourceLab's avatar
DreamSourceLab committed
987 988
}

DreamSourceLab's avatar
DreamSourceLab committed
989 990 991 992 993 994 995
void View::on_measure_updated()
{
    _active_viewport = dynamic_cast<Viewport *>(sender());
    measure_updated();
}

QString View::get_measure(QString option)
DreamSourceLab's avatar
DreamSourceLab committed
996
{
DreamSourceLab's avatar
DreamSourceLab committed
997 998 999 1000
    if (_active_viewport) {
        return _active_viewport->get_measure(option);
    }
    return "#####";
DreamSourceLab's avatar
DreamSourceLab committed
1001 1002 1003 1004
}

QString View::get_cm_time(int index)
{
1005
    return _ruler->format_real_time(get_cursor_samples(index), _session.cur_snap_samplerate());
DreamSourceLab's avatar
DreamSourceLab committed
1006 1007 1008 1009 1010 1011 1012
}

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

1013 1014 1015
    uint64_t samples1 = get_cursor_samples(index1);
    uint64_t samples2 = get_cursor_samples(index2);
    uint64_t delta_sample = (samples1 > samples2) ? samples1 - samples2 : samples2 - samples1;
1016
    return _ruler->format_real_time(delta_sample, _session.cur_snap_samplerate());
DreamSourceLab's avatar
DreamSourceLab committed
1017 1018
}

1019 1020 1021 1022 1023 1024
QString View::get_index_delta(uint64_t start, uint64_t end)
{
    if (start == end)
        return "0";

    uint64_t delta_sample = (start > end) ? start - end : end - start;
1025
    return _ruler->format_real_time(delta_sample, _session.cur_snap_samplerate());
1026 1027
}

DreamSourceLab's avatar
DreamSourceLab committed
1028 1029
uint64_t View::get_cursor_samples(int index)
{
1030
    assert(index < (int)_cursorList.size());
DreamSourceLab's avatar
DreamSourceLab committed
1031

DreamSourceLab's avatar
DreamSourceLab committed
1032
    uint64_t ret = 0;
1033 1034 1035 1036
    int curIndex = 0;
    for (list<Cursor*>::iterator i = _cursorList.begin();
         i != _cursorList.end(); i++) {
        if (index == curIndex) {
DreamSourceLab's avatar
DreamSourceLab committed
1037
            ret = (*i)->index();
1038 1039 1040
        }
        curIndex++;
    }
DreamSourceLab's avatar
DreamSourceLab committed
1041
    return ret;
DreamSourceLab's avatar
DreamSourceLab committed
1042 1043
}

DreamSourceLab's avatar
DreamSourceLab committed
1044 1045
void View::set_measure_en(int enable)
{
Andy Dneg's avatar
Andy Dneg committed
1046 1047
    _time_viewport->set_measure_en(enable);
    _fft_viewport->set_measure_en(enable);
DreamSourceLab's avatar
DreamSourceLab committed
1048 1049 1050 1051
}

void View::on_state_changed(bool stop)
{
DreamSourceLab's avatar
DreamSourceLab committed
1052
    if (stop) {
Andy Dneg's avatar
Andy Dneg committed
1053 1054
        _time_viewport->stop_trigger_timer();
        _fft_viewport->stop_trigger_timer();
DreamSourceLab's avatar
DreamSourceLab committed
1055
    }
1056
    update_scale_offset();
DreamSourceLab's avatar
DreamSourceLab committed
1057 1058
}

1059 1060 1061 1062 1063 1064 1065 1066
QRect View::get_view_rect()
{
    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) {
            return s->get_view_rect();
        }
    }
DreamSourceLab's avatar
DreamSourceLab committed
1067 1068

    return _viewcenter->rect();
1069 1070
}

DreamSourceLab's avatar
DreamSourceLab committed
1071
int View::get_view_width()
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
1072
{
DreamSourceLab's avatar
DreamSourceLab committed
1073 1074
    int view_width = 0;
    if (_session.get_device()->dev_inst()->mode == DSO) {
1075 1076
        const vector< boost::shared_ptr<Signal> > sigs(_session.get_signals());
        BOOST_FOREACH(const boost::shared_ptr<Signal> s, sigs) {
1077
            view_width = max(view_width, s->get_view_rect().width());
DreamSourceLab's avatar
DreamSourceLab committed
1078 1079
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
1080
        view_width = _viewcenter->width();
DreamSourceLab's avatar
DreamSourceLab committed
1081
    }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
1082

DreamSourceLab's avatar
DreamSourceLab committed
1083
    return view_width;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
1084 1085
}

1086 1087 1088 1089 1090 1091
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) {
1092
            view_height = max(view_height, s->get_view_rect().height());
1093 1094
        }
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
1095
        view_height = _viewcenter->height();
1096 1097 1098 1099 1100
    }

    return view_height;
}

1101
int64_t View::get_min_offset()
1102
{
1103 1104 1105 1106
    if (MaxViewRate > 1)
        return floor(get_view_width() * (1 - MaxViewRate));
    else
        return 0;
1107 1108
}

1109
int64_t View::get_max_offset()
1110
{
1111
    return ceil((_session.cur_snap_sampletime() / _scale) -
1112
                (get_view_width() * MaxViewRate));
1113 1114
}

1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
// -- calibration dialog
void View::show_calibration()
{
    _cali->set_device(_session.get_device());
    _cali->show();
}

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

Andy Dneg's avatar
Andy Dneg committed
1127
void View::vDial_updated()
1128 1129 1130 1131
{
    if (_cali->isVisible()) {
        _cali->set_device(_session.get_device());
    }
Andy Dneg's avatar
Andy Dneg committed
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
    boost::shared_ptr<view::MathTrace> math_trace = _session.get_math_trace();
    if (math_trace && math_trace->enabled()) {
        math_trace->update_vDial();
    }
}

// -- lissajous figure
void View::show_lissajous(bool show)
{
    _show_lissajous = show;
    signals_changed();
1143 1144
}

1145
void View::show_region(uint64_t start, uint64_t end, bool keep)
1146 1147
{
    assert(start <= end);
1148 1149 1150 1151
    if (keep) {
        set_all_update(true);
        update();
    } else if (_session.get_map_zoom() == 0) {
1152
        const double ideal_scale = (end-start) * 2.0 / _session.cur_snap_samplerate() / get_view_width();
1153
        const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
1154
        const double new_off = (start + end)  * 0.5 / (_session.cur_snap_samplerate() * new_scale) - (get_view_width() / 2);
1155 1156 1157
        set_scale_offset(new_scale, new_off);
    } else {
        const double new_scale = scale();
1158
        const double new_off = (start + end)  * 0.5 / (_session.cur_snap_samplerate() * new_scale) - (get_view_width() / 2);
1159 1160
        set_scale_offset(new_scale, new_off);
    }
1161 1162
}

DreamSourceLab's avatar
DreamSourceLab committed
1163 1164 1165
void View::viewport_update()
{
    _viewcenter->update();
Andy Dneg's avatar
Andy Dneg committed
1166
    BOOST_FOREACH(QWidget *viewport, _viewport_list)
DreamSourceLab's avatar
DreamSourceLab committed
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
        viewport->update();
}

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

1177 1178
void View::reload()
{
Andy Dneg's avatar
Andy Dneg committed
1179
    clear();
1180 1181 1182 1183 1184

    /*
     * if headerwidth not change, viewport height will not be updated
     * lead to a wrong signal height
     */
Andy Dneg's avatar
Andy Dneg committed
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
    reconstruct();
}

void View::clear()
{
    show_trig_cursor(false);

    if (_session.get_device()->dev_inst()->mode != DSO) {
        show_xcursors(false);
    } else {
        if (!get_xcursorList().empty())
            show_xcursors(true);
    }
}

void View::reconstruct()
{
    if (_session.get_device()->dev_inst()->mode == DSO)
        _viewbottom->setFixedHeight(DsoStatusHeight);
1204
    else
Andy Dneg's avatar
Andy Dneg committed
1205 1206
        _viewbottom->setFixedHeight(StatusHeight);
    _viewbottom->reload();
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
}

void View::repeat_show()
{
    _viewbottom->update();
}

void View::set_capture_status()
{
    bool triggered;
    int progress;
    if (_session.get_capture_status(triggered, progress)) {
        _viewbottom->set_capture_status(triggered, progress);
        _viewbottom->update();
    }
1222 1223
}

DreamSourceLab's avatar