mainwindow.cpp 47.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
 *
 * 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
 */


DreamSourceLab's avatar
DreamSourceLab committed
24
#ifdef ENABLE_DECODE
DreamSourceLab's avatar
DreamSourceLab committed
25
#include <libsigrokdecode4DSL/libsigrokdecode.h>
DreamSourceLab's avatar
DreamSourceLab committed
26
#include "dock/protocoldock.h"
DreamSourceLab's avatar
DreamSourceLab committed
27 28 29 30
#endif

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
DreamSourceLab's avatar
DreamSourceLab committed
31
#include <boost/shared_ptr.hpp>
DreamSourceLab's avatar
DreamSourceLab committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45

#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QFileDialog>
#include <QMessageBox>
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>
#include <QVBoxLayout>
#include <QWidget>
#include <QDockWidget>
#include <QDebug>
#include <QDesktopWidget>
46
#include <QDesktopServices>
DreamSourceLab's avatar
DreamSourceLab committed
47 48
#include <QKeyEvent>
#include <QEvent>
49
#include <QtGlobal>
DreamSourceLab's avatar
DreamSourceLab committed
50 51 52 53

#include "mainwindow.h"

#include "devicemanager.h"
DreamSourceLab's avatar
DreamSourceLab committed
54 55
#include "device/device.h"
#include "device/file.h"
DreamSourceLab's avatar
DreamSourceLab committed
56 57

#include "dialogs/about.h"
DreamSourceLab's avatar
DreamSourceLab committed
58
#include "dialogs/deviceoptions.h"
DreamSourceLab's avatar
DreamSourceLab committed
59
#include "dialogs/storeprogress.h"
DreamSourceLab's avatar
DreamSourceLab committed
60
#include "dialogs/waitingdialog.h"
Andy Dneg's avatar
Andy Dneg committed
61
#include "dialogs/regionoptions.h"
DreamSourceLab's avatar
DreamSourceLab committed
62 63 64 65 66

#include "toolbars/samplingbar.h"
#include "toolbars/trigbar.h"
#include "toolbars/filebar.h"
#include "toolbars/logobar.h"
67
#include "toolbars/titlebar.h"
DreamSourceLab's avatar
DreamSourceLab committed
68 69

#include "dock/triggerdock.h"
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
70
#include "dock/dsotriggerdock.h"
DreamSourceLab's avatar
DreamSourceLab committed
71 72 73 74
#include "dock/measuredock.h"
#include "dock/searchdock.h"

#include "view/view.h"
DreamSourceLab's avatar
DreamSourceLab committed
75 76 77
#include "view/trace.h"
#include "view/signal.h"
#include "view/dsosignal.h"
78
#include "view/logicsignal.h"
79
#include "view/analogsignal.h"
DreamSourceLab's avatar
DreamSourceLab committed
80 81 82 83 84 85 86

/* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdint.h>
#include <stdarg.h>
#include <glib.h>
DreamSourceLab's avatar
DreamSourceLab committed
87
#include <list>
88
#include <libusb.h>
DreamSourceLab's avatar
DreamSourceLab committed
89

DreamSourceLab's avatar
DreamSourceLab committed
90 91 92 93
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
using std::list;
using std::vector;
DreamSourceLab's avatar
DreamSourceLab committed
94 95 96 97 98 99 100 101

namespace pv {

MainWindow::MainWindow(DeviceManager &device_manager,
	const char *open_file_name,
	QWidget *parent) :
    QMainWindow(parent),
    _device_manager(device_manager),
102 103
    _session(device_manager),
    _msg(NULL)
DreamSourceLab's avatar
DreamSourceLab committed
104 105 106 107 108 109 110 111 112 113 114 115 116
{
	setup_ui();
	if (open_file_name) {
		const QString s(QString::fromUtf8(open_file_name));
		QMetaObject::invokeMethod(this, "load_file",
			Qt::QueuedConnection,
			Q_ARG(QString, s));
	}
}

void MainWindow::setup_ui()
{
	setObjectName(QString::fromUtf8("MainWindow"));
Andy Dneg's avatar
Andy Dneg committed
117
    setContentsMargins(0,0,0,0);
118 119
    layout()->setMargin(0);
    layout()->setSpacing(0);
DreamSourceLab's avatar
DreamSourceLab committed
120 121 122 123

	// Setup the central widget
	_central_widget = new QWidget(this);
	_vertical_layout = new QVBoxLayout(_central_widget);
124
    _vertical_layout->setSpacing(0);
DreamSourceLab's avatar
DreamSourceLab committed
125 126 127 128
	_vertical_layout->setContentsMargins(0, 0, 0, 0);
	setCentralWidget(_central_widget);

	// Setup the sampling bar
DreamSourceLab's avatar
DreamSourceLab committed
129
    _sampling_bar = new toolbars::SamplingBar(_session, this);
Andy Dneg's avatar
Andy Dneg committed
130
    _sampling_bar->setObjectName("sampling_bar");
DreamSourceLab's avatar
DreamSourceLab committed
131
    _trig_bar = new toolbars::TrigBar(_session, this);
Andy Dneg's avatar
Andy Dneg committed
132
    _trig_bar->setObjectName("trig_bar");
DreamSourceLab's avatar
DreamSourceLab committed
133
    _file_bar = new toolbars::FileBar(_session, this);
Andy Dneg's avatar
Andy Dneg committed
134
    _file_bar->setObjectName("file_bar");
DreamSourceLab's avatar
DreamSourceLab committed
135
    _logo_bar = new toolbars::LogoBar(_session, this);
Andy Dneg's avatar
Andy Dneg committed
136
    _logo_bar->setObjectName("logo_bar");
DreamSourceLab's avatar
DreamSourceLab committed
137 138 139 140 141 142 143 144 145

    connect(_trig_bar, SIGNAL(on_protocol(bool)), this,
            SLOT(on_protocol(bool)));
    connect(_trig_bar, SIGNAL(on_trigger(bool)), this,
            SLOT(on_trigger(bool)));
    connect(_trig_bar, SIGNAL(on_measure(bool)), this,
            SLOT(on_measure(bool)));
    connect(_trig_bar, SIGNAL(on_search(bool)), this,
            SLOT(on_search(bool)));
Andy Dneg's avatar
Andy Dneg committed
146 147
    connect(_trig_bar, SIGNAL(setTheme(QString)), this,
            SLOT(switchTheme(QString)));
DreamSourceLab's avatar
DreamSourceLab committed
148 149
    connect(_file_bar, SIGNAL(load_file(QString)), this,
            SLOT(load_file(QString)));
150
    connect(_file_bar, SIGNAL(on_save()), this,
DreamSourceLab's avatar
DreamSourceLab committed
151
            SLOT(on_save()));
152 153
    connect(_file_bar, SIGNAL(on_export()), this,
            SLOT(on_export()));
DreamSourceLab's avatar
DreamSourceLab committed
154
    connect(_file_bar, SIGNAL(on_screenShot()), this,
155
            SLOT(on_screenShot()), Qt::QueuedConnection);
156 157 158 159
    connect(_file_bar, SIGNAL(load_session(QString)), this,
            SLOT(load_session(QString)));
    connect(_file_bar, SIGNAL(store_session(QString)), this,
            SLOT(store_session(QString)));
Andy Dneg's avatar
Andy Dneg committed
160 161 162 163
    connect(_logo_bar, SIGNAL(setLanguage(int)), this,
            SLOT(switchLanguage(int)));
    connect(_logo_bar, SIGNAL(openDoc()), this,
            SLOT(openDoc()));
DreamSourceLab's avatar
DreamSourceLab committed
164 165 166

    // trigger dock
    _trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
Andy Dneg's avatar
Andy Dneg committed
167
    _trigger_dock->setObjectName("trigger_dock");
168
    _trigger_dock->setFeatures(QDockWidget::DockWidgetMovable);
DreamSourceLab's avatar
DreamSourceLab committed
169 170 171 172 173
    _trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea);
    _trigger_dock->setVisible(false);
    _trigger_widget = new dock::TriggerDock(_trigger_dock, _session);
    _trigger_dock->setWidget(_trigger_widget);

DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
174
    _dso_trigger_dock=new QDockWidget(tr("Trigger Setting..."),this);
Andy Dneg's avatar
Andy Dneg committed
175
    _dso_trigger_dock->setObjectName("dso_trigger_dock");
176
    _dso_trigger_dock->setFeatures(QDockWidget::DockWidgetMovable);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
177 178 179 180 181 182
    _dso_trigger_dock->setAllowedAreas(Qt::RightDockWidgetArea);
    _dso_trigger_dock->setVisible(false);
    _dso_trigger_widget = new dock::DsoTriggerDock(_dso_trigger_dock, _session);
    _dso_trigger_dock->setWidget(_dso_trigger_widget);


DreamSourceLab's avatar
DreamSourceLab committed
183
    // Setup _view widget
DreamSourceLab's avatar
DreamSourceLab committed
184
    _view = new pv::view::View(_session, _sampling_bar, this);
DreamSourceLab's avatar
DreamSourceLab committed
185 186
    _vertical_layout->addWidget(_view);

DreamSourceLab's avatar
DreamSourceLab committed
187 188
    connect(_sampling_bar, SIGNAL(device_selected()), this,
            SLOT(update_device_list()));
189
    connect(_sampling_bar, SIGNAL(device_updated()), this,
DreamSourceLab's avatar
DreamSourceLab committed
190
        SLOT(reload()));
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
191 192
    connect(_sampling_bar, SIGNAL(run_stop()), this,
        SLOT(run_stop()));
DreamSourceLab's avatar
DreamSourceLab committed
193 194
    connect(_sampling_bar, SIGNAL(instant_stop()), this,
        SLOT(instant_stop()));
195
    connect(_sampling_bar, SIGNAL(duration_changed()), _trigger_widget,
196
        SLOT(device_updated()));
197 198
    connect(_sampling_bar, SIGNAL(duration_changed()), _view,
        SLOT(timebase_changed()));
199 200
    connect(_sampling_bar, SIGNAL(show_calibration()), _view,
        SLOT(show_calibration()));
Andy Dneg's avatar
Andy Dneg committed
201 202
    connect(_trig_bar, SIGNAL(show_lissajous(bool)), _view,
        SLOT(show_lissajous(bool)));
203 204
    connect(_dso_trigger_widget, SIGNAL(set_trig_pos(int)), _view,
        SLOT(set_trig_pos(int)));
205 206
    connect(_view, SIGNAL(auto_trig(int)), _dso_trigger_widget,
        SLOT(auto_trig(int)));
DreamSourceLab's avatar
DreamSourceLab committed
207

208
    setIconSize(QSize(40,40));
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
209
    addToolBar(_sampling_bar);
DreamSourceLab's avatar
DreamSourceLab committed
210 211 212 213 214
    addToolBar(_trig_bar);
    addToolBar(_file_bar);
    addToolBar(_logo_bar);

    // Setup the dockWidget
215 216 217
#ifdef ENABLE_DECODE
    // protocol dock
    _protocol_dock=new QDockWidget(tr("Protocol"),this);
Andy Dneg's avatar
Andy Dneg committed
218
    _protocol_dock->setObjectName("protocol_dock");
219 220 221 222 223 224 225 226 227 228
    _protocol_dock->setFeatures(QDockWidget::DockWidgetMovable);
    _protocol_dock->setAllowedAreas(Qt::RightDockWidgetArea);
    _protocol_dock->setVisible(false);
    //dock::ProtocolDock *_protocol_widget = new dock::ProtocolDock(_protocol_dock, _session);
    _protocol_widget = new dock::ProtocolDock(_protocol_dock, *_view, _session);
    _protocol_dock->setWidget(_protocol_widget);
    qDebug() << "Protocol decoder enabled!\n";

    connect(_protocol_widget, SIGNAL(protocol_updated()), _view, SLOT(signals_changed()));
#endif
DreamSourceLab's avatar
DreamSourceLab committed
229 230
    // measure dock
    _measure_dock=new QDockWidget(tr("Measurement"),this);
Andy Dneg's avatar
Andy Dneg committed
231
    _measure_dock->setObjectName("measure_dock");
232
    _measure_dock->setFeatures(QDockWidget::DockWidgetMovable);
DreamSourceLab's avatar
DreamSourceLab committed
233 234
    _measure_dock->setAllowedAreas(Qt::RightDockWidgetArea);
    _measure_dock->setVisible(false);
235
    _measure_widget = new dock::MeasureDock(_measure_dock, *_view, _session);
DreamSourceLab's avatar
DreamSourceLab committed
236 237 238
    _measure_dock->setWidget(_measure_widget);
    // search dock
    _search_dock=new QDockWidget(tr("Search..."), this);
Andy Dneg's avatar
Andy Dneg committed
239
    _search_dock->setObjectName("search_dock");
DreamSourceLab's avatar
DreamSourceLab committed
240 241 242 243 244 245 246 247
    _search_dock->setFeatures(QDockWidget::NoDockWidgetFeatures);
    _search_dock->setTitleBarWidget(new QWidget(_search_dock));
    _search_dock->setAllowedAreas(Qt::BottomDockWidgetArea);
    _search_dock->setVisible(false);
    //dock::SearchDock *_search_widget = new dock::SearchDock(_search_dock, *_view, _session);
    _search_widget = new dock::SearchDock(_search_dock, *_view, _session);
    _search_dock->setWidget(_search_widget);

DreamSourceLab's avatar
DreamSourceLab committed
248
#ifdef ENABLE_DECODE
DreamSourceLab's avatar
DreamSourceLab committed
249
    addDockWidget(Qt::RightDockWidgetArea,_protocol_dock);
DreamSourceLab's avatar
DreamSourceLab committed
250
#endif
DreamSourceLab's avatar
DreamSourceLab committed
251
    addDockWidget(Qt::RightDockWidgetArea,_trigger_dock);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
252
    addDockWidget(Qt::RightDockWidgetArea,_dso_trigger_dock);
DreamSourceLab's avatar
DreamSourceLab committed
253 254 255 256
    addDockWidget(Qt::RightDockWidgetArea, _measure_dock);
    addDockWidget(Qt::BottomDockWidgetArea, _search_dock);

	// Set the title
DreamSourceLab's avatar
DreamSourceLab committed
257 258
    QString title = QApplication::applicationName()+" v"+QApplication::applicationVersion();
    std::string std_title = title.toStdString();
Diego F. Asanza's avatar
Diego F. Asanza committed
259
    setWindowTitle(QApplication::translate("MainWindow", std_title.c_str(), 0));
DreamSourceLab's avatar
DreamSourceLab committed
260 261 262 263 264

	// Setup _session events
	connect(&_session, SIGNAL(capture_state_changed(int)), this,
		SLOT(capture_state_changed(int)));
    connect(&_session, SIGNAL(device_attach()), this,
265
            SLOT(device_attach()), Qt::QueuedConnection);
DreamSourceLab's avatar
DreamSourceLab committed
266
    connect(&_session, SIGNAL(device_detach()), this,
267
            SLOT(device_detach()), Qt::QueuedConnection);
268 269 270
    connect(&_session, SIGNAL(session_error()), this,
            SLOT(show_error()), Qt::QueuedConnection);
    connect(&_session, SIGNAL(session_save()), this,
271
            SLOT(session_save()));
272 273 274 275
    connect(&_session, SIGNAL(data_updated()), _measure_widget,
            SLOT(reCalc()));
    connect(&_session, SIGNAL(repeat_resume()), this,
            SLOT(repeat_resume()));
276 277
    connect(&_session, SIGNAL(update_capture()), _view,
            SLOT(update_hori_res()), Qt::DirectConnection);
DreamSourceLab's avatar
DreamSourceLab committed
278

279
    connect(&_session, SIGNAL(cur_snap_samplerate_changed()), _measure_widget,
280
            SLOT(cursor_update()));
DreamSourceLab's avatar
DreamSourceLab committed
281 282
    connect(_view, SIGNAL(cursor_update()), _measure_widget,
            SLOT(cursor_update()));
283 284
    connect(_view, SIGNAL(cursor_moving()), _measure_widget,
            SLOT(cursor_moving()));
DreamSourceLab's avatar
DreamSourceLab committed
285
    connect(_view, SIGNAL(cursor_moved()), _measure_widget,
286 287
            SLOT(reCalc()));
    connect(_view, SIGNAL(prgRate(int)), this, SIGNAL(prgRate(int)));
Andy Dneg's avatar
Andy Dneg committed
288 289
    connect(_view, SIGNAL(device_changed(bool)),
            this, SLOT(device_changed(bool)), Qt::DirectConnection);
DreamSourceLab's avatar
DreamSourceLab committed
290 291 292 293 294 295 296 297 298 299 300 301 302 303

    // event filter
    _view->installEventFilter(this);
    _sampling_bar->installEventFilter(this);
    _trig_bar->installEventFilter(this);
    _file_bar->installEventFilter(this);
    _logo_bar->installEventFilter(this);
    _dso_trigger_dock->installEventFilter(this);
    _trigger_dock->installEventFilter(this);
#ifdef ENABLE_DECODE
    _protocol_dock->installEventFilter(this);
#endif
    _measure_dock->installEventFilter(this);
    _search_dock->installEventFilter(this);
DreamSourceLab's avatar
DreamSourceLab committed
304

DreamSourceLab's avatar
DreamSourceLab committed
305
    // Populate the device list and select the initially selected device
DreamSourceLab's avatar
DreamSourceLab committed
306
    _session.set_default_device(boost::bind(&MainWindow::session_error, this,
307
                                            QString(tr("Set Default Device failed")), _1));
Andy Dneg's avatar
Andy Dneg committed
308 309 310 311 312 313 314 315 316 317 318 319 320

    // defaut language
    QSettings settings(QApplication::organizationName(), QApplication::applicationName());
    QLocale locale;
    settings.beginGroup("MainFrame");
    switchLanguage(settings.value("language", locale.language()).toInt());
    switchTheme(settings.value("style", "dark").toString());
    settings.endGroup();

    // UI initial
    _measure_widget->add_dist_measure();

    // update device
DreamSourceLab's avatar
DreamSourceLab committed
321 322
    update_device_list();
    _session.start_hotplug_proc(boost::bind(&MainWindow::session_error, this,
323
                                             QString(tr("Hotplug failed")), _1));
Andy Dneg's avatar
Andy Dneg committed
324 325 326 327 328 329 330 331 332 333 334 335

    retranslateUi();
}


void MainWindow::retranslateUi()
{
    _trigger_dock->setWindowTitle(tr("Trigger Setting..."));
    _dso_trigger_dock->setWindowTitle(tr("Trigger Setting..."));
    _protocol_dock->setWindowTitle(tr("Protocol"));
    _measure_dock->setWindowTitle(tr("Measurement"));
    _search_dock->setWindowTitle(tr("Search..."));
DreamSourceLab's avatar
DreamSourceLab committed
336 337 338 339 340 341 342 343 344 345
}

void MainWindow::session_error(
	const QString text, const QString info_text)
{
	QMetaObject::invokeMethod(this, "show_session_error",
		Qt::QueuedConnection, Q_ARG(QString, text),
		Q_ARG(QString, info_text));
}

DreamSourceLab's avatar
DreamSourceLab committed
346
void MainWindow::update_device_list()
DreamSourceLab's avatar
DreamSourceLab committed
347
{
DreamSourceLab's avatar
DreamSourceLab committed
348
    assert(_sampling_bar);
DreamSourceLab's avatar
DreamSourceLab committed
349

350 351 352
    if (_msg)
        _msg->close();

Andy Dneg's avatar
Andy Dneg committed
353
    switchLanguage(_language);
354
    _session.stop_capture();
355
    _view->reload();
356
    _trigger_widget->device_updated();
DreamSourceLab's avatar
DreamSourceLab committed
357 358 359
#ifdef ENABLE_DECODE
    _protocol_widget->del_all_protocol();
#endif
DreamSourceLab's avatar
DreamSourceLab committed
360
    _trig_bar->reload();
DreamSourceLab's avatar
DreamSourceLab committed
361

DreamSourceLab's avatar
DreamSourceLab committed
362 363 364
    shared_ptr<pv::device::DevInst> selected_device = _session.get_device();
    _device_manager.add_device(selected_device);
    _session.init_signals();
365
    _sampling_bar->set_device_list(_device_manager.devices(), selected_device);
DreamSourceLab's avatar
DreamSourceLab committed
366

367
    shared_ptr<pv::device::File> file_dev;
368
    if((file_dev = dynamic_pointer_cast<pv::device::File>(selected_device))) {
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
        // check version
        if (selected_device->dev_inst()->mode == LOGIC) {
            GVariant* gvar = selected_device->get_config(NULL, NULL, SR_CONF_FILE_VERSION);
            if (gvar != NULL) {
                int16_t version = g_variant_get_int16(gvar);
                g_variant_unref(gvar);
                if (version == 1) {
                    show_session_error(tr("Attension"),
                                       tr("Current loading file has an old format. "
                                          "This will lead to a slow loading speed. "
                                          "Please resave it after loaded."));
                }
            }
        }

Andy Dneg's avatar
Andy Dneg committed
384 385 386 387 388 389 390 391 392
        #ifdef ENABLE_DECODE
        // load decoders
        StoreSession ss(_session);
        ss.load_decoders(_protocol_widget, file_dev->get_decoders());
        #endif

        // load session
        load_session_json(file_dev->get_session(), true);

393
        // load data
DreamSourceLab's avatar
DreamSourceLab committed
394
        const QString errorMessage(
395
            QString(tr("Failed to capture file data!")));
DreamSourceLab's avatar
DreamSourceLab committed
396
        _session.start_capture(true, boost::bind(&MainWindow::session_error, this,
397
            errorMessage, _1));
DreamSourceLab's avatar
DreamSourceLab committed
398
    }
DreamSourceLab's avatar
DreamSourceLab committed
399

400
    if (!selected_device->name().contains("virtual")) {
401
        _file_bar->set_settings_en(true);
DreamSourceLab's avatar
DreamSourceLab committed
402
        _logo_bar->dsl_connected(true);
403 404 405 406 407 408 409
        #if QT_VERSION >= 0x050400
        QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
        #else
        QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
        #endif
        if (dir.exists()) {
            QString str = dir.absolutePath() + "/";
Andy Dneg's avatar
Andy Dneg committed
410
            QString lang_name = ".ses" + QString::number(_language);
411 412 413
            QString ses_name = str +
                               selected_device->name() +
                               QString::number(selected_device->dev_inst()->mode) +
Andy Dneg's avatar
Andy Dneg committed
414
                               lang_name + ".dsc";
415 416
            load_session(ses_name);
        }
417
    } else {
418
        _file_bar->set_settings_en(false);
DreamSourceLab's avatar
DreamSourceLab committed
419
        _logo_bar->dsl_connected(false);
Andy Dneg's avatar
Andy Dneg committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
        #ifdef Q_OS_LINUX
            QDir dir(DS_RES_PATH);
        #else
            QDir dir(QCoreApplication::applicationDirPath());
            assert(dir.cd("res"));
        #endif
        if (dir.exists()) {
            QString str = dir.absolutePath() + "/";
            QString ses_name = str +
                               selected_device->name() +
                               QString::number(selected_device->dev_inst()->mode) +
                               ".dsc";
            if (QFileInfo(ses_name).exists())
                load_session(ses_name);
        }
435
    }
436
    _sampling_bar->reload();
437
    _view->status_clear();
438 439
    _trigger_widget->init();
    _dso_trigger_widget->init();
440
	_measure_widget->reload();
441 442 443

    // USB device speed check
    if (!selected_device->name().contains("virtual")) {
444
        int usb_speed = LIBUSB_SPEED_HIGH;
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
        GVariant *gvar = selected_device->get_config(NULL, NULL, SR_CONF_USB_SPEED);
        if (gvar != NULL) {
            usb_speed = g_variant_get_int32(gvar);
            g_variant_unref(gvar);
        }

        bool usb30_support = false;
        gvar = selected_device->get_config(NULL, NULL, SR_CONF_USB30_SUPPORT);
        if (gvar != NULL) {
            usb30_support = g_variant_get_boolean(gvar);
            g_variant_unref(gvar);

            if (usb30_support && usb_speed == LIBUSB_SPEED_HIGH)
                show_session_error(tr("Speed limited"), tr("This is a super-speed usb device(USB 3.0). "
                                                           "Plug it into a USB 2.0 port will seriously affect its performance."
                                                           "Please replug it into a USB 3.0 port."));
        }
    }

DreamSourceLab's avatar
DreamSourceLab committed
464 465
}

466 467
void MainWindow::reload()
{
468
    _trigger_widget->device_updated();
469
    _session.reload();
470
    _measure_widget->reload();
471 472
}

DreamSourceLab's avatar
DreamSourceLab committed
473 474
void MainWindow::load_file(QString file_name)
{
DreamSourceLab's avatar
DreamSourceLab committed
475
    try {
476 477
        if (strncmp(_session.get_device()->name().toLocal8Bit(), "virtual", 7))
            session_save();
478
        _session.set_file(file_name);
DreamSourceLab's avatar
DreamSourceLab committed
479 480
    } catch(QString e) {
        show_session_error(tr("Failed to load ") + file_name, e);
DreamSourceLab's avatar
DreamSourceLab committed
481
        _session.set_default_device(boost::bind(&MainWindow::session_error, this,
482
                                                QString(tr("Set Default Device failed")), _1));
DreamSourceLab's avatar
DreamSourceLab committed
483 484 485 486 487
        update_device_list();
        return;
    }

    update_device_list();
DreamSourceLab's avatar
DreamSourceLab committed
488 489 490 491 492
}

void MainWindow::show_session_error(
	const QString text, const QString info_text)
{
493
    dialogs::DSMessageBox msg(this);
494
    _msg = &msg;
495 496 497 498
    msg.mBox()->setText(text);
    msg.mBox()->setInformativeText(info_text);
    msg.mBox()->setStandardButtons(QMessageBox::Ok);
    msg.mBox()->setIcon(QMessageBox::Warning);
DreamSourceLab's avatar
DreamSourceLab committed
499
	msg.exec();
500
    _msg = NULL;
DreamSourceLab's avatar
DreamSourceLab committed
501 502 503 504
}

void MainWindow::device_attach()
{
505
    _session.get_device()->device_updated();
DreamSourceLab's avatar
DreamSourceLab committed
506
    //_session.stop_hot_plug_proc();
DreamSourceLab's avatar
DreamSourceLab committed
507

508 509 510 511
    _session.set_repeating(false);
    _session.stop_capture();
    _sampling_bar->set_sampling(false);
    _session.capture_state_changed(SigSession::Stopped);
DreamSourceLab's avatar
DreamSourceLab committed
512 513 514

    struct sr_dev_driver **const drivers = sr_driver_list();
    struct sr_dev_driver **driver;
DreamSourceLab's avatar
DreamSourceLab committed
515 516 517
    for (driver = drivers; *driver; driver++)
        if (*driver)
            _device_manager.driver_scan(*driver);
DreamSourceLab's avatar
DreamSourceLab committed
518

DreamSourceLab's avatar
DreamSourceLab committed
519
    _session.set_default_device(boost::bind(&MainWindow::session_error, this,
520
                                            QString(tr("Set Default Device failed")), _1));
DreamSourceLab's avatar
DreamSourceLab committed
521
    update_device_list();
522

DreamSourceLab's avatar
DreamSourceLab committed
523 524 525 526
}

void MainWindow::device_detach()
{
527
    _session.get_device()->device_updated();
DreamSourceLab's avatar
DreamSourceLab committed
528
    //_session.stop_hot_plug_proc();
DreamSourceLab's avatar
DreamSourceLab committed
529

530 531 532 533
    _session.set_repeating(false);
    _session.stop_capture();
    _sampling_bar->set_sampling(false);
    _session.capture_state_changed(SigSession::Stopped);
DreamSourceLab's avatar
DreamSourceLab committed
534

535
    session_save();
536
    _view->hide_calibration();
537

DreamSourceLab's avatar
DreamSourceLab committed
538 539
    struct sr_dev_driver **const drivers = sr_driver_list();
    struct sr_dev_driver **driver;
DreamSourceLab's avatar
DreamSourceLab committed
540 541 542
    for (driver = drivers; *driver; driver++)
        if (*driver)
            _device_manager.driver_scan(*driver);
DreamSourceLab's avatar
DreamSourceLab committed
543

DreamSourceLab's avatar
DreamSourceLab committed
544
    _session.set_default_device(boost::bind(&MainWindow::session_error, this,
545
                                            QString(tr("Set Default Device failed")), _1));
DreamSourceLab's avatar
DreamSourceLab committed
546
    update_device_list();
DreamSourceLab's avatar
DreamSourceLab committed
547 548
}

Andy Dneg's avatar
Andy Dneg committed
549 550 551 552 553 554 555 556 557 558
void MainWindow::device_changed(bool close)
{
    if (close) {
        _sampling_bar->set_sampling(false);
        _session.set_default_device(boost::bind(&MainWindow::session_error, this,
                                                QString(tr("Set Default Device failed")), _1));
    }
    update_device_list();
}

DreamSourceLab's avatar
DreamSourceLab committed
559 560 561 562
void MainWindow::run_stop()
{
    switch(_session.get_capture_state()) {
    case SigSession::Init:
563
    case SigSession::Stopped:
564
        commit_trigger(false);
DreamSourceLab's avatar
DreamSourceLab committed
565
        _session.start_capture(false,
566 567
            boost::bind(&MainWindow::session_error, this,
                QString(tr("Capture failed")), _1));
568
        _view->capture_init();
DreamSourceLab's avatar
DreamSourceLab committed
569
        break;
DreamSourceLab's avatar
DreamSourceLab committed
570

571 572 573 574
    case SigSession::Running:
        _session.stop_capture();
        break;
    }
DreamSourceLab's avatar
DreamSourceLab committed
575 576
}

DreamSourceLab's avatar
DreamSourceLab committed
577
void MainWindow::instant_stop()
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
578
{
DreamSourceLab's avatar
DreamSourceLab committed
579 580 581
    switch(_session.get_capture_state()) {
    case SigSession::Init:
    case SigSession::Stopped:
582
        commit_trigger(true);
DreamSourceLab's avatar
DreamSourceLab committed
583 584
        _session.start_capture(true,
            boost::bind(&MainWindow::session_error, this,
585
                QString(tr("Capture failed")), _1));
586
        _view->capture_init();
DreamSourceLab's avatar
DreamSourceLab committed
587 588 589 590 591
        break;

    case SigSession::Running:
        _session.stop_capture();
        break;
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
592 593 594
    }
}

595
void MainWindow::repeat_resume()
DreamSourceLab's avatar
DreamSourceLab committed
596
{
597 598 599
    while(_view->session().get_capture_state() == SigSession::Running)
        QCoreApplication::processEvents();
    run_stop();
DreamSourceLab's avatar
DreamSourceLab committed
600 601
}

602
void MainWindow::show_error()
DreamSourceLab's avatar
DreamSourceLab committed
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
    QString title;
    QString details;
    QString ch_status = "";
    uint64_t error_pattern;

    switch(_session.get_error()) {
    case SigSession::Hw_err:
        _session.set_repeating(false);
        _session.stop_capture();
        title = tr("Hardware Operation Failed");
        details = tr("Please replug device to refresh hardware configuration!");
        break;
    case SigSession::Malloc_err:
        _session.set_repeating(false);
        _session.stop_capture();
        title = tr("Malloc Error");
        details = tr("Memory is not enough for this sample!\nPlease reduce the sample depth!");
        break;
    case SigSession::Test_data_err:
        _session.set_repeating(false);
        _session.stop_capture();
        _sampling_bar->set_sampling(false);
        _session.capture_state_changed(SigSession::Stopped);
        title = tr("Data Error");
        error_pattern = _session.get_error_pattern();
        for(int i = 0; i < 16; i++) {
            if (error_pattern & 0x01)
                ch_status += "X ";
            else
                ch_status += "  ";
            ch_status += (i > 9 ? " " : "");
            error_pattern >>= 1;
        }
637 638
        details = tr("the received data are not consist with pre-defined test data!") + "\n" +
                  tr("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15")+ "\n" + ch_status;
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        break;
    case SigSession::Pkt_data_err:
        title = tr("Packet Error");
        details = tr("the content of received packet are not expected!");
        _session.refresh(0);
        break;
    case SigSession::Data_overflow:
        _session.set_repeating(false);
        _session.stop_capture();
        title = tr("Data Overflow");
        details = tr("USB bandwidth can not support current sample rate! \nPlease reduce the sample rate!");
        break;
    default:
        title = tr("Undefined Error");
        details = tr("Not expected error!");
        break;
    }
DreamSourceLab's avatar
DreamSourceLab committed
656

657
    dialogs::DSMessageBox msg(this);
658 659 660 661 662 663 664 665
    connect(_session.get_device().get(), SIGNAL(device_updated()), &msg, SLOT(accept()));
    QFont font("Monaco");
    font.setStyleHint(QFont::Monospace);
    font.setFixedPitch(true);
    msg.mBox()->setFont(font);

    msg.mBox()->setText(title);
    msg.mBox()->setInformativeText(details);
666 667
    msg.mBox()->setStandardButtons(QMessageBox::Ok);
    msg.mBox()->setIcon(QMessageBox::Warning);
668
    msg.exec();
669 670

    _session.clear_error();
671 672
}

DreamSourceLab's avatar
DreamSourceLab committed
673 674
void MainWindow::capture_state_changed(int state)
{
675 676 677 678 679
    if (!_session.repeat_check()) {
        _file_bar->enable_toggle(state != SigSession::Running);
        _sampling_bar->set_sampling(state == SigSession::Running);
        _view->on_state_changed(state != SigSession::Running);

680 681
        if (_session.get_device()->dev_inst()->mode != DSO ||
            _session.get_instant()) {
682 683 684 685 686
            _sampling_bar->enable_toggle(state != SigSession::Running);
            _trig_bar->enable_toggle(state != SigSession::Running);
            //_measure_dock->widget()->setEnabled(state != SigSession::Running);
            _measure_widget->refresh();
        }
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
687
    }
688 689

    if (state == SigSession::Stopped) {
690 691
        prgRate(0);
        _view->repeat_unshow();
692
    }
DreamSourceLab's avatar
DreamSourceLab committed
693 694
}

695
void MainWindow::session_save()
696
{
697 698 699 700 701 702 703 704
    QDir dir;
    #if QT_VERSION >= 0x050400
    QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    #else
    QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    #endif
    if(dir.mkpath(path)) {
        dir.cd(path);
705
        QString driver_name = _session.get_device()->name();
706
        QString mode_name = QString::number(_session.get_device()->dev_inst()->mode);
Andy Dneg's avatar
Andy Dneg committed
707 708 709 710
        QString lang_name = ".ses" + QString::number(_language);
        QString file_name = dir.absolutePath() + "/" +
                            driver_name + mode_name +
                            lang_name + ".dsc";
711
        if (strncmp(driver_name.toLocal8Bit(), "virtual", 7) &&
712
            !file_name.isEmpty()) {
713
            store_session(file_name);
714
        }
715
    }
Andy Dneg's avatar
Andy Dneg committed
716 717 718

    QSettings settings(QApplication::organizationName(), QApplication::applicationName());
    settings.setValue("windowState", saveState());
719 720 721 722
}

void MainWindow::closeEvent(QCloseEvent *event)
{
Andy Dneg's avatar
Andy Dneg committed
723
    // not used, refer to closeEvent of mainFrame
724
    session_save();
725 726 727
    event->accept();
}

DreamSourceLab's avatar
DreamSourceLab committed
728 729
void MainWindow::on_protocol(bool visible)
{
DreamSourceLab's avatar
DreamSourceLab committed
730
#ifdef ENABLE_DECODE
DreamSourceLab's avatar
DreamSourceLab committed
731
    _protocol_dock->setVisible(visible);
DreamSourceLab's avatar
DreamSourceLab committed
732
#endif
DreamSourceLab's avatar
DreamSourceLab committed
733 734 735 736
}

void MainWindow::on_trigger(bool visible)
{
DreamSourceLab's avatar
DreamSourceLab committed
737
    if (_session.get_device()->dev_inst()->mode != DSO) {
DreamSourceLab's avatar
DreamSourceLab committed
738
        _trigger_widget->init();
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
739
        _trigger_dock->setVisible(visible);
DreamSourceLab's avatar
DreamSourceLab committed
740 741
        _dso_trigger_dock->setVisible(false);
    } else {
DreamSourceLab's avatar
DreamSourceLab committed
742
        _dso_trigger_widget->init();
DreamSourceLab's avatar
DreamSourceLab committed
743
        _trigger_dock->setVisible(false);
DreamSourceLab's avatar
v0.3  
DreamSourceLab committed
744
        _dso_trigger_dock->setVisible(visible);
DreamSourceLab's avatar
DreamSourceLab committed
745
    }
746
    _trig_bar->update_trig_btn(visible);
DreamSourceLab's avatar
DreamSourceLab committed
747 748
}

749 750
void MainWindow::commit_trigger(bool instant)
{
751 752
    int i = 0;
    const QString TRIG_KEY("WarnofMultiTrig");
Andy Dneg's avatar
Andy Dneg committed
753
    QSettings settings(QApplication::organizationName(), QApplication::applicationName());
754

755 756 757 758 759 760 761 762 763 764 765 766
    ds_trigger_init();

    if (_session.get_device()->dev_inst()->mode != LOGIC ||
        instant)
        return;

    if (!_trigger_widget->commit_trigger()) {
        /* simple trigger check trigger_enable */
        BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals())
        {
            assert(s);
            boost::shared_ptr<view::LogicSignal> logicSig;
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
            if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s))) {
                if (logicSig->commit_trig())
                    i++;
            }
        }
        if (!settings.contains(TRIG_KEY) &&
            i > 1) {
            dialogs::DSMessageBox msg(this);
            msg.mBox()->setText(tr("Trigger"));
            msg.mBox()->setInformativeText(tr("Trigger setted on multiple channels! "
                                              "Capture will Only triggered when all setted channels fullfill at one sample"));
            msg.mBox()->setIcon(QMessageBox::Information);

            QPushButton *noMoreButton = msg.mBox()->addButton(tr("Not Show Again"), QMessageBox::ActionRole);
            QPushButton *cancelButton = msg.mBox()->addButton(tr("Clear Trig"), QMessageBox::ActionRole);
            msg.mBox()->addButton(tr("Continue"), QMessageBox::ActionRole);

            msg.exec();
            if (msg.mBox()->clickedButton() == cancelButton) {
                BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals())
                {
                    assert(s);
                    boost::shared_ptr<view::LogicSignal> logicSig;
                    if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s))) {
                        logicSig->set_trig(view::LogicSignal::NONTRIG);
                        logicSig->commit_trig();
                    }
                }
            }
            if (msg.mBox()->clickedButton() == noMoreButton)
                  settings.setValue(TRIG_KEY, false);
