Add imported files to the session save/restore mechanism
authorSoeren Apel <soeren@apelpie.net>
Fri, 25 May 2018 14:07:24 +0000 (16:07 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Fri, 25 May 2018 14:26:40 +0000 (16:26 +0200)
This commit also makes the file loading more robust by improving
the handling of cases where files can't be loaded.

pv/devices/file.hpp
pv/devices/inputfile.cpp
pv/devices/inputfile.hpp
pv/globalsettings.cpp
pv/globalsettings.hpp
pv/session.cpp

index d8e9ae9a01eb2b6879ddae931a9da2c04d39d788..23234caa38244134a8f522e594560a2a69344f3a 100644 (file)
@@ -36,7 +36,7 @@ protected:
 
 public:
        /**
-        * Builds the full name. It only contains all the fields.
+        * Builds the full name. It contains all the fields.
         */
        string full_name() const;
 
@@ -46,7 +46,7 @@ public:
        string display_name(const DeviceManager&) const;
 
 protected:
-       const string file_name_;
+       string file_name_;
 };
 
 } // namespace devices
index 4ffd2dfa22cbc702d6ad7dfeb476042ec2d73639..8e973f0561718d33fcd58afbc40659696e41417a 100644 (file)
 #include <fstream>
 #include <vector>
 
+#include <QDebug>
 #include <QString>
 
+#include <pv/globalsettings.hpp>
+
 #include "inputfile.hpp"
 
+using sigrok::InputFormat;
+
 using std::map;
+using std::out_of_range;
+using std::pair;
 using std::shared_ptr;
 using std::streamsize;
 using std::string;
