diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index 9e51799a357d37f77696dfa8a25a2f3e72d05bd2..bc11a8ed84b2f6c73c8b473c6f4688c635ddbfb8 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -54,6 +54,9 @@ #include #include +#include +#include +#include #include @@ -179,6 +182,104 @@ void SigSession::save_file(const std::string &name){ snapshot->get_sample_count()); } +QList SigSession::getSuportedExportFormats(){ + // TODO: uncomment this + //const struct sr_output_module** supportedModules = sr_output_list(); + QList list; + /*while(*supportedModules){ + if(*supportedModules == NULL) + break; + QString format((*supportedModules)->desc); + format.append(" (*."); + format.append((*supportedModules)->id); + format.append(")"); + list.append(format); + *supportedModules++; + }*/ + return list; +} + +void SigSession::cancelSaveFile(){ + saveFileThreadRunning = false; +} + +void SigSession::export_file(const std::string &name, QWidget* parent, const std::string &ext){ + /*const deque< boost::shared_ptr > &snapshots = + _logic_data->get_snapshots(); + if(snapshots.empty()) + return; + const boost::shared_ptr & snapshot = + snapshots.front(); + const struct sr_output_module** supportedModules = sr_output_list(); + const struct sr_output_module* outModule = NULL; + while(*supportedModules){ + if(*supportedModules == NULL) + break; + if(!strcmp((*supportedModules)->id, ext.c_str())){ + outModule = *supportedModules; + break; + } + *supportedModules++; + } + if(outModule == NULL) + return; + struct sr_output output; + GHashTable *params = g_hash_table_new(g_str_hash, g_str_equal); + GVariant* filenameGVariant = g_variant_new_string(name.c_str()); + g_hash_table_insert(params, (char*)"filename", filenameGVariant); + output.module = (sr_output_module*) outModule; + output.sdi = _dev_inst->dev_inst(); + output.param = NULL; + if(outModule->init) + outModule->init(&output, params); + QFile file(name.c_str()); + file.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&file); + QFuture future = QtConcurrent::run([&]{ + saveFileThreadRunning = true; + unsigned char* datat = (unsigned char*)snapshot->get_data(); + int numsamples = snapshot->get_sample_count()*snapshot->unit_size(); + GString *data_out; + int usize = 1024; + int size = usize; + struct sr_datafeed_logic lp; + struct sr_datafeed_packet p; + for(uint64_t i = 0; i < numsamples; i+=usize){ + if(numsamples - i < usize) + size = numsamples - i; + lp.data = &datat[i]; + lp.length = size; + lp.unitsize = snapshot->unit_size(); + p.type = SR_DF_LOGIC; + p.payload = &lp; + outModule->receive(&output, &p, &data_out); + if(data_out){ + out << (char*) data_out->str; + g_string_free(data_out,TRUE); + } + emit progressValueChanged(i*100/numsamples); + if(!saveFileThreadRunning) + break; + } + }); + QFutureWatcher watcher; + Qt::WindowFlags flags = Qt::CustomizeWindowHint; + QProgressDialog dlg(QString::fromUtf8("Exporting data... It can take a while."), + QString::fromUtf8("Cancel"),0,100,parent,flags); + dlg.setWindowModality(Qt::WindowModal); + watcher.setFuture(future); + connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel())); + connect(this,SIGNAL(progressValueChanged(int)),&dlg,SLOT(setValue(int))); + connect(&dlg,SIGNAL(canceled()),this,SLOT(cancelSaveFile())); + dlg.exec(); + future.waitForFinished(); + // optional, as QFile destructor will already do it: + file.close(); + outModule->cleanup(&output); + g_hash_table_destroy(params); + g_variant_unref(filenameGVariant);*/ +} + void SigSession::set_default_device(boost::function error_handler) { shared_ptr default_device; diff --git a/DSView/pv/sigsession.h b/DSView/pv/sigsession.h index cf4674dd984b33df6500b4371655f388efd0cb04..28589271ef05edcde72f04f665a3e1bed28683f1 100644 --- a/DSView/pv/sigsession.h +++ b/DSView/pv/sigsession.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -88,6 +89,7 @@ class SigSession : public QObject private: static const float Oversampling = 2.0f; static const int ViewTime = 800; + bool saveFileThreadRunning = false; public: enum capture_state { @@ -115,6 +117,9 @@ public: void save_file(const std::string &name); void set_default_device(boost::function error_handler); + void export_file(const std::string &name, QWidget* parent, const std::string &ext); + + void set_default_device(); void release_device(device::DevInst *dev_inst); @@ -132,6 +137,7 @@ public: std::vector< boost::shared_ptr > get_group_signals(); + QList getSuportedExportFormats(); #ifdef ENABLE_DECODE bool add_decoder(srd_decoder *const dec); @@ -282,11 +288,15 @@ signals: void malloc_error(); void zero_adj(); + void progressSaveFileValueChanged(int percent); public slots: void reload(); void refresh(); +private slots: + void cancelSaveFile(); + private: // TODO: This should not be necessary. Multiple concurrent // sessions should should be supported and it should be diff --git a/DSView/pv/toolbars/filebar.cpp b/DSView/pv/toolbars/filebar.cpp index 6ef89353666aaee0118d4860c031c7331f056b59..3bf4c185139b7b9f8f45caf893fdfa451e3eb29c 100644 --- a/DSView/pv/toolbars/filebar.cpp +++ b/DSView/pv/toolbars/filebar.cpp @@ -64,6 +64,14 @@ FileBar::FileBar(SigSession &session, QWidget *parent) : _file_button.addAction(_action_save); connect(_action_save, SIGNAL(triggered()), this, SLOT(on_actionSave_triggered())); + _action_export = new QAction(this); + _action_export->setText(QApplication::translate("File", "&Export...", 0)); + _action_export->setIcon(QIcon::fromTheme("file",QIcon(":/icons/instant.png"))); + _action_export->setObjectName(QString::fromUtf8("actionExport")); + _file_button.addAction(_action_export); + connect(_action_export, SIGNAL(triggered()), this, SLOT(on_actionExport_triggered())); + + _action_capture = new QAction(this); _action_capture->setText(QApplication::translate( "File", "&Capture...", 0)); @@ -84,7 +92,7 @@ void FileBar::on_actionOpen_triggered() // Show the dialog const QString file_name = QFileDialog::getOpenFileName( this, tr("Open File"), "", tr( - "DSView Sessions (*.dsl)")); + "DSView Sessions (*.dsl);;All Files (*.*)")); if (!file_name.isEmpty()) load_file(file_name); } @@ -108,6 +116,45 @@ void FileBar::show_session_error( msg.exec(); } +void FileBar::on_actionExport_triggered(){ + int unit_size; + uint64_t length; + void* buf = _session.get_buf(unit_size, length); + if (!buf) { + QMessageBox msg(this); + msg.setText("Data Export"); + msg.setInformativeText("No Data to Save!"); + msg.setStandardButtons(QMessageBox::Ok); + msg.setIcon(QMessageBox::Warning); + msg.exec(); + } else if (_session.get_device()->dev_inst()->mode != LOGIC) { + QMessageBox msg(this); + msg.setText("Export Data"); + msg.setInformativeText("DSLogic currently only support exporting logic data to file!"); + msg.setStandardButtons(QMessageBox::Ok); + msg.setIcon(QMessageBox::Warning); + msg.exec(); + }else { + QList supportedFormats = _session.getSuportedExportFormats(); + QString filter; + for(int i = 0; i < supportedFormats.count();i++){ + filter.append(supportedFormats[i]); + if(i < supportedFormats.count() - 1) + filter.append(";;"); + } + QString file_name = QFileDialog::getSaveFileName( + this, tr("Export Data"), "",filter,&filter); + if (!file_name.isEmpty()) { + QFileInfo f(file_name); + QStringList list = filter.split('.').last().split(')'); + QString ext = list.first(); + if(f.suffix().compare(ext)) + file_name+=tr(".")+ext; + _session.export_file(file_name.toStdString(), this, ext.toStdString()); + } + } +} + void FileBar::on_actionSave_triggered() { //save(); diff --git a/DSView/pv/toolbars/filebar.h b/DSView/pv/toolbars/filebar.h index 1ac54febeeecb3c9025c3a522a7a8c39350fb09d..a10a405c42abbd0dd39becc4ad639ba0470627f0 100644 --- a/DSView/pv/toolbars/filebar.h +++ b/DSView/pv/toolbars/filebar.h @@ -58,6 +58,7 @@ private slots: void on_actionOpen_triggered(); void on_actionSave_triggered(); void on_actionCapture_triggered(); + void on_actionExport_triggered(); private: bool _enable; @@ -67,6 +68,7 @@ private: QAction *_action_open; QAction *_action_save; + QAction *_action_export; QAction *_action_capture; };