798 799 800 801
        }
    }
}

DreamSourceLab's avatar
DreamSourceLab committed
802 803 804 805 806 807 808 809 810 811 812 813 814
void MainWindow::on_measure(bool visible)
{
    _measure_dock->setVisible(visible);
}

void MainWindow::on_search(bool visible)
{
    _search_dock->setVisible(visible);
    _view->show_search_cursor(visible);
}

void MainWindow::on_screenShot()
{
815
    const QString DIR_KEY("ScreenShotPath");
Andy Dneg's avatar
Andy Dneg committed
816
    QSettings settings(QApplication::organizationName(), QApplication::applicationName());
817
    QString default_name = settings.value(DIR_KEY).toString() + "/DSView" + QDateTime::currentDateTime().toString("-yyMMdd-hhmmss");
DreamSourceLab's avatar
DreamSourceLab committed
818 819
    QPixmap pixmap;
    QDesktopWidget *desktop = QApplication::desktop();
820 821
    pixmap = QPixmap::grabWindow(desktop->winId(), parentWidget()->pos().x(), parentWidget()->pos().y(),
                                                   parentWidget()->frameGeometry().width(), parentWidget()->frameGeometry().height());
DreamSourceLab's avatar
DreamSourceLab committed
822 823 824
    QString format = "png";

    QString fileName = QFileDialog::getSaveFileName(this,
825
                       tr("Save As"), default_name,
DreamSourceLab's avatar
DreamSourceLab committed
826 827
                       tr("%1 Files (*.%2);;All Files (*)")
                       .arg(format.toUpper()).arg(format));
828 829
    if (!fileName.isEmpty()) {
        QDir CurrentDir;
830
        settings.setValue(DIR_KEY, CurrentDir.filePath(fileName));
Diego F. Asanza's avatar
Diego F. Asanza committed
831
        pixmap.save(fileName, format.toLatin1());
832
    }
DreamSourceLab's avatar
DreamSourceLab committed
833 834
}