@@ -53,6 +60,56 @@ InputFile::InputFile(const shared_ptr<sigrok::Context> &context,
 {
 }
 
+InputFile::InputFile(const shared_ptr<sigrok::Context> &context,
+       QSettings &settings):
+       File(""),
+       context_(context),
+       interrupt_(false)
+{
+       file_name_ = settings.value("filename").toString().toStdString();
+
+       QString format_name = settings.value("format").toString();
+
+       // Find matching format
+       const map<string, shared_ptr<InputFormat> > formats = context->input_formats();
+
+       try {
+               format_ = formats.at(format_name.toStdString());
+
+               // Restore all saved options
+               int options = settings.value("options").toInt();
+
+               for (int i = 0; i < options; i++) {
+                       settings.beginGroup("option" + QString::number(i));
+                       QString name = settings.value("name").toString();
+                       options_[name.toStdString()] = GlobalSettings::restore_variantbase(settings);
+                       settings.endGroup();
+               }
+
+       } catch (out_of_range) {
+               qWarning() << "Could not find input format" << format_name <<
+                       "needed to restore session input file";
+       }
+}
+
+void InputFile::save_meta_to_settings(QSettings &settings)
+{
+       settings.setValue("filename", QString::fromStdString(file_name_));
+
+       settings.setValue("format", QString::fromStdString(format_->name()));
+
+       settings.setValue("options", (int)options_.size());
+
+       int i = 0;
+       for (pair<string, Glib::VariantBase> option : options_) {
+               settings.beginGroup("option" + QString::number(i));
+               settings.setValue("name", QString::fromStdString(option.first));
+               GlobalSettings::store_variantbase(settings, option.second);
+               settings.endGroup();
+               i++;
+       }
+}
+
 void InputFile::open()
 {
        if (session_)
@@ -60,6 +117,9 @@ void InputFile::open()
        else
                session_ = context_->create_session();
 
+       if (!format_)
+               return;
+
        input_ = format_->create_input(options_);
 
        if (!input_)
@@ -99,6 +159,9 @@ void InputFile::start()
 
 void InputFile::run()
 {
+       if (!input_)
+               return;
+
        if (!f) {
                // Previous call to run() processed the entire file already
                f = new ifstream(file_name_, ios::binary);
index 41698e6d6be45638b7d00f24cb139deb9f2c6f6a..e08832f608d6247e9febce369f32c3b8aea843e5 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "file.hpp"
 
+#include <QSettings>
+
 using std::atomic;
 using std::ifstream;
 using std::map;
@@ -47,6 +49,15 @@ public:
                shared_ptr<sigrok::InputFormat> format,
                const map<string, Glib::VariantBase> &options);
 
+       /**
+        * Constructor that loads a file using the metadata saved by
+        * save_meta_to_settings() before.
+        */
+       InputFile(const shared_ptr<sigrok::Context> &context,
+               QSettings &settings);
+
+       void save_meta_to_settings(QSettings &settings);
+
        void open();
 
        void close();
@@ -59,8 +70,8 @@ public:
 
 private:
        const shared_ptr<sigrok::Context> context_;
-       const shared_ptr<sigrok::InputFormat> format_;
-       const map<string, Glib::VariantBase> options_;
+       shared_ptr<sigrok::InputFormat> format_;
+       map<string, Glib::VariantBase> options_;
        shared_ptr<sigrok::Input> input_;
 
        ifstream *f;
index c77327c3d1b6b18bd1c1255139b0a6b19323a7d9..cd356ae631f70c4f1ec3d83d1ae29fad302a8b4d 100644 (file)
@@ -25,6 +25,7 @@
 #include <QString>
 
 using std::map;
+using std::string;
 using std::vector;
 
 namespace pv {
@@ -169,5 +170,33 @@ GVariant* GlobalSettings::restore_gvariant(QSettings &settings)
        return value;
 }
 
+void GlobalSettings::store_variantbase(QSettings &settings, Glib::VariantBase v)
+{
+       const QByteArray var_data = QByteArray((const char*)v.get_data(), v.get_size());
+
+       settings.setValue("value", var_data);
+       settings.setValue("type", QString::fromStdString(v.get_type_string()));
+}
+
+Glib::VariantBase GlobalSettings::restore_variantbase(QSettings &settings)
+{
+       QString raw_type = settings.value("type").toString();
+       GVariantType *var_type = g_variant_type_new(raw_type.toUtf8());
+
+       QByteArray data = settings.value("value").toByteArray();
+
+       gpointer var_data = g_memdup((gconstpointer)data.constData(),
+               (guint)data.size());
+
+       GVariant *value = g_variant_new_from_data(var_type, var_data,
+               data.size(), false, g_free, var_data);
+
+       Glib::VariantBase ret_val = Glib::VariantBase(value, true);
+
+       g_variant_type_free(var_type);
+       g_variant_unref(value);
+
+       return ret_val;
+}
 
 } // namespace pv
index b7f7af06de2d8ec5efbb7e15205187ff9090928c..276a968247b11b585d8583e3a0a2423eecb1108c 100644 (file)
@@ -23,6 +23,7 @@
 #include <map>
 
 #include <glib.h>
+#include <glibmm/variant.h>
 
 #include <QSettings>
 #include <QString>
@@ -97,6 +98,10 @@ public:
 
        static GVariant* restore_gvariant(QSettings &settings);
 
+       static void store_variantbase(QSettings &settings, Glib::VariantBase v);
+
+       static Glib::VariantBase restore_variantbase(QSettings &settings);
+
 private:
        static vector<GlobalSettingsInterface*> callbacks_;
 
index 4aba385b687d22ac8764da163b3f552792580682..7df73d63d5ba43660eb666ec1a91322046002442 100644 (file)
@@ -207,7 +207,7 @@ void Session::save_settings(QSettings &settings) const
                }
 
                shared_ptr<devices::SessionFile> sessionfile_device =
-                       dynamic_pointer_cast< devices::SessionFile >(device_);
+                       dynamic_pointer_cast<devices::SessionFile>(device_);
 
                if (sessionfile_device) {
                        settings.setValue("device_type", "sessionfile");
@@ -217,6 +217,16 @@ void Session::save_settings(QSettings &settings) const
                        settings.endGroup();
                }
 
+               shared_ptr<devices::InputFile> inputfile_device =
+                       dynamic_pointer_cast<devices::InputFile>(device_);
+
+               if (inputfile_device) {
+                       settings.setValue("device_type", "inputfile");
+                       settings.beginGroup("device");
+                       inputfile_device->save_meta_to_settings(settings);
+                       settings.endGroup();
+               }
+
                // Save channels and decoders
                for (shared_ptr<data::SignalBase> base : signalbases_) {
 #ifdef ENABLE_DECODE
@@ -290,21 +300,34 @@ void Session::restore_settings(QSettings &settings)
                settings.endGroup();
        }
 
-       if (device_type == "sessionfile") {
-               settings.beginGroup("device");
-               QString filename = settings.value("filename").toString();
-               settings.endGroup();
+       if ((device_type == "sessionfile") || (device_type == "inputfile")) {
+               if (device_type == "sessionfile") {
+                       settings.beginGroup("device");
+                       QString filename = settings.value("filename").toString();
+                       settings.endGroup();
+
+                       if (QFileInfo(filename).isReadable()) {
+                               device = make_shared<devices::SessionFile>(device_manager_.context(),
+                                       filename.toStdString());
+                       }
+               }
+
+               if (device_type == "inputfile") {
+                       settings.beginGroup("device");
+                       device = make_shared<devices::InputFile>(device_manager_.context(),
+                               settings);
+                       settings.endGroup();
+               }
 
-               if (QFileInfo(filename).isReadable()) {
-                       device = make_shared<devices::SessionFile>(device_manager_.context(),
-                               filename.toStdString());
+               if (device) {
                        set_device(device);
 
                        start_capture([](QString infoMessage) {
                                // TODO Emulate noquote()
                                qDebug() << "Session error:" << infoMessage; });
 
-                       set_name(QFileInfo(filename).fileName());
+                       set_name(QString::fromStdString(
+                               dynamic_pointer_cast<devices::File>(device)->display_name(device_manager_)));
                }
        }