]> sigrok.org Git - pulseview.git/commitdiff
Add save feature to DecoderOutputView
authorSoeren Apel <redacted>
Thu, 19 Dec 2019 08:32:45 +0000 (09:32 +0100)
committerSoeren Apel <redacted>
Fri, 20 Dec 2019 00:44:21 +0000 (01:44 +0100)
pv/data/decodesignal.cpp
pv/data/decodesignal.hpp
pv/views/decoder_output/QHexView.cpp
pv/views/decoder_output/QHexView.hpp
pv/views/decoder_output/view.cpp
pv/views/decoder_output/view.hpp

index 00812917013ae361f739ea649dbf9611792bef0e..12379518acf9bb90dda59e376ee9b0145d5b7b69 100644 (file)
@@ -567,7 +567,7 @@ void DecodeSignal::get_binary_data_chunk(uint32_t segment_id,
        }
 }
 
-void DecodeSignal::get_binary_data_chunks_merged(uint32_t segment_id,
+void DecodeSignal::get_merged_binary_data_chunks_by_sample(uint32_t segment_id,
        const Decoder* dec, uint32_t bin_class_id, uint64_t start_sample,
        uint64_t end_sample, vector<uint8_t> *dest) const
 {
@@ -608,6 +608,48 @@ void DecodeSignal::get_binary_data_chunks_merged(uint32_t segment_id,
        }
 }
 
+void DecodeSignal::get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
+       const data::decode::Decoder* dec, uint32_t bin_class_id, uint64_t start,
+       uint64_t end, vector<uint8_t> *dest) const
+{
+       assert(dest != nullptr);
+
+       try {
+               const DecodeSegment *segment = &(segments_.at(segment_id));
+
+               const DecodeBinaryClass* bin_class = nullptr;
+               for (const DecodeBinaryClass& bc : segment->binary_classes)
+                       if ((bc.decoder == dec) && (bc.info->bin_class_id == bin_class_id))
+                               bin_class = &bc;
+
+               // Determine overall size before copying to resize dest vector only once
+               uint64_t size = 0;
+               uint64_t offset = 0;
+               for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) {
+                       if (offset >= start)
+                               size += chunk.data.size();
+                       offset += chunk.data.size();
+                       if (offset >= end)
+                               break;
+               }
+               dest->resize(size);
+
+               offset = 0;
+               uint64_t dest_offset = 0;
+               for (const DecodeBinaryDataChunk& chunk : bin_class->chunks) {
+                       if (offset >= start) {
+                               memcpy(dest->data() + dest_offset, chunk.data.data(), chunk.data.size());
+                               dest_offset += chunk.data.size();
+                       }
+                       offset += chunk.data.size();
+                       if (offset >= end)
+                               break;
+               }
+       } catch (out_of_range&) {
+               // Do nothing
+       }
+}
+
 const DecodeBinaryClass* DecodeSignal::get_binary_data_class(uint32_t segment_id,
        const data::decode::Decoder* dec, uint32_t bin_class_id) const
 {
index e591eb010bfb007f357f5c28b5961f1ac822669c..8bcc562068a13d6655425b834566968bb51420cc 100644 (file)
@@ -165,8 +165,13 @@ public:
        void get_binary_data_chunk(uint32_t segment_id, const data::decode::Decoder* dec,
                uint32_t bin_class_id, uint32_t chunk_id, const vector<uint8_t> **dest,
                uint64_t *size);
-       void get_binary_data_chunks_merged(uint32_t segment_id, const data::decode::Decoder* dec,
-               uint32_t bin_class_id, uint64_t start_sample, uint64_t end_sample,
+       void get_merged_binary_data_chunks_by_sample(uint32_t segment_id,
+               const data::decode::Decoder* dec, uint32_t bin_class_id,
+               uint64_t start_sample, uint64_t end_sample,
+               vector<uint8_t> *dest) const;
+       void get_merged_binary_data_chunks_by_offset(uint32_t segment_id,
+               const data::decode::Decoder* dec, uint32_t bin_class_id,
+               uint64_t start, uint64_t end,
                vector<uint8_t> *dest) const;
        const DecodeBinaryClass* get_binary_data_class(uint32_t segment_id,
                const data::decode::Decoder* dec, uint32_t bin_class_id) const;
index 06df103b7f45c43b9aa19cc75d3e22260eace604..0fca4161fe02f6467799619a56862cb09db8b8c1 100644 (file)
@@ -126,6 +126,21 @@ QSizePolicy QHexView::sizePolicy() const
        return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
 }
 
+pair<size_t, size_t> QHexView::get_selection() const
+{
+       size_t start = selectBegin_ / 2;
+       size_t end = selectEnd_ / 2;
+
+       if (start == end) {
+               // Nothing is currently selected
+               start = 0;
+               end = data_size_;
+       } else
+               end++;
+
+       return std::make_pair(start, end);
+}
+
 void QHexView::initialize_byte_iterator(size_t offset)
 {
        current_chunk_id_ = 0;
index e7c255670b7b793e014ac076c735ca34866261a6..c3004c5c59d07aa7040589b688f9e36b4e26616e 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <pv/data/decodesignal.hpp>
 
+using std::pair;
 using std::size_t;
 using pv::data::DecodeBinaryClass;
 using pv::data::DecodeBinaryDataChunk;
@@ -58,6 +59,8 @@ public:
        void showFromOffset(size_t offset);
        virtual QSizePolicy sizePolicy() const;
 
+       pair<size_t, size_t> get_selection() const;
+
 protected:
        void initialize_byte_iterator(size_t offset);
        uint8_t get_next_byte(bool* is_next_chunk = nullptr);
index 218c5c9a6e84fbf07e09c043915c8ad6130dff4f..951bc06ef296712c65c467548736a1eb62e421eb 100644 (file)
 
 #include <QByteArray>
 #include <QDebug>
+#include <QFileDialog>
 #include <QLabel>
 #include <QMenu>
+#include <QMessageBox>
 #include <QToolBar>
 #include <QVBoxLayout>
 
@@ -31,6 +33,7 @@
 #include "view.hpp"
 #include "QHexView.hpp"
 
+#include "pv/globalsettings.hpp"
 #include "pv/session.hpp"
 #include "pv/util.hpp"
 #include "pv/data/decode/decoder.hpp"
@@ -240,6 +243,52 @@ void View::update_data()
                signal_->get_binary_data_class(current_segment_, decoder_, bin_class_id_);
 
        hex_view_->setData(bin_class);
+
+       if (!save_button_->isEnabled())
+               save_button_->setEnabled(true);
+}
+
+void View::save_data() const
+{
+       assert(decoder_);
+       assert(signal_);
+
+       if (!signal_)
+               return;
+
+       GlobalSettings settings;
+       const QString dir = settings.value("MainWindow/SaveDirectory").toString();
+
+       const QString file_name = QFileDialog::getSaveFileName(
+               parent_, tr("Save Binary Data"), dir, tr("Binary Data Files (*.bin);;All Files (*)"));
+
+       if (file_name.isEmpty())
+               return;
+
+       QFile file(file_name);
+       if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+               pair<size_t, size_t> selection = hex_view_->get_selection();
+
+               vector<uint8_t> data;
+               signal_->get_merged_binary_data_chunks_by_offset(current_segment_, decoder_,
+                       bin_class_id_, selection.first, selection.second, &data);
+
+               int64_t bytes_written = file.write((const char*)data.data(), data.size());
+
+               if ((bytes_written == -1) || ((uint64_t)bytes_written != data.size())) {
+                       QMessageBox msg(parent_);
+                       msg.setText(tr("Error") + "\n\n" + tr("File %1 could not be written to.").arg(file_name));
+                       msg.setStandardButtons(QMessageBox::Ok);
+                       msg.setIcon(QMessageBox::Warning);
+                       msg.exec();
+                       return;
+               }
+       }
+}
+
+void View::save_data_as_hex_dump() const
+{
+
 }
 
 void View::on_selected_decoder_changed(int index)