DreamSourceLab's avatar
DreamSourceLab committed
835 836 837
void MainWindow::on_save()
{
    using pv::dialogs::StoreProgress;
Andy Dneg's avatar
Andy Dneg committed
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855

//    dialogs::RegionOptions *regionDlg = new dialogs::RegionOptions(_view, _session, this);
//    regionDlg->exec();

    QString session_file;
    QDir dir;
    #if QT_VERSION >= 0x050400
    QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    #else
    QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
    #endif
    if(dir.mkpath(path)) {
        dir.cd(path);

        session_file = dir.absolutePath() + "/DSView-session-XXXXXX";
        store_session(session_file);
    }

856
    StoreProgress *dlg = new StoreProgress(_session, this);
Andy Dneg's avatar
Andy Dneg committed
857
    dlg->save_run(session_file);
858
}
DreamSourceLab's avatar
DreamSourceLab committed
859

860 861 862
void MainWindow::on_export()
{
    using pv::dialogs::StoreProgress;
Andy Dneg's avatar
Andy Dneg committed
863 864 865 866

//    dialogs::RegionOptions *regionDlg = new dialogs::RegionOptions(_view, _session, this);
//    regionDlg->exec();

867 868
    StoreProgress *dlg = new StoreProgress(_session, this);
    dlg->export_run();
DreamSourceLab's avatar
DreamSourceLab committed
869 870
}

