]> sigrok.org Git - pulseview.git/commitdiff
Add serial_num/connection_id handling and save/restore last device
authorSoeren Apel <redacted>
Mon, 29 Sep 2014 21:31:55 +0000 (23:31 +0200)
committerBert Vermeulen <redacted>
Mon, 29 Sep 2014 21:37:05 +0000 (23:37 +0200)
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.

pv/device/device.cpp
pv/device/device.h
pv/device/devinst.h
pv/device/file.cpp
pv/device/file.h
pv/devicemanager.cpp
pv/devicemanager.h
pv/mainwindow.cpp

index 40044f8cd9490d8cae5be998f8359881114696e8..546ce391869f81c52a86116326e034972ebb2df2 100644 (file)
@@ -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<string, string> Device::get_device_info() const
+{
+       map<string, string> 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
index 1bcadab4e71e86f80368c8ae5a61c75ec0d706e2..0a908a7962d451034d732cddd88e3abbb6809c93 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef PULSEVIEW_PV_DEVICE_DEVICE_H
 #define PULSEVIEW_PV_DEVICE_DEVICE_H
 
+#include <map>
+#include <string>
+
 #include "devinst.h"
 
 namespace pv {
@@ -39,6 +42,8 @@ public:
 
        std::string format_device_title() const;
 
+       std::map<std::string, std::string> get_device_info() const;
+
 private:
        sr_dev_inst *const _sdi;
 };
index 5a994372d347ca76dca32d151760a6b735d358a9..1e0850c8cd9ae8089e2e98df7e65a97f3feae84f 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef PULSEVIEW_PV_DEVICE_DEVINST_H
 #define PULSEVIEW_PV_DEVICE_DEVINST_H
 
+#include <map>
 #include <memory>
 #include <string>
 
@@ -58,6 +59,8 @@ public:
 
        virtual std::string format_device_title() const = 0;
 
+       virtual std::map<std::string, std::string> 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);
index edc2da2bdd96cad6ba3a56eb39d13c2a1a2b2e4e..e82c5ece16c89e8f7d00da6da9fcb3bdda4506b9 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <libsigrok/libsigrok.h>
 
+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<string, string> File::get_device_info() const
+{
+       map<string, string> 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) {
index 4a45a823dca1854e3b4e37bf263564eee9e87431..c6c21cac4f3845a138090384ef0d79a23983d574 100644 (file)
@@ -39,6 +39,8 @@ public:
 public:
        std::string format_device_title() const;
 
+       std::map<std::string, std::string> get_device_info() const;
+
 protected:
        const std::string _path;
 };
index bbcfbf247675b345ab5af39376a930af132ca2e8..13b44e969cc2720e0d17f86c9ab4871030221f06 100644 (file)
@@ -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<device::Device> > DeviceManager::driver_scan(
        return driver_devices;
 }
 
+const shared_ptr<device::Device> DeviceManager::find_device_from_info(
+       const map<string, string> search_info)
+{
+       shared_ptr<device::Device> last_resort_dev;
+       map<string, string> dev_info;
+
+       last_resort_dev = NULL;
+
+       for (shared_ptr<device::Device> 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
index ca86a7fe9c15c69f727ccbf3b04711a8650e8250..0a8f2e0dca7d24fedb53cf7b734d321320ff180a 100644 (file)
@@ -24,6 +24,7 @@
 #include <glib.h>
 
 #include <list>
+#include <map>
 #include <memory>
 #include <string>
 
@@ -52,6 +53,9 @@ public:
                struct sr_dev_driver *const driver,
                GSList *const drvopts = NULL);
 
+       const std::shared_ptr<device::Device> find_device_from_info(
+               const std::map<std::string, std::string> search_info);
+
 private:
        void init_drivers();
 
index c3747e0256f945f81ce94fa5298ad7ce4c0c2904..d4c5f1f79ed27111c17bcbe9bee6a97902d4a7e8 100644 (file)
@@ -63,7 +63,9 @@
 #include <libsigrok/libsigrok.h>
 
 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<string, string> dev_info;
+       list<string> 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<pv::device::DevInst> device;
+
+       map<string, string> dev_info;
+       list<string> 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(