From: Soeren Apel Date: Mon, 29 Sep 2014 21:31:55 +0000 (+0200) Subject: Add serial_num/connection_id handling and save/restore last device X-Git-Tag: pulseview-0.3.0~534 X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=6842b5fc481eb43d9aeea81f17e211820d6dc405 Add serial_num/connection_id handling and save/restore last device This patch performs several correlated changes: - Make use of sdi->serial_num and sdi->connection_id in format_device_title() - Add a Device::get_device_info() method that returns a map with all device identification information that's available - Add a DeviceManager::find_device_from_info() method which returns the best match to a given set of device infos - Add save/restore code to the MainWindow class that makes use of the aforementioned maps to identify the currently selected device. --- diff --git a/pv/device/device.cpp b/pv/device/device.cpp index 40044f8c..546ce391 100644 --- a/pv/device/device.cpp +++ b/pv/device/device.cpp @@ -25,6 +25,9 @@ #include "device.h" +using std::list; +using std::make_pair; +using std::map; using std::ostringstream; using std::string; @@ -70,24 +73,51 @@ std::string Device::format_device_title() const assert(_sdi); - if (_sdi->vendor && _sdi->vendor[0]) { - s << _sdi->vendor; - if ((_sdi->model && _sdi->model[0]) || - (_sdi->version && _sdi->version[0])) - s << ' '; - } + if (_sdi->vendor && _sdi->vendor[0]) + s << _sdi->vendor << " "; - if (_sdi->model && _sdi->model[0]) { - s << _sdi->model; - if (_sdi->version && _sdi->version[0]) - s << ' '; - } + if (_sdi->model && _sdi->model[0]) + s << _sdi->model << " "; if (_sdi->version && _sdi->version[0]) - s << _sdi->version; + s << _sdi->version << " "; + + // Show connection string only if no serial number is present. + if (_sdi->serial_num && _sdi->serial_num[0]) + s << "(" << _sdi->serial_num << ") "; + else if (_sdi->connection_id && _sdi->connection_id[0]) + s << "[" << _sdi->connection_id << "] "; + + // Remove trailing space. + s.seekp(-1, std::ios_base::end); + s << std::ends; return s.str(); } +map Device::get_device_info() const +{ + map result; + + assert(_sdi); + + if (_sdi->vendor && _sdi->vendor[0]) + result.insert(make_pair("vendor", _sdi->vendor)); + + if (_sdi->model && _sdi->model[0]) + result.insert(make_pair("model", _sdi->model)); + + if (_sdi->version && _sdi->version[0]) + result.insert(make_pair("version", _sdi->version)); + + if (_sdi->serial_num && _sdi->serial_num[0]) + result.insert(make_pair("serial_num", _sdi->serial_num)); + + if (_sdi->connection_id && _sdi->connection_id[0]) + result.insert(make_pair("connection_id", _sdi->connection_id)); + + return result; +} + } // device } // pv diff --git a/pv/device/device.h b/pv/device/device.h index 1bcadab4..0a908a79 100644 --- a/pv/device/device.h +++ b/pv/device/device.h @@ -21,6 +21,9 @@ #ifndef PULSEVIEW_PV_DEVICE_DEVICE_H #define PULSEVIEW_PV_DEVICE_DEVICE_H +#include +#include + #include "devinst.h" namespace pv { @@ -39,6 +42,8 @@ public: std::string format_device_title() const; + std::map get_device_info() const; + private: sr_dev_inst *const _sdi; }; diff --git a/pv/device/devinst.h b/pv/device/devinst.h index 5a994372..1e0850c8 100644 --- a/pv/device/devinst.h +++ b/pv/device/devinst.h @@ -21,6 +21,7 @@ #ifndef PULSEVIEW_PV_DEVICE_DEVINST_H #define PULSEVIEW_PV_DEVICE_DEVINST_H +#include #include #include @@ -58,6 +59,8 @@ public: virtual std::string format_device_title() const = 0; + virtual std::map get_device_info() const = 0; + GVariant* get_config(const sr_channel_group *group, int key); bool set_config(const sr_channel_group *group, int key, GVariant *data); diff --git a/pv/device/file.cpp b/pv/device/file.cpp index edc2da2b..e82c5ece 100644 --- a/pv/device/file.cpp +++ b/pv/device/file.cpp @@ -25,6 +25,8 @@ #include +using std::make_pair; +using std::map; using std::string; namespace pv { @@ -40,6 +42,18 @@ std::string File::format_device_title() const return boost::filesystem::path(_path).filename().string(); } +map File::get_device_info() const +{ + map result; + + result.insert(make_pair("vendor", "sigrok")); + result.insert(make_pair("model", "file")); + result.insert(make_pair("connection_id", + boost::filesystem::path(_path).filename().string())); + + return result; +} + File* File::create(const string &name) { if (sr_session_load(name.c_str(), &SigSession::_sr_session) == SR_OK) { diff --git a/pv/device/file.h b/pv/device/file.h index 4a45a823..c6c21cac 100644 --- a/pv/device/file.h +++ b/pv/device/file.h @@ -39,6 +39,8 @@ public: public: std::string format_device_title() const; + std::map get_device_info() const; + protected: const std::string _path; }; diff --git a/pv/devicemanager.cpp b/pv/devicemanager.cpp index bbcfbf24..13b44e96 100644 --- a/pv/devicemanager.cpp +++ b/pv/devicemanager.cpp @@ -30,7 +30,6 @@ using std::list; using std::map; -using std::ostringstream; using std::runtime_error; using std::shared_ptr; using std::string; @@ -90,6 +89,57 @@ list< shared_ptr > DeviceManager::driver_scan( return driver_devices; } +const shared_ptr DeviceManager::find_device_from_info( + const map search_info) +{ + shared_ptr last_resort_dev; + map dev_info; + + last_resort_dev = NULL; + + for (shared_ptr dev : _devices) { + assert(dev); + dev_info = dev->get_device_info(); + + // If present, vendor and model always have to match. + if (dev_info.count("vendor") > 0 && search_info.count("vendor") > 0) + if (dev_info.at("vendor") != search_info.at("vendor")) continue; + + if (dev_info.count("model") > 0 && search_info.count("model") > 0) + if (dev_info.at("model") != search_info.at("model")) continue; + + // Most unique match: vendor/model/serial_num (but don't match a S/N of 0) + if ((dev_info.count("serial_num") > 0) && (dev_info.at("serial_num") != "0") + && search_info.count("serial_num") > 0) + if (dev_info.at("serial_num") == search_info.at("serial_num") && + dev_info.at("serial_num") != "0") + return dev; + + // Second best match: vendor/model/connection_id + if (dev_info.count("connection_id") > 0 && + search_info.count("connection_id") > 0) + if (dev_info.at("connection_id") == search_info.at("connection_id")) + return dev; + + // Last resort: vendor/model/version + if (dev_info.count("version") > 0 && + search_info.count("version") > 0) + if (dev_info.at("version") == search_info.at("version") && + dev_info.at("version") != "0") + return dev; + + // For this device, we merely have a vendor/model match. + last_resort_dev = dev; + } + + // If there wasn't even a vendor/model/version match, we end up here. + // This is usually the case for devices with only vendor/model data. + // The selected device may be wrong with multiple such devices attached + // but it is the best we can do at this point. After all, there may be + // only one such device and we do want to select it in this case. + return last_resort_dev; +} + void DeviceManager::init_drivers() { // Initialise all libsigrok drivers diff --git a/pv/devicemanager.h b/pv/devicemanager.h index ca86a7fe..0a8f2e0d 100644 --- a/pv/devicemanager.h +++ b/pv/devicemanager.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -52,6 +53,9 @@ public: struct sr_dev_driver *const driver, GSList *const drvopts = NULL); + const std::shared_ptr find_device_from_info( + const std::map search_info); + private: void init_drivers(); diff --git a/pv/mainwindow.cpp b/pv/mainwindow.cpp index c3747e02..d4c5f1f7 100644 --- a/pv/mainwindow.cpp +++ b/pv/mainwindow.cpp @@ -63,7 +63,9 @@ #include using std::list; +using std::map; using std::shared_ptr; +using std::string; namespace pv { @@ -266,23 +268,53 @@ void MainWindow::setup_ui() // Setup _session events connect(&_session, SIGNAL(capture_state_changed(int)), this, SLOT(capture_state_changed(int))); - } void MainWindow::save_ui_settings() { QSettings settings; + map dev_info; + list key_list; + settings.beginGroup("MainWindow"); settings.setValue("state", saveState()); settings.setValue("geometry", saveGeometry()); settings.endGroup(); + + if (_session.get_device()) { + settings.beginGroup("Device"); + key_list.push_back("vendor"); + key_list.push_back("model"); + key_list.push_back("version"); + key_list.push_back("serial_num"); + key_list.push_back("connection_id"); + + dev_info = _session.get_device()->get_device_info(); + + for (string key : key_list) { + + if (dev_info.count(key)) + settings.setValue(QString::fromUtf8(key.c_str()), + QString::fromUtf8(dev_info.at(key).c_str())); + else + settings.remove(QString::fromUtf8(key.c_str())); + } + + settings.endGroup(); + } } void MainWindow::restore_ui_settings() { QSettings settings; + shared_ptr device; + + map dev_info; + list key_list; + string value; + settings.beginGroup("MainWindow"); if (settings.contains("geometry")) { @@ -292,6 +324,33 @@ void MainWindow::restore_ui_settings() resize(1000, 720); settings.endGroup(); + + // Re-select last used device if possible. + settings.beginGroup("Device"); + key_list.push_back("vendor"); + key_list.push_back("model"); + key_list.push_back("version"); + key_list.push_back("serial_num"); + key_list.push_back("connection_id"); + + for (string key : key_list) { + if (!settings.contains(QString::fromUtf8(key.c_str()))) + continue; + + value = settings.value(QString::fromUtf8(key.c_str())).toString().toStdString(); + + if (value.size() > 0) + dev_info.insert(std::make_pair(key, value)); + } + + device = _device_manager.find_device_from_info(dev_info); + + if (device) { + _session.set_device(device); + update_device_list(); + } + + settings.endGroup(); } void MainWindow::session_error(