871 872
bool MainWindow::load_session(QString name)
{
873
    QFile sessionFile(name);
874
    if (!sessionFile.open(QIODevice::ReadOnly)) {
875
        qDebug("Warning: Couldn't open session file!");
876 877 878
        return false;
    }

879 880
    QString sessionData = QString::fromUtf8(sessionFile.readAll());
    QJsonDocument sessionDoc = QJsonDocument::fromJson(sessionData.toUtf8());
Andy Dneg's avatar
Andy Dneg committed
881 882 883 884 885 886 887

    return load_session_json(sessionDoc, false);
}

bool MainWindow::load_session_json(QJsonDocument json, bool file_dev)
{
    QJsonObject sessionObj = json.object();
888

889 890 891 892 893
    // check session file version
    if (!sessionObj.contains("Version") ||
        sessionObj["Version"].toInt() != Session_Version)
        return false;

894 895
    // check device and mode
    const sr_dev_inst *const sdi = _session.get_device()->dev_inst();
Andy Dneg's avatar
Andy Dneg committed
896
    if ((!file_dev && strcmp(sdi->driver->name, sessionObj["Device"].toString().toLocal8Bit()) != 0) ||
897
        sdi->mode != sessionObj["DeviceMode"].toDouble()) {
898 899 900 901 902
        dialogs::DSMessageBox msg(this);
        msg.mBox()->setText(tr("Session Error"));
        msg.mBox()->setInformativeText(tr("Session File is not compatible with current device or mode!"));
        msg.mBox()->setStandardButtons(QMessageBox::Ok);
        msg.mBox()->setIcon(QMessageBox::Warning);
903 904 905 906
        msg.exec();
        return false;
    }

Andy Dneg's avatar
Andy Dneg committed
907 908 909
    // check language
    if (sessionObj.contains("Language")) {
        switchLanguage(sessionObj["Language"].toInt());
910
    } else if (sessionObj.contains("Operation Mode")) {
Andy Dneg's avatar
Andy Dneg committed
911 912 913 914 915 916 917 918 919 920
        bool language_matched = _session.get_device()->set_config(NULL, NULL, SR_CONF_OPERATION_MODE,
                                          g_variant_new_string(sessionObj["Operation Mode"].toString().toUtf8()));
        if (!language_matched) {
            if (_language != QLocale::Chinese)
                switchLanguage(QLocale::Chinese);
            else
                switchLanguage(QLocale::English);
        }
    }

921 922 923 924 925 926 927
    // clear decoders
    #ifdef ENABLE_DECODE
    if (sdi->mode == LOGIC) {
        _protocol_widget->del_all_protocol();
    }
    #endif

928 929 930 931 932 933 934 935 936
    // load device settings
    GVariant *gvar_opts;
    gsize num_opts;
    if ((sr_config_list(sdi->driver, sdi, NULL, SR_CONF_DEVICE_SESSIONS, &gvar_opts) == SR_OK)) {
        const int *const options = (const int32_t *)g_variant_get_fixed_array(
            gvar_opts, &num_opts, sizeof(int32_t));
        for (unsigned int i = 0; i < num_opts; i++) {
            const struct sr_config_info *const info =
                sr_config_info_get(options[i]);
937 938
            if (!sessionObj.contains(info->name))
                continue;
939 940 941 942 943 944 945 946 947
            if (info->datatype == SR_T_BOOL)
                _session.get_device()->set_config(NULL, NULL, info->key, g_variant_new_boolean(sessionObj[info->name].toDouble()));
            else if (info->datatype == SR_T_UINT64)
                _session.get_device()->set_config(NULL, NULL, info->key, g_variant_new_uint64(sessionObj[info->name].toString().toULongLong()));
            else if (info->datatype == SR_T_UINT8)
                _session.get_device()->set_config(NULL, NULL, info->key, g_variant_new_byte(sessionObj[info->name].toString().toUInt()));
            else if (info->datatype == SR_T_FLOAT)
                _session.get_device()->set_config(NULL, NULL, info->key, g_variant_new_double(sessionObj[info->name].toDouble()));
            else if (info->datatype == SR_T_CHAR)
948
                _session.get_device()->set_config(NULL, NULL, info->key, g_variant_new_string(sessionObj[info->name].toString().toUtf8()));
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
        }
    }

    // load channel settings
    for (const GSList *l = _session.get_device()->dev_inst()->channels; l; l = l->next) {
        sr_channel *const probe = (sr_channel*)l->data;
        assert(probe);
        bool isEnabled = false;
        foreach (const QJsonValue &value, sessionObj["channel"].toArray()) {
            QJsonObject obj = value.toObject();
            if ((probe->index == obj["index"].toDouble()) &&
                (probe->type == obj["type"].toDouble())) {
                isEnabled = true;
                probe->enabled = obj["enabled"].toBool();
                probe->name = g_strdup(obj["name"].toString().toStdString().c_str());
                probe->vdiv = obj["vdiv"].toDouble();
                probe->coupling = obj["coupling"].toDouble();
                probe->vfactor = obj["vfactor"].toDouble();
                probe->trig_value = obj["trigValue"].toDouble();
968 969 970
                probe->map_unit = g_strdup(obj["mapUnit"].toString().toStdString().c_str());
                probe->map_min = obj["mapMin"].toDouble();
                probe->map_max = obj["mapMax"].toDouble();
971 972 973 974 975 976
                break;
            }
        }
        if (!isEnabled)
            probe->enabled = false;
    }
977

978 979
    //_session.init_signals();
    _session.reload();
980 981 982 983 984 985 986 987

    // load signal setting
    BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
        foreach (const QJsonValue &value, sessionObj["channel"].toArray()) {
            QJsonObject obj = value.toObject();
            if ((s->get_index() == obj["index"].toDouble()) &&
                (s->get_type() == obj["type"].toDouble())) {
                s->set_colour(QColor(obj["colour"].toString()));
988
                s->set_name(g_strdup(obj["name"].toString().toStdString().c_str()));
989 990

                boost::shared_ptr<view::LogicSignal> logicSig;
991
                if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s))) {
992 993 994
                    logicSig->set_trig(obj["strigger"].toDouble());
                }