@@ -359,18 +408,22 @@ void View::on_decoder_removed(void* decoder)
 
 void View::on_actionSave_triggered(QAction* action)
 {
-       (void)action;
+       int save_type = SaveTypeBinary;
+       if (action)
+               save_type = action->data().toInt();
+
+       if (save_type == SaveTypeBinary)
+               save_data();
+       if (save_type == SaveTypeHexDump)
+               save_data_as_hex_dump();
 }
 
 void View::perform_delayed_view_update()
 {
        if (!binary_data_exists_)
-               if (signal_->get_binary_data_chunk_count(current_segment_, decoder_, bin_class_id_)) {
+               if (signal_->get_binary_data_chunk_count(current_segment_, decoder_, bin_class_id_))
                        binary_data_exists_ = true;
 
-                       save_button_->setEnabled(true);
-               }
-
        update_data();
 }
 
index ece85ad65835f45a5d83a29ece14f8eb97515ae6..28c7e9066ae27960d8b321919c8f2ec472ac2d13 100644 (file)
@@ -76,6 +76,9 @@ private:
        void reset_data();
        void update_data();
 
+       void save_data() const;
+       void save_data_as_hex_dump() const;
+
 private Q_SLOTS:
        void on_selected_decoder_changed(int index);
        void on_selected_class_changed(int index);