995
                boost::shared_ptr<view::DsoSignal> dsoSig;
996
                if ((dsoSig = dynamic_pointer_cast<view::DsoSignal>(s))) {
997
                    dsoSig->load_settings();
Andy Dneg's avatar
Andy Dneg committed
998 999
                    dsoSig->set_zero_ratio(obj["zeroPos"].toDouble());
                    dsoSig->set_trig_ratio(obj["trigValue"].toDouble());
1000
                    dsoSig->commit_settings();
1001
                }
1002 1003

                boost::shared_ptr<view::AnalogSignal> analogSig;
1004
                if ((analogSig = dynamic_pointer_cast<view::AnalogSignal>(s))) {
Andy Dneg's avatar
Andy Dneg committed
1005
                    analogSig->set_zero_ratio(obj["zeroPos"].toDouble());
1006 1007 1008
                    analogSig->commit_settings();
                }

1009 1010 1011 1012 1013
                break;
            }
        }
    }

1014 1015 1016 1017
    // update UI settings
    _sampling_bar->update_sample_rate_selector();
    _trigger_widget->device_updated();

1018 1019 1020 1021 1022
    // load trigger settings
    if (sessionObj.contains("trigger")) {
        _trigger_widget->set_session(sessionObj["trigger"].toObject());
    }
    on_trigger(false);
1023 1024 1025 1026 1027 1028 1029 1030

    #ifdef ENABLE_DECODE
    // load decoders
    if (sessionObj.contains("decoder")) {
        StoreSession ss(_session);
        ss.load_decoders(_protocol_widget, sessionObj["decoder"].toArray());
    }
    #endif
DreamSourceLab's avatar
DreamSourceLab committed
1031

Andy Dneg's avatar
Andy Dneg committed
1032 1033 1034 1035 1036
    // load measure
    if (sessionObj.contains("measure")) {
        _view->get_viewstatus()->load_session(sessionObj["measure"].toArray());
    }

DreamSourceLab's avatar
DreamSourceLab committed
1037
    return true;
1038 1039
}

Andy Dneg's avatar
Andy Dneg committed
1040

1041 1042
bool MainWindow::store_session(QString name)
{
1043 1044
    QFile sessionFile(name);
    if (!sessionFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
1045 1046 1047 1048 1049 1050 1051
//        dialogs::DSMessageBox msg(this);
//        msg.mBox()->setText(tr("File Error"));
//        msg.mBox()->setInformativeText(tr("Couldn't open session file to write!"));
//        msg.mBox()->setStandardButtons(QMessageBox::Ok);
//        msg.mBox()->setIcon(QMessageBox::Warning);
//        msg.exec();
        qDebug("Warning: Couldn't open session file to write!");
1052 1053
        return false;
    }
1054 1055
    QTextStream outStream(&sessionFile);
    outStream.setCodec("UTF-8");
Andy Dneg's avatar
Andy Dneg committed
1056
    //outStream.setGenerateByteOrderMark(true); // UTF-8 without BOM
1057 1058 1059 1060 1061 1062 1063

    GVariant *gvar_opts;
    GVariant *gvar;
    gsize num_opts;
    const sr_dev_inst *const sdi = _session.get_device()->dev_inst();
    QJsonObject sessionVar;
    QJsonArray channelVar;
1064
    sessionVar["Version"]= QJsonValue::fromVariant(Session_Version);
1065 1066
    sessionVar["Device"] = QJsonValue::fromVariant(sdi->driver->name);
    sessionVar["DeviceMode"] = QJsonValue::fromVariant(sdi->mode);
Andy Dneg's avatar
Andy Dneg committed
1067
    sessionVar["Language"] = QJsonValue::fromVariant(_language);
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097

    if ((sr_config_list(sdi->driver, sdi, NULL, SR_CONF_DEVICE_SESSIONS, &gvar_opts) != SR_OK))
        return false;   /* Driver supports no device instance sessions. */
    const int *const options = (const int32_t *)g_variant_get_fixed_array(
        gvar_opts, &num_opts, sizeof(int32_t));
    for (unsigned int i = 0; i < num_opts; i++) {
        const struct sr_config_info *const info =
            sr_config_info_get(options[i]);
        gvar = _session.get_device()->get_config(NULL, NULL, info->key);
        if (gvar != NULL) {
            if (info->datatype == SR_T_BOOL)
                sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_boolean(gvar));
            else if (info->datatype == SR_T_UINT64)
                sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_uint64(gvar)));
            else if (info->datatype == SR_T_UINT8)
                sessionVar[info->name] = QJsonValue::fromVariant(QString::number(g_variant_get_byte(gvar)));
            else if (info->datatype == SR_T_FLOAT)
                sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_double(gvar));
            else if (info->datatype == SR_T_CHAR)
                sessionVar[info->name] = QJsonValue::fromVariant(g_variant_get_string(gvar, NULL));
            g_variant_unref(gvar);
        }
    }

    BOOST_FOREACH(const boost::shared_ptr<view::Signal> s, _session.get_signals()) {
        QJsonObject s_obj;
        s_obj["index"] = s->get_index();
        s_obj["type"] = s->get_type();
        s_obj["enabled"] = s->enabled();
        s_obj["name"] = s->get_name();
Andy Dneg's avatar
Andy Dneg committed
1098 1099 1100 1101
        if (s->get_colour().isValid())
            s_obj["colour"] = QJsonValue::fromVariant(s->get_colour());
        else
            s_obj["colour"] = QJsonValue::fromVariant("default");
1102 1103

        boost::shared_ptr<view::LogicSignal> logicSig;
1104
        if ((logicSig = dynamic_pointer_cast<view::LogicSignal>(s))) {
1105 1106 1107
            s_obj["strigger"] = logicSig->get_trig();
        }

1108
        boost::shared_ptr<view::DsoSignal> dsoSig;
1109
        if ((dsoSig = dynamic_pointer_cast<view::DsoSignal>(s))) {
Anatol Pomozov's avatar
Anatol Pomozov committed
1110 1111
            s_obj["vdiv"] = QJsonValue::fromVariant(static_cast<qulonglong>(dsoSig->get_vDialValue()));
            s_obj["vfactor"] = QJsonValue::fromVariant(static_cast<qulonglong>(dsoSig->get_factor()));
1112
            s_obj["coupling"] = dsoSig->get_acCoupling();
1113
            s_obj["trigValue"] = dsoSig->get_trig_vrate();
Andy Dneg's avatar
Andy Dneg committed
1114
            s_obj["zeroPos"] = dsoSig->get_zero_ratio();
1115
        }
1116 1117

        boost::shared_ptr<view::AnalogSignal> analogSig;
1118
        if ((analogSig = dynamic_pointer_cast<view::AnalogSignal>(s))) {
1119
            s_obj["vdiv"] = QJsonValue::fromVariant(static_cast<qulonglong>(analogSig->get_vdiv()));
Andy Dneg's avatar
Andy Dneg committed
1120
            s_obj["vfactor"] = QJsonValue::fromVariant(static_cast<qulonglong>(analogSig->get_factor()));
1121
            s_obj["coupling"] = analogSig->get_acCoupling();
Andy Dneg's avatar
Andy Dneg committed
1122
            s_obj["zeroPos"] = analogSig->get_zero_ratio();
1123 1124 1125 1126
            s_obj["mapUnit"] = analogSig->get_mapUnit();
            s_obj["mapMin"] = analogSig->get_mapMin();
            s_obj["mapMax"] = analogSig->get_mapMax();
        }
1127 1128 1129 1130 1131 1132 1133 1134
        channelVar.append(s_obj);
    }
    sessionVar["channel"] = channelVar;

    if (_session.get_device()->dev_inst()->mode == LOGIC) {
        sessionVar["trigger"] = _trigger_widget->get_session();
    }

1135 1136 1137 1138
    #ifdef ENABLE_DECODE
    StoreSession ss(_session);
    sessionVar["decoder"] = ss.json_decoders();
    #endif
1139

Andy Dneg's avatar
Andy Dneg committed
1140 1141 1142 1143
    if (_session.get_device()->dev_inst()->mode == DSO) {
        sessionVar["measure"] = _view->get_viewstatus()->get_session();
    }

1144
    QJsonDocument sessionDoc(sessionVar);
1145 1146 1147
    //sessionFile.write(QString::fromUtf8(sessionDoc.toJson()));
    outStream << QString::fromUtf8(sessionDoc.toJson());
    sessionFile.close();
1148 1149
    return true;
}
DreamSourceLab's avatar
DreamSourceLab committed
1150

Andy Dneg's avatar
Andy Dneg committed
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
void MainWindow::restore_dock()
{
    // default dockwidget size
    QSettings settings(QApplication::organizationName(), QApplication::applicationName());
    restoreState(settings.value("windowState").toByteArray());
    if (_session.get_device()->dev_inst()->mode != DSO) {
        _dso_trigger_dock->setVisible(false);
        _trig_bar->update_trig_btn(_trigger_dock->isVisible());
    } else {
        _trigger_dock->setVisible(false);
        _trig_bar->update_trig_btn(_dso_trigger_dock->isVisible());
    }
    if (_session.get_device()->dev_inst()->mode != LOGIC) {
#ifdef ENABLE_DECODE
        on_protocol(false);
#endif
    }
    _trig_bar->update_protocol_btn(_protocol_dock->isVisible());
    _trig_bar->update_measure_btn(_measure_dock->isVisible());
    _trig_bar->update_search_btn(_search_dock->isVisible());
}

DreamSourceLab's avatar
DreamSourceLab committed
1173 1174 1175 1176
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
    (void) object;

1177 1178
    if ( event->type() == QEvent::KeyPress ) {
        const vector< shared_ptr<view::Signal> > sigs(_session.get_signals());
DreamSourceLab's avatar
DreamSourceLab committed
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
        QKeyEvent *ke = (QKeyEvent *) event;