2
0
forked from Ivasoft/DSView

Add protocol list viewer and export support

This commit is contained in:
DreamSourceLab
2016-05-03 15:47:06 +08:00
parent f3138d93c2
commit adf428ffd0
41 changed files with 2901 additions and 483 deletions

View File

@@ -56,5 +56,6 @@
<file>icons/start_dis.png</file>
<file>icons/start_dis_cn.png</file>
<file>icons/settings.png</file>
<file>darkstyle/style.qss</file>
</qresource>
</RCC>

1218
DSView/darkstyle/style.qss Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -147,7 +147,8 @@ int main(int argc, char *argv[])
// Initialise the main window
pv::MainWindow w(device_manager, open_file);
QFile qss(":/stylesheet.qss");
//QFile qss(":/stylesheet.qss");
QFile qss(":qdarkstyle/style.qss");
qss.open(QFile::ReadOnly);
a.setStyleSheet(qss.readAll());
qss.close();

View File

@@ -49,6 +49,12 @@ Annotation::Annotation(const srd_proto_data *const pdata) :
}
}
Annotation::Annotation()
{
_start_sample = 0;
_end_sample = 0;
}
Annotation::~Annotation()
{
_annotations.clear();

View File

@@ -35,6 +35,7 @@ class Annotation
{
public:
Annotation(const srd_proto_data *const pdata);
Annotation();
~Annotation();
uint64_t start_sample() const;

View File

@@ -68,8 +68,8 @@ const QString Row::title() const
bool Row::operator<(const Row &other) const
{
return (_decoder < other._decoder) ||
(_decoder == other._decoder && _row < other._row);
return (_decoder->name < other._decoder->name) ||
(_decoder->name == other._decoder->name && _row->desc < other._row->desc);
}
} // decode

View File

@@ -46,7 +46,7 @@ public:
const QString title() const;
bool operator<(const Row &other) const;
bool operator<(const Row &other) const;
private:
const srd_decoder *_decoder;

View File

@@ -23,6 +23,7 @@
#include "rowdata.h"
using std::max;
using std::min;
using std::vector;
namespace pv {
@@ -30,7 +31,8 @@ namespace data {
namespace decode {
RowData::RowData() :
_max_annotation(0)
_max_annotation(0),
_min_annotation(UINT64_MAX)
{
}
@@ -51,6 +53,11 @@ uint64_t RowData::get_max_annotation() const
return _max_annotation;
}
uint64_t RowData::get_min_annotation() const
{
return _min_annotation;
}
void RowData::get_annotation_subset(
vector<pv::data::decode::Annotation> &dest,
uint64_t start_sample, uint64_t end_sample) const
@@ -62,10 +69,33 @@ void RowData::get_annotation_subset(
dest.push_back(*i);
}
void RowData::push_annotation(const Annotation &a)
bool RowData::push_annotation(const Annotation &a)
{
_annotations.push_back(a);
_max_annotation = max(_max_annotation, a.end_sample() - a.start_sample());
try {
_annotations.push_back(a);
_max_annotation = max(_max_annotation, a.end_sample() - a.start_sample());
if (a.end_sample() != a.start_sample())
_min_annotation = min(_min_annotation, a.end_sample() - a.start_sample());
return true;
} catch (const std::bad_alloc&) {
return false;
}
}
uint64_t RowData::get_annotation_size() const
{
return _annotations.size();
}
bool RowData::get_annotation(Annotation &ann,
uint64_t index) const
{
if (index < _annotations.size()) {
ann = _annotations[index];
return true;
} else {
return false;
}
}
} // decode

View File

@@ -39,6 +39,7 @@ public:
uint64_t get_max_sample() const;
uint64_t get_max_annotation() const;
uint64_t get_min_annotation() const;
/**
* Extracts sorted annotations between two period into a vector.
*/
@@ -46,10 +47,16 @@ public:
std::vector<pv::data::decode::Annotation> &dest,
uint64_t start_sample, uint64_t end_sample) const;
void push_annotation(const Annotation &a);
bool push_annotation(const Annotation &a);
uint64_t get_annotation_size() const;
bool get_annotation(pv::data::decode::Annotation &ann,
uint64_t index) const;
private:
uint64_t _max_annotation;
uint64_t _min_annotation;
std::vector<Annotation> _annotations;
};

View File

@@ -0,0 +1,108 @@
/*
* This file is part of the DSView project.
*
* Copyright (C) 2016 Andy Deng <andy@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libsigrokdecode/libsigrokdecode.h>
#include <boost/foreach.hpp>
#include <boost/thread/thread.hpp>
#include <pv/data/decode/annotation.h>
#include <pv/data/decode/rowdata.h>
#include "decoderstack.h"
#include "decodermodel.h"
using namespace boost;
using namespace std;
namespace pv {
namespace data {
DecoderModel::DecoderModel(QObject *parent)
: QAbstractTableModel(parent),
_decoder_stack(NULL)
{
}
void DecoderModel::setDecoderStack(boost::shared_ptr<pv::data::DecoderStack> decoder_stack)
{
beginResetModel();
_decoder_stack = decoder_stack;
endResetModel();
}
const boost::shared_ptr<pv::data::DecoderStack>& DecoderModel::getDecoderStack() const
{
return _decoder_stack;
}
int DecoderModel::rowCount(const QModelIndex & /* parent */) const
{
if (_decoder_stack)
return _decoder_stack->list_annotation_size();
else
return 100;
}
int DecoderModel::columnCount(const QModelIndex & /* parent */) const
{
if (_decoder_stack)
return _decoder_stack->list_rows_size();
else
return 1;
}
QVariant DecoderModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::TextAlignmentRole) {
return int(Qt::AlignLeft | Qt::AlignVCenter);
} else if (role == Qt::DisplayRole) {
if (_decoder_stack) {
pv::data::decode::Annotation ann;
if (_decoder_stack->list_annotation(ann, index.column(), index.row())) {
return ann.annotations().at(0);
}
}
}
return QVariant();
}
QVariant DecoderModel::headerData(int section,
Qt::Orientation orientation,
int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Vertical)
return section;
if (_decoder_stack) {
QString title;
if (_decoder_stack->list_row_title(section, title))
return title;
}
return QVariant();
}
} // namespace data
} // namespace pv

View File

@@ -0,0 +1,62 @@
/*
* This file is part of the DSView project.
*
* Copyright (C) 2016 Andy Deng <andy@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DSVIEW_PV_DATA_DECODERMODEL_H
#define DSVIEW_PV_DATA_DECODERMODEL_H
#include <QAbstractTableModel>
#include <boost/shared_ptr.hpp>
#include <pv/data/decode/rowdata.h>
namespace pv {
namespace data {
class DecoderStack;
namespace decode {
class Annotation;
class Decoder;
class Row;
}
class DecoderModel : public QAbstractTableModel
{
public:
DecoderModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role) const;
void setDecoderStack(boost::shared_ptr<pv::data::DecoderStack> decoder_stack);
const boost::shared_ptr<pv::data::DecoderStack>& getDecoderStack() const;
private:
boost::shared_ptr<pv::data::DecoderStack> _decoder_stack;
};
} // namespace data
} // namespace pv
#endif // DSVIEW_PV_DATA_DECODERMODEL_H

View File

@@ -68,7 +68,8 @@ DecoderStack::DecoderStack(pv::SigSession &session,
_frame_complete(false),
_samples_decoded(0),
_decode_state(Stopped),
_options_changed(false)
_options_changed(false),
_no_memory(false)
{
connect(&_session, SIGNAL(frame_began()),
this, SLOT(on_new_frame()));
@@ -79,6 +80,8 @@ DecoderStack::DecoderStack(pv::SigSession &session,
_stack.push_back(shared_ptr<decode::Decoder>(
new decode::Decoder(dec)));
build_row();
}
DecoderStack::~DecoderStack()
@@ -89,7 +92,10 @@ DecoderStack::~DecoderStack()
// }
stop_decode();
_stack.clear();
clear();
_rows.clear();
_rows_gshow.clear();
_rows_lshow.clear();
_class_rows.clear();
}
const std::list< boost::shared_ptr<decode::Decoder> >&
@@ -102,20 +108,83 @@ void DecoderStack::push(boost::shared_ptr<decode::Decoder> decoder)
{
assert(decoder);
_stack.push_back(decoder);
build_row();
_options_changed = true;
}
void DecoderStack::remove(int index)
void DecoderStack::remove(boost::shared_ptr<Decoder> &decoder)
{
assert(index >= 0);
assert(index < (int)_stack.size());
// Find the decoder in the stack
list< shared_ptr<Decoder> >::iterator iter = _stack.begin();
for(int i = 0; i < index; i++, iter++)
assert(iter != _stack.end());
for(int i = 0; i < _stack.size(); i++, iter++)
if ((*iter) == decoder)
break;
// Delete the element
_stack.erase(iter);
if (iter != _stack.end())
_stack.erase(iter);
build_row();
_options_changed = true;
}
void DecoderStack::build_row()
{
_rows.clear();
// Add classes
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
{
assert(dec);
const srd_decoder *const decc = dec->decoder();
assert(dec->decoder());
// Add a row for the decoder if it doesn't have a row list
if (!decc->annotation_rows) {
const Row row(decc);
_rows[row] = decode::RowData();
std::map<const decode::Row, bool>::const_iterator iter = _rows_gshow.find(row);
if (iter == _rows_gshow.end()) {
if (row.title().contains("bit", Qt::CaseInsensitive) ||
row.title().contains("warning", Qt::CaseInsensitive)) {
_rows_gshow[row] = false;
_rows_lshow[row] = false;
} else {
_rows_gshow[row] = true;
_rows_lshow[row] = true;
}
}
}
// Add the decoder rows
for (const GSList *l = decc->annotation_rows; l; l = l->next)
{
const srd_decoder_annotation_row *const ann_row =
(srd_decoder_annotation_row *)l->data;
assert(ann_row);
const Row row(decc, ann_row);
// Add a new empty row data object
_rows[row] = decode::RowData();
std::map<const decode::Row, bool>::const_iterator iter = _rows_gshow.find(row);
if (iter == _rows_gshow.end()) {
if (row.title().contains("bit", Qt::CaseInsensitive) ||
row.title().contains("warning", Qt::CaseInsensitive)) {
_rows_gshow[row] = false;
_rows_lshow[row] = false;
} else {
_rows_gshow[row] = true;
_rows_lshow[row] = true;
}
}
// Map out all the classes
for (const GSList *ll = ann_row->ann_classes;
ll; ll = ll->next)
_class_rows[make_pair(decc,
GPOINTER_TO_INT(ll->data))] = row;
}
}
}
int64_t DecoderStack::samples_decoded() const
@@ -124,36 +193,6 @@ int64_t DecoderStack::samples_decoded() const
return _samples_decoded;
}
std::vector< std::pair<decode::Row, bool> > DecoderStack::get_visible_rows() const
{
lock_guard<mutex> lock(_output_mutex);
std::vector< std::pair<decode::Row, bool> > rows;
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
{
assert(dec);
const srd_decoder *const decc = dec->decoder();
assert(dec->decoder());
// Add a row for the decoder if it doesn't have a row list
if (!decc->annotation_rows)
rows.push_back(make_pair(Row(decc), dec->shown()));
// Add the decoder rows
for (const GSList *l = decc->annotation_rows; l; l = l->next)
{
const srd_decoder_annotation_row *const ann_row =
(srd_decoder_annotation_row *)l->data;
assert(ann_row);
rows.push_back(make_pair(Row(decc, ann_row), dec->shown()));
}
}
return rows;
}
void DecoderStack::get_annotation_subset(
std::vector<pv::data::decode::Annotation> &dest,
const Row &row, uint64_t start_sample,
@@ -161,9 +200,9 @@ void DecoderStack::get_annotation_subset(
{
lock_guard<mutex> lock(_output_mutex);
std::map<const Row, decode::RowData>::const_iterator iter =
_rows.find(row);
if (iter != _rows.end())
std::map<const Row, decode::RowData>::const_iterator iter =
_rows.find(row);
if (iter != _rows.end())
(*iter).second.get_annotation_subset(dest,
start_sample, end_sample);
}
@@ -180,6 +219,44 @@ uint64_t DecoderStack::get_max_annotation(const Row &row)
return 0;
}
uint64_t DecoderStack::get_min_annotation(const Row &row)
{
lock_guard<mutex> lock(_output_mutex);
std::map<const Row, decode::RowData>::const_iterator iter =
_rows.find(row);
if (iter != _rows.end())
return (*iter).second.get_min_annotation();
return 0;
}
std::map<const decode::Row, bool>& DecoderStack::get_rows_gshow()
{
return _rows_gshow;
}
std::map<const decode::Row, bool>& DecoderStack::get_rows_lshow()
{
return _rows_lshow;
}
void DecoderStack::set_rows_gshow(const decode::Row row, bool show)
{
std::map<const decode::Row, bool>::const_iterator iter = _rows_gshow.find(row);
if (iter != _rows_gshow.end()) {
_rows_gshow[row] = show;
}
}
void DecoderStack::set_rows_lshow(const decode::Row row, bool show)
{
std::map<const decode::Row, bool>::const_iterator iter = _rows_lshow.find(row);
if (iter != _rows_lshow.end()) {
_rows_lshow[row] = show;
}
}
bool DecoderStack::has_annotations(const Row &row) const
{
lock_guard<mutex> lock(_output_mutex);
@@ -195,6 +272,55 @@ bool DecoderStack::has_annotations(const Row &row) const
return false;
}
uint64_t DecoderStack::list_annotation_size() const
{
uint64_t max_annotation_size = 0;
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
if (iter != _rows_lshow.end() && (*iter).second)
max_annotation_size = max(max_annotation_size,
(*i).second.get_annotation_size());
}
return max_annotation_size;
}
bool DecoderStack::list_annotation(pv::data::decode::Annotation &ann,
uint16_t row_index, uint64_t col_index) const
{
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
if (iter != _rows_lshow.end() && (*iter).second) {
if (row_index-- == 0) {
return (*i).second.get_annotation(ann, col_index);
}
}
}
return false;
}
bool DecoderStack::list_row_title(int row, QString &title) const
{
int index = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
if (iter != _rows_lshow.end() && (*iter).second) {
if (row-- == 0) {
title = (*i).first.title();
return 1;
}
}
}
return 0;
}
QString DecoderStack::error_message()
{
lock_guard<mutex> lock(_output_mutex);
@@ -207,16 +333,20 @@ void DecoderStack::clear()
_frame_complete = false;
_samples_decoded = 0;
_error_message = QString();
_rows.clear();
_class_rows.clear();
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++)
_rows[(*i).first] = decode::RowData();
_no_memory = false;
}
void DecoderStack::stop_decode()
{
_snapshot.reset();
if(_decode_state == Stopped)
if(_decode_state == Stopped) {
clear();
return;
}
if (_decode_thread.get()) {
_decode_thread->interrupt();
@@ -224,6 +354,7 @@ void DecoderStack::stop_decode()
_decode_state = Stopped;
}
_decode_thread.reset();
clear();
}
void DecoderStack::begin_decode()
@@ -239,8 +370,6 @@ void DecoderStack::begin_decode()
// }
stop_decode();
clear();
// Check that all decoders have the required channels
BOOST_FOREACH(const shared_ptr<decode::Decoder> &dec, _stack)
if (!dec->have_required_probes()) {
@@ -249,37 +378,6 @@ void DecoderStack::begin_decode()
return;
}
// Add classes
BOOST_FOREACH (const shared_ptr<decode::Decoder> &dec, _stack)
{
assert(dec);
const srd_decoder *const decc = dec->decoder();
assert(dec->decoder());
// Add a row for the decoder if it doesn't have a row list
if (!decc->annotation_rows)
_rows[Row(decc)] = decode::RowData();
// Add the decoder rows
for (const GSList *l = decc->annotation_rows; l; l = l->next)
{
const srd_decoder_annotation_row *const ann_row =
(srd_decoder_annotation_row *)l->data;
assert(ann_row);
const Row row(decc, ann_row);
// Add a new empty row data object
_rows[row] = decode::RowData();
// Map out all the classes
for (const GSList *ll = ann_row->ann_classes;
ll; ll = ll->next)
_class_rows[make_pair(decc,
GPOINTER_TO_INT(ll->data))] = row;
}
}
// We get the logic data of the first channel in the list.
// This works because we are currently assuming all
// LogicSignals have the same data/snapshot
@@ -313,8 +411,8 @@ uint64_t DecoderStack::get_max_sample_count() const
{
uint64_t max_sample_count = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++)
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++)
max_sample_count = max(max_sample_count,
(*i).second.get_max_sample());
@@ -333,48 +431,6 @@ boost::optional<uint64_t> DecoderStack::wait_for_data() const
_sample_count);
}
//void DecoderStack::decode_data(
// const uint64_t sample_count, const unsigned int unit_size,
// srd_session *const session)
//{
// //uint8_t chunk[DecodeChunkLength];
// uint8_t *chunk = NULL;
// //chunk = (uint8_t *)realloc(chunk, DecodeChunkLength);
// const uint64_t chunk_sample_count =
// DecodeChunkLength / _snapshot->unit_size();
// for (uint64_t i = 0;
// !boost::this_thread::interruption_requested() &&
// i < sample_count;
// i += chunk_sample_count)
// {
// //lock_guard<mutex> decode_lock(_global_decode_mutex);
// const uint64_t chunk_end = min(
// i + chunk_sample_count, sample_count);
// chunk = _snapshot->get_samples(i, chunk_end);
// if (srd_session_send(session, i, i + sample_count, chunk,
// (chunk_end - i) * unit_size, unit_size) != SRD_OK) {
// _error_message = tr("Decoder reported an error");
// break;
// }
// {
// lock_guard<mutex> lock(_output_mutex);
// _samples_decoded = chunk_end;
// }
// if (i % DecodeNotifyPeriod == 0)
// new_decode_data();
// }
// _options_changed = false;
// decode_done();
// //new_decode_data();
//}
void DecoderStack::decode_data(
const uint64_t decode_start, const uint64_t decode_end,
const unsigned int unit_size, srd_session *const session)
@@ -386,7 +442,7 @@ void DecoderStack::decode_data(
for (uint64_t i = decode_start;
!boost::this_thread::interruption_requested() &&
i < decode_end;
i < decode_end && !_no_memory;
i += chunk_sample_count)
{
//lock_guard<mutex> decode_lock(_global_decode_mutex);
@@ -490,6 +546,11 @@ uint64_t DecoderStack::sample_count() const
return 0;
}
uint64_t DecoderStack::sample_rate() const
{
return _samplerate;
}
void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
{
assert(pdata);
@@ -500,6 +561,9 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
lock_guard<mutex> lock(d->_output_mutex);
if (d->_no_memory)
return;
const Annotation a(pdata);
// Find the row
@@ -508,21 +572,21 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
const srd_decoder *const decc = pdata->pdo->di->decoder;
assert(decc);
map<const Row, decode::RowData>::iterator row_iter = d->_rows.end();
map<const Row, decode::RowData>::iterator row_iter = d->_rows.end();
// Try looking up the sub-row of this class
const map<pair<const srd_decoder*, int>, Row>::const_iterator r =
d->_class_rows.find(make_pair(decc, a.format()));
if (r != d->_class_rows.end())
row_iter = d->_rows.find((*r).second);
row_iter = d->_rows.find((*r).second);
else
{
// Failing that, use the decoder as a key
row_iter = d->_rows.find(Row(decc));
row_iter = d->_rows.find(Row(decc));
}
assert(row_iter != d->_rows.end());
if (row_iter == d->_rows.end()) {
assert(row_iter != d->_rows.end());
if (row_iter == d->_rows.end()) {
qDebug() << "Unexpected annotation: decoder = " << decc <<
", format = " << a.format();
assert(0);
@@ -530,7 +594,8 @@ void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
}
// Add the annotation
(*row_iter).second.push_annotation(a);
if (!(*row_iter).second.push_annotation(a))
d->_no_memory = true;
}
void DecoderStack::on_new_frame()
@@ -560,21 +625,25 @@ void DecoderStack::on_frame_ended()
begin_decode();
}
int DecoderStack::cur_rows_size()
int DecoderStack::list_rows_size()
{
int rows_size = 0;
int row = 0;
for (map<const Row, RowData>::const_iterator i = _rows.begin();
i != _rows.end(); i++)
if ((*i).second.get_max_sample() != 0)
i != _rows.end(); i++) {
map<const Row, bool>::const_iterator iter = _rows_lshow.find((*i).first);
if (iter != _rows_lshow.end() && (*iter).second)
rows_size++;
if (rows_size == 0)
return 1;
else
return rows_size;
}
return rows_size;
}
void DecoderStack::options_changed(bool changed)
bool DecoderStack::options_changed() const
{
return _options_changed;
}
void DecoderStack::set_options_changed(bool changed)
{
_options_changed = changed;
}

View File

@@ -86,14 +86,13 @@ public:
virtual ~DecoderStack();
const std::list< boost::shared_ptr<decode::Decoder> >& stack() const;
const std::list< boost::shared_ptr<decode::Decoder> >& stack() const;
void push(boost::shared_ptr<decode::Decoder> decoder);
void remove(int index);
void remove(boost::shared_ptr<decode::Decoder>& decoder);
void build_row();
int64_t samples_decoded() const;
std::vector< std::pair<decode::Row, bool> > get_visible_rows() const;
/**
* Extracts sorted annotations between two period into a vector.
*/
@@ -103,9 +102,23 @@ public:
uint64_t end_sample) const;
uint64_t get_max_annotation(const decode::Row &row);
uint64_t get_min_annotation(const decode::Row &row); // except instant(end=start) annotation
std::map<const decode::Row, bool> &get_rows_gshow();
std::map<const decode::Row, bool> &get_rows_lshow();
void set_rows_gshow(const decode::Row row, bool show);
void set_rows_lshow(const decode::Row row, bool show);
bool has_annotations(const decode::Row &row) const;
uint64_t list_annotation_size() const;
bool list_annotation(decode::Annotation &ann,
uint16_t row_index, uint64_t col_index) const;
bool list_row_title(int row, QString &title) const;
QString error_message();
void clear();
@@ -116,11 +129,13 @@ public:
void stop_decode();
int cur_rows_size();
int list_rows_size();
void options_changed(bool changed);
bool options_changed() const;
void set_options_changed(bool changed);
uint64_t sample_count() const;
uint64_t sample_rate() const;
private:
boost::optional<uint64_t> wait_for_data() const;
@@ -170,9 +185,10 @@ private:
mutable boost::mutex _output_mutex;
int64_t _samples_decoded;
std::map<const decode::Row, decode::RowData> _rows;
std::map<std::pair<const srd_decoder*, int>, decode::Row> _class_rows;
std::map<const decode::Row, decode::RowData> _rows;
std::map<const decode::Row, bool> _rows_gshow;
std::map<const decode::Row, bool> _rows_lshow;
std::map<std::pair<const srd_decoder*, int>, decode::Row> _class_rows;
QString _error_message;
@@ -180,6 +196,7 @@ private:
decode_state _decode_state;
bool _options_changed;
bool _no_memory;
friend class DecoderStackTest::TwoDecoderStack;
};

View File

@@ -0,0 +1,215 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "protocolexp.h"
#include <boost/foreach.hpp>
#include <QFormLayout>
#include <QListWidget>
#include <QMessageBox>
#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include <QProgressDialog>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#include "../sigsession.h"
#include "../data/decoderstack.h"
#include "../data/decode/row.h"
#include "../data/decode/annotation.h"
#include "../view/decodetrace.h"
#include "../data/decodermodel.h"
using namespace boost;
using namespace std;
namespace pv {
namespace dialogs {
ProtocolExp::ProtocolExp(QWidget *parent, SigSession &session) :
QDialog(parent),
_session(session),
_button_box(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, this),
_export_cancel(false)
{
_format_combobox = new QComboBox(this);
_format_combobox->addItem(tr("Comma-Separated Values (*.csv)"));
_format_combobox->addItem(tr("Text files (*.txt)"));
_flayout = new QFormLayout();
_flayout->addRow(new QLabel(tr("Export Format: "), this), _format_combobox);
pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
const boost::shared_ptr<pv::data::DecoderStack>& decoder_stack = decoder_model->getDecoderStack();
if (decoder_stack) {
int row_index = 0;
const std::map<const pv::data::decode::Row, bool>& rows(decoder_stack->get_rows_lshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if ((*i).second) {
QLabel *row_label = new QLabel((*i).first.title(), this);
QRadioButton *row_sel = new QRadioButton(this);
if (row_index == 0) {
row_sel->setChecked(true);
}
_row_label_list.push_back(row_label);
_row_sel_list.push_back(row_sel);
_flayout->addRow(row_label, row_sel);
row_sel->setProperty("index", row_index);
row_sel->setProperty("title", (*i).first.title());
row_index++;
}
}
}
_layout = new QVBoxLayout(this);
_layout->addLayout(_flayout);
_layout->addWidget(&_button_box);
setLayout(_layout);
connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
connect(&_button_box, SIGNAL(rejected()), this, SLOT(reject()));
}
void ProtocolExp::accept()
{
using namespace Qt;
using namespace pv::data::decode;
QDialog::accept();
if (!_row_sel_list.empty()) {
QList<QString> supportedFormats;
for (int i = _format_combobox->count() - 1; i >= 0; i--) {
supportedFormats.push_back(_format_combobox->itemText(i));
}
QString filter;
for(int i = 0; i < supportedFormats.count();i++){
filter.append(supportedFormats[i]);
if(i < supportedFormats.count() - 1)
filter.append(";;");
}
QString default_filter = _format_combobox->currentText();
QString file_name = QFileDialog::getSaveFileName(
this, tr("Export Data"), "",filter,&default_filter);
if (!file_name.isEmpty()) {
QFileInfo f(file_name);
QStringList list = default_filter.split('.').last().split(')');
QString ext = list.first();
if(f.suffix().compare(ext))
file_name+=tr(".")+ext;
QFile file(file_name);
file.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream out(&file);
out.setCodec("UTF-8");
out.setGenerateByteOrderMark(true);
QFuture<void> future;
future = QtConcurrent::run([&]{
_export_cancel = false;
QString title;
int index;
for (std::list<QRadioButton *>::const_iterator i = _row_sel_list.begin();
i != _row_sel_list.end(); i++) {
if ((*i)->isChecked()) {
title = (*i)->property("title").toString();
index = (*i)->property("index").toULongLong();
break;
}
}
out << QString("%1;%2;%3\n")
.arg("ID")
.arg("Time[s]")
.arg(title);
pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
const boost::shared_ptr<pv::data::DecoderStack>& decoder_stack = decoder_model->getDecoderStack();
int row_index = 0;
Row row;
const std::map<const Row, bool>& rows_lshow(decoder_stack->get_rows_lshow());
for (std::map<const Row, bool>::const_iterator i = rows_lshow.begin();
i != rows_lshow.end(); i++) {
if ((*i).second) {
if (index == row_index) {
row = (*i).first;
break;
}
row_index++;
}
}
uint64_t exported = 0;
double time_pre_samples = 1.0 / decoder_stack->samplerate();
vector<Annotation> annotations;
decoder_stack->get_annotation_subset(annotations, row,
0, decoder_stack->sample_count()-1);
if (!annotations.empty()) {
BOOST_FOREACH(const Annotation &a, annotations) {
out << QString("%1;%2;%3\n")
.arg(QString::number(exported))
.arg(QString::number(a.start_sample()*time_pre_samples))
.arg(a.annotations().at(0));
exported++;
emit export_progress(exported*100/annotations.size());
if (_export_cancel)
break;
}
}
});
Qt::WindowFlags flags = Qt::CustomizeWindowHint;
QProgressDialog dlg(tr("Export Protocol List Result... It can take a while."),
tr("Cancel"),0,100,this,flags);
dlg.setWindowModality(Qt::WindowModal);
dlg.setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
QFutureWatcher<void> watcher;
connect(&watcher,SIGNAL(finished()),&dlg,SLOT(cancel()));
connect(this,SIGNAL(export_progress(int)),&dlg,SLOT(setValue(int)));
connect(&dlg,SIGNAL(canceled()),this,SLOT(cancel_export()));
watcher.setFuture(future);
dlg.exec();
future.waitForFinished();
file.close();
}
}
}
void ProtocolExp::reject()
{
using namespace Qt;
QDialog::reject();
}
void ProtocolExp::cancel_export()
{
_export_cancel = true;
}
} // namespace dialogs
} // namespace pv

View File

@@ -0,0 +1,85 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DSVIEW_PV_PROTOCOLEXP_H
#define DSVIEW_PV_PROTOCOLEXP_H
#include <QDialog>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QRadioButton>
#include <QComboBox>
#include <boost/shared_ptr.hpp>
#include "../device/devinst.h"
#include "../prop/binding/deviceoptions.h"
namespace pv {
class SigSession;
namespace data {
namespace decode {
class Row;
}
}
namespace dialogs {
class ProtocolExp : public QDialog
{
Q_OBJECT
public:
ProtocolExp(QWidget *parent, SigSession &session);
protected:
void accept();
void reject();
signals:
void export_progress(int percent);
private slots:
void cancel_export();
private:
SigSession &_session;
QComboBox *_format_combobox;
std::list<QRadioButton *> _row_sel_list;
std::list<QLabel *> _row_label_list;
QFormLayout *_flayout;
QVBoxLayout *_layout;
QDialogButtonBox _button_box;
bool _export_cancel;
};
} // namespace dialogs
} // namespace pv
#endif // DSVIEW_PV_PROTOCOLEXP_H

View File

@@ -0,0 +1,183 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "protocollist.h"
#include <boost/foreach.hpp>
#include <QFormLayout>
#include <QListWidget>
#include <QMessageBox>
#include "../sigsession.h"
#include "../data/decoderstack.h"
#include "../data/decode/row.h"
#include "../view/decodetrace.h"
#include "../data/decodermodel.h"
using namespace boost;
using namespace std;
namespace pv {
namespace dialogs {
ProtocolList::ProtocolList(QWidget *parent, SigSession &session) :
QDialog(parent),
_session(session),
_button_box(QDialogButtonBox::Ok,
Qt::Horizontal, this)
{
pv::data::DecoderModel* decoder_model = _session.get_decoder_model();
_protocol_combobox = new QComboBox(this);
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
int index = 0;
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
_protocol_combobox->addItem(d->get_name());
if (decoder_model->getDecoderStack() == d->decoder())
_protocol_combobox->setCurrentIndex(index);
index++;
}
_protocol_combobox->addItem("", qVariantFromValue(NULL));
if (decoder_model->getDecoderStack() == NULL)
_protocol_combobox->setCurrentIndex(index);
_flayout = new QFormLayout();
_flayout->addRow(new QLabel(tr("Decoded Protocols: "), this), _protocol_combobox);
_layout = new QVBoxLayout(this);
_layout->addLayout(_flayout);
_layout->addWidget(&_button_box);
setLayout(_layout);
connect(&_button_box, SIGNAL(accepted()), this, SLOT(accept()));
connect(_protocol_combobox, SIGNAL(currentIndexChanged(int)), this, SLOT(set_protocol(int)));
set_protocol(_protocol_combobox->currentIndex());
}
void ProtocolList::accept()
{
using namespace Qt;
QDialog::accept();
}
void ProtocolList::reject()
{
using namespace Qt;
QDialog::accept();
}
void ProtocolList::set_protocol(int index)
{
(void)index;
for(std::list<QCheckBox *>::const_iterator i = _show_checkbox_list.begin();
i != _show_checkbox_list.end(); i++) {
(*i)->setParent(NULL);
_flayout->removeWidget((*i));
delete (*i);
}
_show_checkbox_list.clear();
for(std::list<QLabel *>::const_iterator i = _show_label_list.begin();
i != _show_label_list.end(); i++) {
(*i)->setParent(NULL);
_flayout->removeWidget((*i));
delete (*i);
}
_show_label_list.clear();
boost::shared_ptr<pv::data::DecoderStack> decoder_stack;
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
int cur_index = 0;
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
if (index == cur_index) {
decoder_stack = d->decoder();
break;
}
cur_index++;
}
if (!decoder_stack){
_session.get_decoder_model()->setDecoderStack(NULL);
return;
}
_session.get_decoder_model()->setDecoderStack(decoder_stack);
int row_index = 0;
const std::map<const pv::data::decode::Row, bool>& rows(decoder_stack->get_rows_lshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
QLabel *row_label = new QLabel((*i).first.title(), this);
QCheckBox *row_checkbox = new QCheckBox(this);
//row_checkbox->setChecked(false);
_show_label_list.push_back(row_label);
_show_checkbox_list.push_back(row_checkbox);
_flayout->addRow(row_label, row_checkbox);
row_checkbox->setChecked((*i).second);
connect(row_checkbox, SIGNAL(clicked(bool)), this, SLOT(on_row_check(bool)));
row_checkbox->setProperty("index", row_index);
row_index++;
}
}
void ProtocolList::on_row_check(bool show)
{
QCheckBox *sc = dynamic_cast<QCheckBox*>(sender());
QVariant id = sc->property("index");
int index = id.toInt();
boost::shared_ptr<pv::data::DecoderStack> decoder_stack;
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
int cur_index = 0;
BOOST_FOREACH(boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
if (cur_index == _protocol_combobox->currentIndex()) {
decoder_stack = d->decoder();
break;
}
cur_index++;
}
if (!decoder_stack)
return;
std::map<const pv::data::decode::Row, bool>& rows(decoder_stack->get_rows_lshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if (index-- == 0) {
decoder_stack->set_rows_lshow((*i).first, show);
break;
}
}
_session.get_decoder_model()->setDecoderStack(decoder_stack);
}
} // namespace dialogs
} // namespace pv

View File

@@ -0,0 +1,76 @@
/*
* This file is part of the DSView project.
* DSView is based on PulseView.
*
* Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
* Copyright (C) 2013 DreamSourceLab <dreamsourcelab@dreamsourcelab.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef DSVIEW_PV_PROTOCOLLIST_H
#define DSVIEW_PV_PROTOCOLLIST_H
#include <QDialog>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QCheckBox>
#include <QComboBox>
#include <boost/shared_ptr.hpp>
#include "../device/devinst.h"
#include "../prop/binding/deviceoptions.h"
namespace pv {
class SigSession;
namespace dialogs {
class ProtocolList : public QDialog
{
Q_OBJECT
public:
ProtocolList(QWidget *parent, SigSession &session);
protected:
void accept();
void reject();
private slots:
void set_protocol(int index);
void on_row_check(bool show);
private:
SigSession &_session;
QComboBox *_protocol_combobox;
std::list<QCheckBox *> _show_checkbox_list;
std::list<QLabel *> _show_label_list;
QFormLayout *_flayout;
QVBoxLayout *_layout;
QDialogButtonBox _button_box;
};
} // namespace dialogs
} // namespace pv
#endif // DSVIEW_PV_PROTOCOLLIST_H

View File

@@ -25,13 +25,21 @@
#include "../sigsession.h"
#include "../view/decodetrace.h"
#include "../device/devinst.h"
#include "../data/decodermodel.h"
#include "../data/decoderstack.h"
#include "../dialogs/protocollist.h"
#include "../dialogs/protocolexp.h"
#include <QObject>
#include <QHBoxLayout>
#include <QPainter>
#include <QMessageBox>
#include <QFormLayout>
#include <QStandardItemModel>
#include <QTableView>
#include <QHeaderView>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
namespace pv {
@@ -41,20 +49,20 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
QScrollArea(parent),
_session(session)
{
_widget = new QWidget(this);
_up_widget = new QWidget(this);
QHBoxLayout *hori_layout = new QHBoxLayout();
_add_button = new QPushButton(_widget);
_add_button = new QPushButton(_up_widget);
_add_button->setFlat(true);
_add_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/add.png")));
_del_all_button = new QPushButton(_widget);
_del_all_button = new QPushButton(_up_widget);
_del_all_button->setFlat(true);
_del_all_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/del.png")));
_del_all_button->setCheckable(true);
_protocol_combobox = new QComboBox(_widget);
_protocol_combobox = new QComboBox(_up_widget);
GSList *l = g_slist_sort(g_slist_copy(
(GSList*)srd_decoder_list()), decoder_name_cmp);
@@ -80,15 +88,72 @@ ProtocolDock::ProtocolDock(QWidget *parent, SigSession &session) :
connect(_del_all_button, SIGNAL(clicked()),
this, SLOT(del_protocol()));
_layout = new QVBoxLayout();
_layout->addLayout(hori_layout);
_layout->addStretch(1);
_up_layout = new QVBoxLayout();
_up_layout->addLayout(hori_layout);
_up_layout->addStretch(1);
_widget->setLayout(_layout);
_up_widget->setLayout(_up_layout);
_up_widget->setMinimumHeight(120);
this->setWidget(_widget);
_widget->setGeometry(0, 0, sizeHint().width(), 500);
_widget->setObjectName("protocolWidget");
// this->setWidget(_widget);
// _widget->setGeometry(0, 0, sizeHint().width(), 500);
// _widget->setObjectName("protocolWidget");
_dn_widget = new QWidget(this);
_dn_set_button = new QPushButton(_dn_widget);
_dn_set_button->setFlat(true);
_dn_set_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/gear.png")));
connect(_dn_set_button, SIGNAL(clicked()),
this, SLOT(set_model()));
_dn_save_button = new QPushButton(_dn_widget);
_dn_save_button->setFlat(true);
_dn_save_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/save.png")));
connect(_dn_save_button, SIGNAL(clicked()),
this, SLOT(export_table_view()));
QHBoxLayout *dn_title_layout = new QHBoxLayout();
dn_title_layout->addWidget(_dn_set_button, 0, Qt::AlignLeft);
dn_title_layout->addWidget(_dn_save_button, 0, Qt::AlignLeft);
dn_title_layout->addWidget(new QLabel(tr("Protocol List Viewer"), _dn_widget), 1, Qt::AlignLeft);
dn_title_layout->addStretch(1);
_table_view = new QTableView(_dn_widget);
_table_view->setModel(_session.get_decoder_model());
_table_view->setAlternatingRowColors(true);
_table_view->setShowGrid(false);
_table_view->horizontalHeader()->setStretchLastSection(true);
_table_view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
_table_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
QVBoxLayout *dn_layout = new QVBoxLayout();
dn_layout->addLayout(dn_title_layout);
dn_layout->addWidget(_table_view);
_dn_widget->setLayout(dn_layout);
_dn_widget->setMinimumHeight(400);
_split_widget = new QSplitter(this);
_split_widget->insertWidget(0, _up_widget);
_split_widget->insertWidget(1, _dn_widget);
_split_widget->setOrientation(Qt::Vertical);
_split_widget->setCollapsible(0, false);
_split_widget->setCollapsible(1, false);
//_split_widget->setStretchFactor(1, 1);
//_split_widget
this->setWidgetResizable(true);
this->setWidget(_split_widget);
//_split_widget->setGeometry(0, 0, sizeHint().width(), 500);
_split_widget->setObjectName("protocolWidget");
connect(&_session, SIGNAL(decode_done()), this, SLOT(update_model()));
connect(this, SIGNAL(protocol_updated()), this, SLOT(update_model()));
connect(_table_view, SIGNAL(clicked(QModelIndex)), this, SLOT(item_clicked(QModelIndex)));
connect(_table_view->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(column_resize(int, int, int)));
}
ProtocolDock::~ProtocolDock()
@@ -126,15 +191,15 @@ void ProtocolDock::add_protocol()
//QMap <QString, QVariant>& _options = dlg.get_options();
//QMap <QString, int> _options_index = dlg.get_options_index();
QPushButton *_del_button = new QPushButton(_widget);
QPushButton *_set_button = new QPushButton(_widget);
QPushButton *_del_button = new QPushButton(_up_widget);
QPushButton *_set_button = new QPushButton(_up_widget);
_del_button->setFlat(true);
_del_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/del.png")));
_set_button->setFlat(true);
_set_button->setIcon(QIcon::fromTheme("protocol",
QIcon(":/icons/gear.png")));
QLabel *_protocol_label = new QLabel(_widget);
QLabel *_protocol_label = new QLabel(_up_widget);
_del_button->setCheckable(true);
_protocol_label->setText(_protocol_combobox->currentText());
@@ -155,9 +220,10 @@ void ProtocolDock::add_protocol()
hori_layout->addWidget(_protocol_label);
hori_layout->addStretch(1);
_hori_layout_list.push_back(hori_layout);
_layout->insertLayout(_del_button_list.size(), hori_layout);
_up_layout->insertLayout(_del_button_list.size(), hori_layout);
//_session.add_protocol_analyzer(_protocol_combobox->currentIndex(), _sel_probes, _options, _options_index);
protocol_updated();
}
}
}
@@ -183,6 +249,7 @@ void ProtocolDock::rst_protocol()
}
rst_index++;
}
protocol_updated();
}
void ProtocolDock::del_protocol()
@@ -193,7 +260,7 @@ void ProtocolDock::del_protocol()
int del_index = 0;
for (QVector <QHBoxLayout *>::const_iterator i = _hori_layout_list.begin();
i != _hori_layout_list.end(); i++) {
_layout->removeItem((*i));
_up_layout->removeItem((*i));
delete (*i);
delete _del_button_list.at(del_index);
delete _set_button_list.at(del_index);
@@ -220,7 +287,7 @@ void ProtocolDock::del_protocol()
for (QVector <QPushButton *>::const_iterator i = _del_button_list.begin();
i != _del_button_list.end(); i++) {
if ((*i)->isChecked()) {
_layout->removeItem(_hori_layout_list.at(del_index));
_up_layout->removeItem(_hori_layout_list.at(del_index));
delete _hori_layout_list.at(del_index);
delete _del_button_list.at(del_index);
@@ -234,12 +301,12 @@ void ProtocolDock::del_protocol()
_protocol_index_list.remove(del_index);
_session.remove_decode_signal(del_index);
break;
}
del_index++;
}
}
protocol_updated();
}
void ProtocolDock::del_all_protocol()
@@ -248,7 +315,7 @@ void ProtocolDock::del_all_protocol()
int del_index = 0;
for (QVector <QHBoxLayout *>::const_iterator i = _hori_layout_list.begin();
i != _hori_layout_list.end(); i++) {
_layout->removeItem((*i));
_up_layout->removeItem((*i));
delete (*i);
delete _del_button_list.at(del_index);
delete _set_button_list.at(del_index);
@@ -262,8 +329,90 @@ void ProtocolDock::del_all_protocol()
_set_button_list.clear();
_protocol_label_list.clear();
_protocol_index_list.clear();
protocol_updated();
}
}
void ProtocolDock::set_model()
{
pv::dialogs::ProtocolList *protocollist_dlg = new pv::dialogs::ProtocolList(this, _session);
protocollist_dlg->exec();
resize_table_view(_session.get_decoder_model());
}
void ProtocolDock::update_model()
{
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
const std::vector< boost::shared_ptr<pv::view::DecodeTrace> > decode_sigs(
_session.get_decode_signals());
if (decode_sigs.size() == 0)
decoder_model->setDecoderStack(NULL);
else if (!decoder_model->getDecoderStack())
decoder_model->setDecoderStack(decode_sigs.at(0)->decoder());
else {
int index = 0;
BOOST_FOREACH(const boost::shared_ptr<pv::view::DecodeTrace> d, decode_sigs) {
if (d->decoder() == decoder_model->getDecoderStack()) {
decoder_model->setDecoderStack(d->decoder());
break;
}
index++;
}
if (index >= decode_sigs.size())
decoder_model->setDecoderStack(decode_sigs.at(0)->decoder());
}
resize_table_view(decoder_model);
}
void ProtocolDock::resize_table_view(data::DecoderModel* decoder_model)
{
if (decoder_model->getDecoderStack()) {
for (int i = 0; i < decoder_model->columnCount(QModelIndex()) - 1; i++) {
_table_view->resizeColumnToContents(i);
if (_table_view->columnWidth(i) > 200)
_table_view->setColumnWidth(i, 200);
}
int top_row = _table_view->rowAt(0);
int bom_row = _table_view->rowAt(_table_view->height());
if (bom_row >= top_row && top_row >= 0) {
for (int i = top_row; i <= bom_row; i++)
_table_view->resizeRowToContents(i);
}
}
}
void ProtocolDock::item_clicked(const QModelIndex &index)
{
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
boost::shared_ptr<pv::data::DecoderStack> decoder_stack = decoder_model->getDecoderStack();
if (decoder_stack) {
pv::data::decode::Annotation ann;
if (decoder_stack->list_annotation(ann, index.column(), index.row())) {
_session.show_region(ann.start_sample(), ann.end_sample());
}
}
}
void ProtocolDock::column_resize(int index, int old_size, int new_size)
{
pv::data::DecoderModel *decoder_model = _session.get_decoder_model();
if (decoder_model->getDecoderStack()) {
int top_row = _table_view->rowAt(0);
int bom_row = _table_view->rowAt(_table_view->height());
if (bom_row >= top_row && top_row >= 0) {
for (int i = top_row; i <= bom_row; i++)
_table_view->resizeRowToContents(i);
}
}
}
void ProtocolDock::export_table_view()
{
pv::dialogs::ProtocolExp *protocolexp_dlg = new pv::dialogs::ProtocolExp(this, _session);
protocolexp_dlg->exec();
}
} // namespace dock
} // namespace pv

View File

@@ -34,15 +34,23 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QSplitter>
#include <QTableView>
#include <vector>
#include <libsigrok4DSL/libsigrok.h>
#include "../data/decodermodel.h"
namespace pv {
class SigSession;
namespace data {
class DecoderModel;
}
namespace dock {
class ProtocolDock : public QScrollArea
@@ -58,19 +66,29 @@ public:
void del_all_protocol();
signals:
void protocol_updated();
private slots:
void add_protocol();
void rst_protocol();
void del_protocol();
void set_model();
void update_model();
void export_table_view();
void item_clicked(const QModelIndex &index);
void column_resize(int index, int old_size, int new_size);
private:
static int decoder_name_cmp(const void *a, const void *b);
void resize_table_view(data::DecoderModel *decoder_model);
private:
SigSession &_session;
QWidget *_widget;
QSplitter *_split_widget;
QWidget *_up_widget;
QWidget *_dn_widget;
QTableView *_table_view;
QPushButton *_add_button;
QPushButton *_del_all_button;
@@ -80,7 +98,10 @@ private:
QVector <QLabel *> _protocol_label_list;
QVector <int > _protocol_index_list;
QVector <QHBoxLayout *> _hori_layout_list;
QVBoxLayout *_layout;
QVBoxLayout *_up_layout;
QPushButton *_dn_set_button;
QPushButton *_dn_save_button;
};
} // namespace dock

View File

@@ -197,7 +197,9 @@ void MainWindow::setup_ui()
SLOT(device_change()));
connect(_dso_trigger_widget, SIGNAL(set_trig_pos(quint64)), _view,
SLOT(set_trig_pos(quint64)));
connect(_protocol_widget, SIGNAL(protocol_updated()), _view, SLOT(signals_changed()));
setIconSize(QSize(40,40));
addToolBar(_sampling_bar);
addToolBar(_trig_bar);
addToolBar(_file_bar);

View File

@@ -41,6 +41,7 @@
#include "data/groupsnapshot.h"
#include "data/decoderstack.h"
#include "data/decode/decoder.h"
#include "data/decodermodel.h"
#include "view/analogsignal.h"
#include "view/dsosignal.h"
@@ -99,6 +100,7 @@ SigSession::SigSession(DeviceManager &device_manager) :
_refresh_timer.stop();
_refresh_timer.setSingleShot(true);
_data_lock = false;
_decoder_model = new pv::data::DecoderModel(this);
connect(this, SIGNAL(start_timer(int)), &_view_timer, SLOT(start(int)));
//connect(&_view_timer, SIGNAL(timeout()), this, SLOT(refresh()));
connect(&_refresh_timer, SIGNAL(timeout()), this, SLOT(data_unlock()));
@@ -455,7 +457,6 @@ void SigSession::start_capture(bool instant,
_view_timer.blockSignals(false);
// Begin the session
_sampling_thread.reset(new boost::thread(
&SigSession::sample_thread_proc, this, _dev_inst,
error_handler));
@@ -1104,9 +1105,10 @@ void SigSession::data_feed_in(const struct sr_dev_inst *sdi,
_cur_logic_snapshot.reset();
_cur_dso_snapshot.reset();
_cur_analog_snapshot.reset();
#ifdef ENABLE_DECODE
BOOST_FOREACH(const boost::shared_ptr<view::DecodeTrace> d, _decode_traces)
d->frame_ended();
#endif
}
frame_ended();
@@ -1394,6 +1396,12 @@ void SigSession::rst_decoder(view::DecodeTrace *signal)
return;
}
}
pv::data::DecoderModel* SigSession::get_decoder_model() const
{
return _decoder_model;
}
#endif
} // namespace pv

View File

@@ -67,6 +67,7 @@ class Logic;
class LogicSnapshot;
class Group;
class GroupSnapshot;
class DecoderModel;
}
namespace device {
@@ -154,6 +155,8 @@ public:
void rst_decoder(view::DecodeTrace *signal);
pv::data::DecoderModel* get_decoder_model() const;
#endif
void init_signals();
@@ -234,6 +237,7 @@ private:
std::vector< boost::shared_ptr<view::GroupSignal> > _group_traces;
#ifdef ENABLE_DECODE
std::vector< boost::shared_ptr<view::DecodeTrace> > _decode_traces;
pv::data::DecoderModel *_decoder_model;
#endif
mutable boost::mutex _data_mutex;
@@ -291,6 +295,10 @@ signals:
void zero_adj();
void progressSaveFileValueChanged(int percent);
void decode_done();
void show_region(uint64_t start, uint64_t end);
public slots:
void reload();
void refresh(int holdtime);

View File

@@ -454,7 +454,8 @@ void SamplingBar::update_sample_rate_selector_value()
break;
}
}
update_scale();
if (samplerate != _sample_rate.itemData(_sample_rate.currentIndex()).value<uint64_t>())
update_scale();
_updating_sample_rate = false;
}
@@ -511,7 +512,7 @@ void SamplingBar::on_samplecount_sel(int index)
g_variant_new_uint64(sample_count));
sample_count_changed();
update_scale();
//update_scale();
}
}
@@ -535,7 +536,7 @@ void SamplingBar::on_samplerate_sel(int index)
SR_CONF_SAMPLERATE,
g_variant_new_uint64(sample_rate));
update_scale();
//update_scale();
}
}
@@ -625,9 +626,11 @@ void SamplingBar::update_sample_count_selector_value()
i).value<uint64_t>())
_sample_count.setCurrentIndex(i);
if (samplecount != _sample_count.itemData(_sample_count.currentIndex()).value<uint64_t>()) {
sample_count_changed();
update_scale();
}
_updating_sample_count = false;
sample_count_changed();
update_scale();
}
void SamplingBar::commit_sample_count()

View File

@@ -125,7 +125,6 @@ DecodeTrace::DecodeTrace(pv::SigSession &session,
_end_index(0),
_start_count(0),
_end_count(0),
_show_hide_mapper(this),
_popup_form(NULL),
_popup()
{
@@ -137,8 +136,6 @@ DecodeTrace::DecodeTrace(pv::SigSession &session,
this, SLOT(on_new_decode_data()));
connect(_decoder_stack.get(), SIGNAL(decode_done()),
this, SLOT(on_decode_done()));
connect(&_show_hide_mapper, SIGNAL(mapped(int)),
this, SLOT(on_show_hide_decoder(int)));
}
DecodeTrace::~DecodeTrace()
@@ -203,7 +200,7 @@ void DecodeTrace::paint_back(QPainter &p, int left, int right)
void DecodeTrace::paint_mid(QPainter &p, int left, int right)
{
using namespace pv::data::decode;
using namespace pv::data::decode;
const double scale = _view->scale();
assert(scale > 0);
@@ -249,47 +246,57 @@ void DecodeTrace::paint_mid(QPainter &p, int left, int right)
const double decode_startX = _decode_start/samples_per_pixel - (_view->offset() / _view->scale());
const double decode_endX = _decode_end/samples_per_pixel - (_view->offset() / _view->scale());
const std::vector< std::pair<Row, bool> > rows(_decoder_stack->get_visible_rows());
for (size_t i = 0; i < rows.size(); i++)
{
const Row &row = rows[i].first;
const bool shown = rows[i].second;
if (!shown && _decoder_stack->has_annotations(row)) {
draw_unshown_row(p, y, annotation_height, decode_startX, decode_endX);
y += annotation_height;
_cur_row_headings.push_back(row.title());
continue;
}
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (dec->shown()) {
const std::map<const pv::data::decode::Row, bool>& rows(_decoder_stack->get_rows_gshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if ((*i).first.decoder() == dec->decoder() &&
_decoder_stack->has_annotations((*i).first)) {
if ((*i).second) {
const Row &row = (*i).first;
size_t base_colour = 0x13579BDF;
boost::hash_combine(base_colour, this);
boost::hash_combine(base_colour, row.decoder());
boost::hash_combine(base_colour, row.row());
base_colour >>= 16;
size_t base_colour = 0x13579BDF;
boost::hash_combine(base_colour, this);
boost::hash_combine(base_colour, row.decoder());
boost::hash_combine(base_colour, row.row());
base_colour >>= 16;
const uint64_t min_annotation =
_decoder_stack->get_min_annotation(row);
const double min_annWidth = min_annotation / samples_per_pixel;
const uint64_t max_annotation =
_decoder_stack->get_max_annotation(row);
const double max_annWidth = max_annotation / samples_per_pixel;
if (max_annWidth > 5) {
vector<Annotation> annotations;
_decoder_stack->get_annotation_subset(annotations, row,
start_sample, end_sample);
if (!annotations.empty()) {
BOOST_FOREACH(const Annotation &a, annotations)
draw_annotation(a, p, get_text_colour(),
annotation_height, left, right,
samples_per_pixel, pixels_offset, y,
base_colour);
const uint64_t max_annotation =
_decoder_stack->get_max_annotation(row);
const double max_annWidth = max_annotation / samples_per_pixel;
if (max_annWidth > 5) {
vector<Annotation> annotations;
_decoder_stack->get_annotation_subset(annotations, row,
start_sample, end_sample);
if (!annotations.empty()) {
BOOST_FOREACH(const Annotation &a, annotations)
draw_annotation(a, p, get_text_colour(),
annotation_height, left, right,
samples_per_pixel, pixels_offset, y,
base_colour, min_annWidth);
}
} else if (max_annWidth != 0){
draw_nodetail(p, annotation_height, left, right, y, base_colour);
}
if (max_annWidth != 0) {
y += annotation_height;
_cur_row_headings.push_back(row.title());
}
}
}
}
} else if (max_annWidth != 0){
draw_nodetail(p, annotation_height, decode_startX, decode_endX, y, base_colour);
}
if (max_annWidth != 0) {
} else {
draw_unshown_row(p, y, annotation_height, left, right, tr("Unshown"));
y += annotation_height;
_cur_row_headings.push_back(row.title());
_cur_row_headings.push_back(dec->decoder()->name);
}
}
}
}
void DecodeTrace::paint_fore(QPainter &p, int left, int right)
@@ -350,8 +357,8 @@ bool DecodeTrace::create_popup()
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack())
{
if (dec->commit()) {
_decoder_stack->options_changed(true);
if (dec->commit() || _decoder_stack->options_changed()) {
_decoder_stack->set_options_changed(true);
_decode_start = dec->decode_start();
_decode_end = dec->decode_end();
ret = true;
@@ -378,6 +385,9 @@ void DecodeTrace::create_popup_form()
_popup_form = new QFormLayout(_popup);
_popup->setLayout(_popup_form);
populate_popup_form(_popup, _popup_form);
const int width = _popup_form->sizeHint().width();
const int height = _popup_form->sizeHint().height();
_popup->resize(width, height);
}
void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
@@ -395,20 +405,15 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
const list< boost::shared_ptr<Decoder> >& stack = _decoder_stack->stack();
if (stack.empty())
{
if (stack.empty()) {
QLabel *const l = new QLabel(
tr("<p><i>No decoders in the stack</i></p>"));
l->setAlignment(Qt::AlignCenter);
form->addRow(l);
}
else
{
list< boost::shared_ptr<Decoder> >::const_iterator iter =
stack.begin();
for (int i = 0; i < (int)stack.size(); i++, iter++) {
boost::shared_ptr<Decoder> dec(*iter);
create_decoder_form(i, dec, parent, form);
} else {
BOOST_FOREACH(boost::shared_ptr<Decoder> dec,stack) {
//boost::shared_ptr<Decoder> dec(*iter);
create_decoder_form(_decoder_stack, dec, parent, form);
}
form->addRow(new QLabel(
@@ -477,9 +482,9 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
}
void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
QPainter &p, QColor text_color, int h, int left, int right,
double samples_per_pixel, double pixels_offset, int y,
size_t base_colour) const
QPainter &p, QColor text_color, int h, int left, int right,
double samples_per_pixel, double pixels_offset, int y,
size_t base_colour, double min_annWidth) const
{
const double start = max(a.start_sample() / samples_per_pixel -
pixels_offset, (double)left);
@@ -495,7 +500,7 @@ void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
if (a.start_sample() == a.end_sample())
draw_instant(a, p, fill, outline, text_color, h,
start, y);
start, y, min_annWidth);
else
draw_range(a, p, fill, outline, text_color, h,
start, end, y);
@@ -506,22 +511,31 @@ void DecodeTrace::draw_nodetail(QPainter &p,
size_t base_colour) const
{
const QRectF nodetail_rect(left, y - h/2 + 0.5, right - left, h);
const size_t colour = base_colour % countof(Colours);
const QColor &fill = Colours[colour];
QString info = tr("Zoom in For Detial");
int info_left = nodetail_rect.center().x() - p.boundingRect(QRectF(), 0, info).width();
int info_right = nodetail_rect.center().x() + p.boundingRect(QRectF(), 0, info).width();
int height = p.boundingRect(QRectF(), 0, info).height();
p.setPen(Qt::white);
p.setBrush(fill);
p.drawRect(nodetail_rect);
p.drawText(nodetail_rect, Qt::AlignCenter | Qt::AlignVCenter, "Zoom in for more detials");
p.setPen(Trace::DARK_FORE);
p.drawLine(left, y, info_left, y);
p.drawLine(info_right, y, right, y);
p.drawLine(info_left, y, info_left+5, y - height/2 + 0.5);
p.drawLine(info_left, y, info_left+5, y + height/2 + 0.5);
p.drawLine(info_right, y, info_right-5, y - height/2 + 0.5);
p.drawLine(info_right, y, info_right-5, y + height/2 + 0.5);
p.setPen(Trace::DARK_FORE);
p.drawText(nodetail_rect, Qt::AlignCenter | Qt::AlignVCenter, info);
}
void DecodeTrace::draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
QColor fill, QColor outline, QColor text_color, int h, double x, int y) const
QColor fill, QColor outline, QColor text_color, int h, double x, int y, double min_annWidth) const
{
const QString text = a.annotations().empty() ?
QString() : a.annotations().back();
const double w = min((double)p.boundingRect(QRectF(), 0, text).width(),
0.0) + h;
// const double w = min((double)p.boundingRect(QRectF(), 0, text).width(),
// 0.0) + h;
const double w = min(min_annWidth, (double)h);
const QRectF rect(x - w / 2, y - h / 2, w, h);
p.setPen(outline);
@@ -564,7 +578,7 @@ void DecodeTrace::draw_range(const pv::data::decode::Annotation &a, QPainter &p,
QPointF(start + cap_width, bottom)
};
p.setPen(Qt::white);
p.setPen(DARK_BACK);
p.drawConvexPolygon(pts, countof(pts));
if (annotations.empty())
@@ -643,20 +657,8 @@ bool DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
return false;
const int y = get_y();
// const double start = max(samples_decoded /
// samples_per_pixel - pixels_offset, left - 1.0);
// const double end = min(sample_count / samples_per_pixel -
// pixels_offset, right + 1.0);
const QRectF no_decode_rect(left, y - h/2 + 0.5, right - left, h);
p.setPen(QPen(Qt::NoPen));
p.setBrush(Qt::white);
p.drawRect(no_decode_rect);
p.setPen(NoDecodeColour);
p.setBrush(QBrush(NoDecodeColour, Qt::Dense7Pattern));
p.drawRect(no_decode_rect);
const int progress100 = ceil(samples_decoded * 100.0 / need_sample_count);
p.setPen(dsLightBlue);
QFont font=p.font();
@@ -669,40 +671,40 @@ bool DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
}
void DecodeTrace::draw_unshown_row(QPainter &p, int y, int h, int left,
int right)
int right, QString info)
{
const QRectF unshown_rect(left, y - h/2 + 0.5, right - left, h);
int info_left = unshown_rect.center().x() - p.boundingRect(QRectF(), 0, info).width();
int info_right = unshown_rect.center().x() + p.boundingRect(QRectF(), 0, info).width();
int height = p.boundingRect(QRectF(), 0, info).height();
p.setPen(QPen(Qt::NoPen));
p.setBrush(QBrush(NoDecodeColour, Qt::Dense7Pattern));
p.drawRect(unshown_rect);
p.setPen(Trace::DARK_FORE);
p.drawLine(left, y, info_left, y);
p.drawLine(info_right, y, right, y);
p.drawLine(info_left, y, info_left+5, y - height/2 + 0.5);
p.drawLine(info_left, y, info_left+5, y + height/2 + 0.5);
p.drawLine(info_right, y, info_right-5, y - height/2 + 0.5);
p.drawLine(info_right, y, info_right-5, y + height/2 + 0.5);
p.setPen(dsLightBlue);
QFont font=p.font();
font.setPointSize(_view->get_signalHeight()*2/3);
font.setBold(true);
p.setFont(font);
p.drawText(unshown_rect, Qt::AlignCenter | Qt::AlignVCenter, "Unshown");
p.setPen(Trace::DARK_FORE);
p.drawText(unshown_rect, Qt::AlignCenter | Qt::AlignVCenter, info);
}
void DecodeTrace::create_decoder_form(int index,
void DecodeTrace::create_decoder_form(
boost::shared_ptr<pv::data::DecoderStack> &decoder_stack,
boost::shared_ptr<data::decode::Decoder> &dec, QWidget *parent,
QFormLayout *form)
QFormLayout *form)
{
const GSList *l;
assert(dec);
assert(dec);
const srd_decoder *const decoder = dec->decoder();
assert(decoder);
pv::widgets::DecoderGroupBox *const group =
new pv::widgets::DecoderGroupBox(
QString::fromUtf8(decoder->name));
group->set_decoder_visible(dec->shown());
_show_hide_mapper.setMapping(group, index);
connect(group, SIGNAL(show_hide_decoder()),
&_show_hide_mapper, SLOT(map()));
pv::widgets::DecoderGroupBox *const group =
new pv::widgets::DecoderGroupBox(decoder_stack, dec);
connect(group, SIGNAL(del_stack(boost::shared_ptr<data::decode::Decoder>&)),
this, SLOT(on_del_stack(boost::shared_ptr<data::decode::Decoder>&)));
QFormLayout *const decoder_form = new QFormLayout;
group->add_layout(decoder_form);
@@ -739,7 +741,7 @@ void DecodeTrace::create_decoder_form(int index,
// Add the options
boost::shared_ptr<prop::binding::DecoderOptions> binding(
new prop::binding::DecoderOptions(_decoder_stack, dec));
new prop::binding::DecoderOptions(decoder_stack, dec));
binding->add_properties_to_form(decoder_form, true);
_bindings.push_back(binding);
@@ -837,6 +839,7 @@ void DecodeTrace::on_decode_done()
_view->set_need_update(true);
_view->signals_changed();
}
_session.decode_done();
}
void DecodeTrace::on_delete()
@@ -860,33 +863,36 @@ void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
create_popup_form();
}
void DecodeTrace::on_show_hide_decoder(int index)
void DecodeTrace::on_del_stack(boost::shared_ptr<data::decode::Decoder> &dec)
{
using pv::data::decode::Decoder;
assert(dec);
assert(_decoder_stack);
_decoder_stack->remove(dec);
const list< boost::shared_ptr<Decoder> > stack(_decoder_stack->stack());
// Find the decoder in the stack
list< boost::shared_ptr<Decoder> >::const_iterator iter = stack.begin();
for(int i = 0; i < index; i++, iter++)
assert(iter != stack.end());
boost::shared_ptr<Decoder> dec = *iter;
assert(dec);
const bool show = !dec->shown();
dec->show(show);
assert(index < (int)_decoder_forms.size());
_decoder_forms[index]->set_decoder_visible(show);
//_view->set_need_update(true);
create_popup_form();
}
int DecodeTrace::rows_size()
{
return _decoder_stack->cur_rows_size();
using pv::data::decode::Decoder;
int size = 0;
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (dec->shown()) {
const std::map<const pv::data::decode::Row, bool>& rows(_decoder_stack->get_rows_gshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if ((*i).first.decoder() == dec->decoder() &&
_decoder_stack->has_annotations((*i).first) &&
(*i).second)
size++;
}
} else {
size++;
}
}
return size == 0 ? 1 : size;
}
void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
@@ -897,9 +903,8 @@ void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF group_index_rect = get_rect(CHNLREG, y, right);
QString index_string;
int last_index;
p.setPen(Qt::transparent);
p.setBrush(dsBlue);
p.drawRect(group_index_rect);
p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
p.drawLine(group_index_rect.bottomLeft(), group_index_rect.bottomRight());
std::list<int>::iterator i = _index_list.begin();
last_index = (*i);
index_string = QString::number(last_index);
@@ -912,7 +917,7 @@ void DecodeTrace::paint_type_options(QPainter &p, int right, const QPoint pt)
index_string = QString::number((*i)) + "," + index_string;
last_index = (*i);
}
p.setPen(Qt::white);
p.setPen(DARK_FORE);
p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string);
}
@@ -986,5 +991,6 @@ void DecodeTrace::frame_ended()
}
}
} // namespace view
} // namespace pv

View File

@@ -152,14 +152,14 @@ private:
void draw_annotation(const pv::data::decode::Annotation &a, QPainter &p,
QColor text_colour, int text_height, int left, int right,
double samples_per_pixel, double pixels_offset, int y,
size_t base_colour) const;
size_t base_colour, double min_annWidth) const;
void draw_nodetail(QPainter &p,
int text_height, int left, int right, int y,
size_t base_colour) const;
void draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
QColor fill, QColor outline, QColor text_color, int h, double x,
int y) const;
int y, double min_annWidth) const;
void draw_range(const pv::data::decode::Annotation &a, QPainter &p,
QColor fill, QColor outline, QColor text_color, int h, double start,
@@ -172,11 +172,11 @@ private:
int right);
void draw_unshown_row(QPainter &p, int y, int h, int left,
int right);
int right, QString info);
void create_decoder_form(int index,
boost::shared_ptr<pv::data::decode::Decoder> &dec,
QWidget *parent, QFormLayout *form);
void create_decoder_form(boost::shared_ptr<data::DecoderStack> &decoder_stack,
boost::shared_ptr<pv::data::decode::Decoder> &dec,
QWidget *parent, QFormLayout *form);
QComboBox* create_probe_selector(QWidget *parent,
const boost::shared_ptr<pv::data::decode::Decoder> &dec,
@@ -195,8 +195,7 @@ private slots:
void on_probe_selected(int);
void on_stack_decoder(srd_decoder *decoder);
void on_show_hide_decoder(int index);
void on_del_stack(boost::shared_ptr<data::decode::Decoder> &dec);
void on_decode_done();
@@ -219,7 +218,6 @@ private:
std::vector<QString> _cur_row_headings;
QSignalMapper _show_hide_mapper;
QFormLayout *_popup_form;
QDialog *_popup;
};

View File

@@ -44,45 +44,50 @@ using namespace std;
namespace pv {
namespace view {
DevMode::DevMode(View &parent) :
QWidget(&parent),
_view(parent),
layout(new QGridLayout(this))
DevMode::DevMode(QWidget *parent, SigSession &session) :
QWidget(parent),
_session(session),
_layout(new QGridLayout(this))
{
setLayout(layout);
setLayout(_layout);
}
void DevMode::set_device()
{
int index = 0;
const boost::shared_ptr<device::DevInst> dev_inst = _view.session().get_device();
const boost::shared_ptr<device::DevInst> dev_inst = _session.get_device();
assert(dev_inst);
for(std::map<QPushButton *, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
i != _mode_button_list.end(); i++) {
(*i).first->setParent(NULL);
_layout->removeWidget((*i).first);
delete (*i).first;
}
_mode_button_list.clear();
delete layout;
layout = new QGridLayout(this);
for (GSList *l = dev_inst->get_dev_mode_list();
l; l = l->next) {
sr_dev_mode *mode = (sr_dev_mode *)l->data;
boost::shared_ptr<QPushButton> mode_button = boost::shared_ptr<QPushButton>(new QPushButton(NULL));
mode_button->setFlat(true);
QPushButton *mode_button = new QPushButton(this);
//mode_button->setFlat(true);
mode_button->setText(mode->name);
mode_button->setCheckable(true);
_mode_button_list[mode_button] = mode;
if (dev_inst->dev_inst()->mode == _mode_button_list[mode_button]->mode)
mode_button->setChecked(true);
connect(mode_button.get(), SIGNAL(clicked()), this, SLOT(on_mode_change()));
connect(mode_button, SIGNAL(clicked()), this, SLOT(on_mode_change()));
layout->addWidget(mode_button.get(), index / GRID_COLS, index % GRID_COLS);
layout->addWidget(new QWidget(), index / GRID_COLS, GRID_COLS);
layout->setColumnStretch(GRID_COLS, 1);
_layout->addWidget(mode_button, index / GRID_COLS, index % GRID_COLS);
//layout->addWidget(new QWidget(), index / GRID_COLS, GRID_COLS);
_layout->setColumnStretch(GRID_COLS, 1);
index++;
}
setLayout(layout);
}
update();
}
@@ -94,40 +99,27 @@ void DevMode::paintEvent(QPaintEvent*)
o.initFrom(this);
QPainter painter(this);
style()->drawPrimitive(QStyle::PE_Widget, &o, &painter, this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
for(std::map<boost::shared_ptr<QPushButton>, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
i != _mode_button_list.end(); i++) {
const boost::shared_ptr<device::DevInst> dev_inst = _view.session().get_device();
assert(dev_inst);
if (dev_inst->dev_inst()->mode == (*i).second->mode)
painter.setBrush(Trace::dsBlue);
else
painter.setBrush(Trace::dsGray);
painter.drawRoundedRect((*i).first->geometry(), 4, 4);
}
painter.end();
}
void DevMode::on_mode_change()
{
const boost::shared_ptr<device::DevInst> dev_inst = _view.session().get_device();
const boost::shared_ptr<device::DevInst> dev_inst = _session.get_device();
assert(dev_inst);
QPushButton *button = qobject_cast<QPushButton *>(sender());
for(std::map<boost::shared_ptr<QPushButton>, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
for(std::map<QPushButton *, sr_dev_mode *>::const_iterator i = _mode_button_list.begin();
i != _mode_button_list.end(); i++) {
if ((*i).first.get() == button) {
if ((*i).first == button) {
if (dev_inst->dev_inst()->mode != (*i).second->mode) {
_view.session().stop_capture();
_session.stop_capture();
dev_inst->set_config(NULL, NULL,
SR_CONF_DEVICE_MODE,
g_variant_new_int16((*i).second->mode));
button->setChecked(true);
mode_changed();
}
} else {
(*i).first->setChecked(false);
}
}
}

View File

@@ -44,9 +44,9 @@ namespace device{
class DevInst;
}
namespace view {
class SigSession;
class View;
namespace view {
class DevMode : public QWidget
{
@@ -56,7 +56,7 @@ private:
static const int GRID_COLS = 3;
public:
DevMode(View &parent);
DevMode(QWidget *parent, SigSession &session);
private:
void paintEvent(QPaintEvent *event);
@@ -77,10 +77,10 @@ signals:
void mode_changed();
private:
View &_view;
SigSession &_session;
QGridLayout * layout;
std::map <boost::shared_ptr<QPushButton>, sr_dev_mode *> _mode_button_list;
QGridLayout * _layout;
std::map <QPushButton *, sr_dev_mode *> _mode_button_list;
QPoint _mouse_point;
};

View File

@@ -204,9 +204,8 @@ void GroupSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF group_index_rect = get_rect(CHNLREG, y, right);
QString index_string;
int last_index;
p.setPen(Qt::transparent);
p.setBrush(dsBlue);
p.drawRect(group_index_rect);
p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
p.drawLine(group_index_rect.bottomLeft(), group_index_rect.bottomRight());
std::list<int>::iterator i = _index_list.begin();
last_index = (*i);
index_string = QString::number(last_index);
@@ -219,7 +218,7 @@ void GroupSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
index_string = QString::number((*i)) + "," + index_string;
last_index = (*i);
}
p.setPen(Qt::white);
p.setPen(DARK_FORE);
p.drawText(group_index_rect, Qt::AlignRight | Qt::AlignVCenter, index_string);
}

View File

@@ -115,15 +115,13 @@ void Header::paintEvent(QPaintEvent*)
QStyleOption o;
o.initFrom(this);
QPainter painter(this);
//painter.setRenderHint(QPainter::Antialiasing);
style()->drawPrimitive(QStyle::PE_Widget, &o, &painter, this);
const int w = width();
const vector< boost::shared_ptr<Trace> > traces(
_view.get_traces());
//QPainter painter(this);
//painter.setRenderHint(QPainter::Antialiasing);
const bool dragging = !_drag_traces.empty();
BOOST_FOREACH(const boost::shared_ptr<Trace> t, traces)
{

View File

@@ -44,24 +44,7 @@ const QColor LogicSignal::EdgeColour(0x80, 0x80, 0x80);
const QColor LogicSignal::HighColour(0x00, 0xC0, 0x00);
const QColor LogicSignal::LowColour(0xC0, 0x00, 0x00);
const QColor LogicSignal::SignalColours[8] = {
QColor(0x16, 0x19, 0x1A), // Black
QColor(0x8F, 0x52, 0x02), // Brown
QColor(0xCC, 0x00, 0x00), // Red
QColor(0xF5, 0x79, 0x00), // Orange
QColor(0xED, 0xD4, 0x00), // Yellow
QColor(0x73, 0xD2, 0x16), // Green
QColor(0x34, 0x65, 0xA4), // Blue
QColor(0x75, 0x50, 0x7B), // Violet
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
};
const QColor LogicSignal::DEFAULT_COLOR = QColor(150, 150, 150, 255);
const int LogicSignal::StateHeight = 12;
const int LogicSignal::StateRound = 5;
@@ -73,7 +56,8 @@ LogicSignal::LogicSignal(boost::shared_ptr<pv::device::DevInst> dev_inst,
_data(data),
_trig(NONTRIG)
{
_colour = SignalColours[probe->index % countof(SignalColours)];
//_colour = PROBE_COLORS[probe->index % countof(PROBE_COLORS)];
_colour = DEFAULT_COLOR;
}
LogicSignal::LogicSignal(boost::shared_ptr<view::LogicSignal> s,
@@ -249,35 +233,37 @@ void LogicSignal::paint_type_options(QPainter &p, int right, const QPoint pt)
const QRectF lowTrig_rect = get_rect(LOWTRIG, y, right);
const QRectF edgeTrig_rect = get_rect(EDGTRIG, y, right);
p.setPen(Qt::transparent);
p.setBrush(posTrig_rect.contains(pt) ? dsYellow.darker() :
(_trig == POSTRIG) ? dsYellow : dsBlue);
p.setPen(Qt::NoPen);
p.setBrush(posTrig_rect.contains(pt) ? dsBlue.lighter() :
(_trig == POSTRIG) ? dsBlue : DARK_BACK);
p.drawRect(posTrig_rect);
p.setBrush(higTrig_rect.contains(pt) ? dsYellow.darker() :
(_trig == HIGTRIG) ? dsYellow : dsBlue);
p.setBrush(higTrig_rect.contains(pt) ? dsBlue.lighter() :
(_trig == HIGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(higTrig_rect);
p.setBrush(negTrig_rect.contains(pt) ? dsYellow.darker() :
(_trig == NEGTRIG) ? dsYellow : dsBlue);
p.setBrush(negTrig_rect.contains(pt) ? dsBlue.lighter() :
(_trig == NEGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(negTrig_rect);
p.setBrush(lowTrig_rect.contains(pt) ? dsYellow.darker() :
(_trig == LOWTRIG) ? dsYellow : dsBlue);
p.setBrush(lowTrig_rect.contains(pt) ? dsBlue.lighter() :
(_trig == LOWTRIG) ? dsBlue : DARK_BACK);
p.drawRect(lowTrig_rect);
p.setBrush(edgeTrig_rect.contains(pt) ? dsYellow.darker() :
(_trig == EDGTRIG) ? dsYellow : dsBlue);
p.setBrush(edgeTrig_rect.contains(pt) ? dsBlue.lighter() :
(_trig == EDGTRIG) ? dsBlue : DARK_BACK);
p.drawRect(edgeTrig_rect);
p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
p.setPen(QPen(DARK_FORE, 1, Qt::DashLine));
p.setBrush(Qt::transparent);
p.drawLine(posTrig_rect.right(), posTrig_rect.top() + 3,
posTrig_rect.right(), posTrig_rect.bottom() - 3);
p.drawLine(higTrig_rect.right(), higTrig_rect.top() + 3,
higTrig_rect.right(), higTrig_rect.bottom() - 3);
p.drawLine(negTrig_rect.right(), negTrig_rect.top() + 3,
negTrig_rect.right(), negTrig_rect.bottom() - 3);
p.drawLine(lowTrig_rect.right(), lowTrig_rect.top() + 3,
lowTrig_rect.right(), lowTrig_rect.bottom() - 3);
// p.drawLine(posTrig_rect.right(), posTrig_rect.top(),
// posTrig_rect.right(), posTrig_rect.bottom());
// p.drawLine(higTrig_rect.right(), higTrig_rect.top(),
// higTrig_rect.right(), higTrig_rect.bottom());
// p.drawLine(negTrig_rect.right(), negTrig_rect.top(),
// negTrig_rect.right(), negTrig_rect.bottom());
// p.drawLine(lowTrig_rect.right(), lowTrig_rect.top(),
// lowTrig_rect.right(), lowTrig_rect.bottom());
p.drawLine(posTrig_rect.left(), posTrig_rect.bottom(),
edgeTrig_rect.right(), edgeTrig_rect.bottom());
p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
p.setPen(QPen(DARK_FORE, 2, Qt::SolidLine));
p.setBrush(Qt::transparent);
p.drawLine(posTrig_rect.left() + 5, posTrig_rect.bottom() - 5,
posTrig_rect.center().x(), posTrig_rect.bottom() - 5);

View File

@@ -48,7 +48,7 @@ private:
static const QColor HighColour;
static const QColor LowColour;
static const QColor SignalColours[8];
static const QColor DEFAULT_COLOR;
static const int StateHeight;
static const int StateRound;

View File

@@ -77,6 +77,7 @@ const QColor Ruler::dsBlue = QColor(17, 133, 209, 255);
const QColor Ruler::dsYellow = QColor(238, 178, 17, 255);
const QColor Ruler::dsRed = QColor(213, 15, 37, 255);
const QColor Ruler::dsGreen = QColor(0, 153, 37, 255);
const QColor Ruler::RULER_COLOR = QColor(255, 255, 255, 255);
const QColor Ruler::HitColor = dsYellow;
const QColor Ruler::WarnColor = dsRed;
@@ -458,7 +459,7 @@ void Ruler::draw_logic_tick_mark(QPainter &p)
AlignLeft | AlignTop, "8").height();
// Draw the tick marks
p.setPen(dsBlue);
p.setPen(Trace::DARK_FORE);
const double minor_tick_period = tick_period / MinPeriodScale;
const int minor_order = (int)floorf(log10f(minor_tick_period));
@@ -548,7 +549,7 @@ void Ruler::draw_hover_mark(QPainter &p)
return;
p.setPen(QPen(Qt::NoPen));
p.setBrush(dsBlue);
p.setBrush(RULER_COLOR);
const int b = height() - 1;
const QPointF points[] = {

View File

@@ -54,6 +54,7 @@ private:
static const QColor dsYellow;
static const QColor dsRed;
static const QColor dsGreen;
static const QColor RULER_COLOR;
public:
static const QColor CursorColor[8];

View File

@@ -50,6 +50,29 @@ const QColor Trace::dsLightBlue = QColor(17, 133, 209, 150);
const QColor Trace::dsLightRed = QColor(213, 15, 37, 150);
const QPen Trace::SignalAxisPen = QColor(128, 128, 128, 64);
const QColor Trace::DARK_BACK = QColor(48, 47, 47, 255);
const QColor Trace::DARK_FORE = QColor(150, 150, 150, 255);
const QColor Trace::DARK_HIGHLIGHT = QColor(32, 32, 32, 255);
const QColor Trace::PROBE_COLORS[8] = {
QColor(0x50, 0x50, 0x50), // Black
QColor(0x8F, 0x52, 0x02), // Brown
QColor(0xCC, 0x00, 0x00), // Red
QColor(0xF5, 0x79, 0x00), // Orange
QColor(0xED, 0xD4, 0x00), // Yellow
QColor(0x73, 0xD2, 0x16), // Green
QColor(0x34, 0x65, 0xA4), // Blue
QColor(0x75, 0x50, 0x7B), // Violet
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
// QColor(17, 133, 209),
};
const QPen Trace::AxisPen(QColor(128, 128, 128, 64));
const int Trace::LabelHitPadding = 2;
@@ -220,14 +243,14 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
const QRectF name_rect = get_rect("name", y, right);
const QRectF label_rect = get_rect("label", get_zeroPos(), right);
p.setRenderHint(QPainter::Antialiasing);
//p.setRenderHint(QPainter::Antialiasing);
// Paint the ColorButton
p.setPen(Qt::transparent);
p.setBrush(enabled() ? _colour : dsDisable);
p.drawRect(color_rect);
// Paint the signal name
p.setPen(enabled() ? Qt::black : dsDisable);
p.setPen(enabled() ? DARK_FORE: dsDisable);
p.drawText(name_rect, Qt::AlignLeft | Qt::AlignVCenter, _name);
// Paint the trigButton
@@ -244,16 +267,14 @@ void Trace::paint_label(QPainter &p, int right, const QPoint pt)
};
p.setPen(Qt::transparent);
if (_type == SR_CHANNEL_DSO)
if (_type == SR_CHANNEL_DSO) {
p.setBrush((label_rect.contains(pt) || selected()) ? _colour.darker() : _colour);
else
p.setBrush((label_rect.contains(pt) || selected()) ? dsYellow : dsBlue);
p.drawPolygon(points, countof(points));
p.setPen(QPen(Qt::blue, 1, Qt::DotLine));
p.setBrush(Qt::transparent);
p.drawLine(label_rect.right(), label_rect.top() + 3,
label_rect.right(), label_rect.bottom() - 3);
p.drawPolygon(points, countof(points));
} else {
QColor color = PROBE_COLORS[*_index_list.begin() % countof(PROBE_COLORS)];
p.setBrush((label_rect.contains(pt) || selected()) ? color.lighter() : color);
p.drawPolygon(points, countof(points));
}
// Paint the text
p.setPen(Qt::white);
@@ -326,30 +347,6 @@ void Trace::compute_text_size(QPainter &p)
p.boundingRect(QRectF(), 0, "99").height());
}
QRectF Trace::get_rect(const char *s, int y, int right)
{
const QSizeF color_size(SquareWidth, SquareWidth);
const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth);
//const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
const QSizeF label_size(SquareWidth, SquareWidth);
if (!strcmp(s, "name"))
return QRectF(
get_leftWidth(),
y - name_size.height() / 2,
name_size.width(), name_size.height());
else if (!strcmp(s, "label"))
return QRectF(
right - 1.5f * label_size.width(),
y - SquareWidth / 2,
label_size.width(), label_size.height());
else
return QRectF(
2,
y - SquareWidth / 2,
SquareWidth, SquareWidth);
}
QRectF Trace::get_view_rect() const
{
assert(_view);
@@ -385,7 +382,7 @@ int Trace::rows_size()
int Trace::get_leftWidth() const
{
return SquareWidth + Margin;
return SquareWidth/2 + Margin;
}
int Trace::get_rightWidth() const
@@ -398,5 +395,34 @@ int Trace::get_headerHeight() const
return SquareWidth;
}
QRectF Trace::get_rect(const char *s, int y, int right) const
{
const QSizeF color_size(get_leftWidth() - Margin, SquareWidth);
const QSizeF name_size(right - get_leftWidth() - get_rightWidth(), SquareWidth);
//const QSizeF label_size(_text_size.width() + Margin, SquareWidth);
const QSizeF label_size(SquareWidth, SquareWidth);
if (!strcmp(s, "name"))
return QRectF(
get_leftWidth(),
y - name_size.height() / 2,
name_size.width(), name_size.height());
else if (!strcmp(s, "label"))
return QRectF(
right - 1.5f * label_size.width(),
y - label_size.height() / 2,
label_size.width(), label_size.height());
else if (!strcmp(s, "color"))
return QRectF(
2,
y - color_size.height() / 2,
color_size.width(), color_size.height());
else
return QRectF(
2,
y - SquareWidth / 2,
SquareWidth, SquareWidth);
}
} // namespace view
} // namespace pv

View File

@@ -70,6 +70,12 @@ public:
static const QColor dsLightRed;
static const QPen SignalAxisPen;
static const QColor DARK_BACK;
static const QColor DARK_FORE;
static const QColor DARK_HIGHLIGHT;
static const QColor PROBE_COLORS[8];
protected:
Trace(QString name, uint16_t index, int type);
Trace(QString name, std::list<int> index_list, int type, int sec_index);
@@ -225,7 +231,7 @@ public:
* area.
* @return Returns the rectangle of the signal label.
*/
QRectF get_rect(const char *s, int y, int right);
QRectF get_rect(const char *s, int y, int right) const;
virtual int rows_size();

View File

@@ -74,7 +74,7 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
_viewport(new Viewport(*this)),
_ruler(new Ruler(*this)),
_header(new Header(*this)),
_devmode(new DevMode(*this)),
_devmode(new DevMode(this, session)),
_scale(1e-8),
_preScale(1e-6),
_maxscale(1e9),
@@ -98,15 +98,17 @@ View::View(SigSession &session, pv::toolbars::SamplingBar *sampling_bar, QWidget
setViewportMargins(headerWidth(), RulerHeight, 0, 0);
setViewport(_viewport);
connect(&_session, SIGNAL(device_setted()),
_devmode, SLOT(set_device()));
connect(&_session, SIGNAL(signals_changed()),
this, SLOT(signals_changed()));
connect(&_session, SIGNAL(data_updated()),
this, SLOT(data_updated()));
connect(&_session, SIGNAL(receive_trigger(quint64)),
this, SLOT(set_trig_pos(quint64)));
connect(&_session, SIGNAL(show_region(uint64_t,uint64_t)),
this, SLOT(show_region(uint64_t, uint64_t)));
connect(&_session, SIGNAL(device_setted()),
_devmode, SLOT(set_device()));
connect(_devmode, SIGNAL(mode_changed()),
this, SIGNAL(mode_changed()));
@@ -464,9 +466,9 @@ void View::update_scale()
}
_minscale = (1.0 / sample_rate) / MaxPixelsPerSample;
_offset = 0;
//_offset = 0;
_preScale = _scale;
_preOffset = _offset;
//_preOffset = _offset;
_trig_cursor->set_index(_trig_pos);
@@ -514,6 +516,7 @@ void View::signals_changed()
_viewport->clear_measure();
header_updated();
normalize_layout();
data_updated();
}
bool View::eventFilter(QObject *object, QEvent *event)
@@ -834,5 +837,14 @@ QString View::trigger_time()
return _trigger_time.toString("yyyy-MM-dd hh:mm:ss ddd");
}
void View::show_region(uint64_t start, uint64_t end)
{
assert(start <= end);
const double ideal_scale = (end-start) * 2.0 / _session.get_device()->get_sample_rate() / get_view_width();
const double new_scale = max(min(ideal_scale, _maxscale), _minscale);
const double new_off = (start + end) * 0.5 / _session.get_device()->get_sample_rate() - new_scale * get_view_width() / 2;
set_scale_offset(new_scale, new_off);
}
} // namespace view
} // namespace pv

View File

@@ -221,6 +221,7 @@ public slots:
void signals_changed();
void data_updated();
void update_scale();
void show_region(uint64_t start, uint64_t end);
private slots:

View File

@@ -445,11 +445,11 @@ void Viewport::mouseMoveEvent(QMouseEvent *event)
if (_action_type == DSO_YM)
_dso_ym_end = event->pos().y();
measure();
}
_mouse_point = event->pos();
measure();
update();
}
@@ -719,7 +719,6 @@ void Viewport::leaveEvent(QEvent *)
_mm_period = "#####";
_mm_freq = "#####";
_mm_duty = "#####";
measure_updated();
} else if (_action_type == DSO_YM) {
_dso_ym_valid = false;
}
@@ -727,6 +726,7 @@ void Viewport::leaveEvent(QEvent *)
if (_action_type != NO_ACTION)
_action_type = NO_ACTION;
measure();
update();
}
@@ -767,7 +767,7 @@ void Viewport::measure()
boost::shared_ptr<view::DsoSignal> dsoSig;
if (logicSig = dynamic_pointer_cast<view::LogicSignal>(s)) {
if (_action_type == NO_ACTION) {
if (logicSig->measure(_view.hover_point(), _cur_sample, _nxt_sample, _thd_sample)) {
if (logicSig->measure(_mouse_point, _cur_sample, _nxt_sample, _thd_sample)) {
_measure_type = LOGIC_FREQ;
_mm_width = _view.get_ruler()->format_real_time(_nxt_sample - _cur_sample, sample_rate);
@@ -1173,7 +1173,7 @@ void Viewport::on_drag_timer()
void Viewport::paintTrigTime(QPainter &p)
{
if (_view.session().get_device()->dev_inst()->mode == LOGIC) {
p.setPen(Trace::dsBack);
p.setPen(Trace::DARK_FORE);
p.drawText(this->rect(), Qt::AlignRight | Qt::AlignBottom,
"Last Trigger Time: "+_view.trigger_time());
}

View File

@@ -17,52 +17,134 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
extern "C" {
#include <libsigrokdecode/libsigrokdecode.h>
}
#include "decodergroupbox.h"
#include "../data/decoderstack.h"
#include "../data/decode/decoder.h"
#include "../data/decode/row.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QVariant>
#include <boost/foreach.hpp>
#include <assert.h>
namespace pv {
namespace widgets {
DecoderGroupBox::DecoderGroupBox(QString title, QWidget *parent) :
QWidget(parent),
_layout(new QGridLayout),
_show_hide_button(QIcon(":/icons/shown.png"), QString(), this)
DecoderGroupBox::DecoderGroupBox(boost::shared_ptr<data::DecoderStack> &decoder_stack,
boost::shared_ptr<data::decode::Decoder> &dec,
QWidget *parent) :
QWidget(parent),
_decoder_stack(decoder_stack),
_dec(dec),
_layout(new QGridLayout)
{
_layout->setContentsMargins(0, 0, 0, 0);
setLayout(_layout);
setLayout(_layout);
_layout->addWidget(new QLabel(QString("<h3>%1</h3>").arg(title)),
_layout->addWidget(new QLabel(QString("<h3>%1</h3>").arg(_dec->decoder()->name)),
0, 0);
_layout->setColumnStretch(0, 1);
QHBoxLayout *const toolbar = new QHBoxLayout;
_layout->addLayout(toolbar, 0, 1);
const srd_decoder *const d = _dec->decoder();
assert(d);
const bool have_probes = (d->channels || d->opt_channels) != 0;
if (!have_probes) {
_del_button = new QPushButton(QIcon(":/icons/del.png"), QString(), this);
_layout->addWidget(_del_button, 0, 1);
connect(_del_button, SIGNAL(clicked()), this, SLOT(on_del_stack()));
}
_show_hide_button.setFlat(true);
//_show_hide_button.setIconSize(QSize(16, 16));
connect(&_show_hide_button, SIGNAL(clicked()),
this, SIGNAL(show_hide_decoder()));
toolbar->addWidget(&_show_hide_button);
_index = 0;
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (dec == _dec)
break;
_index++;
}
_show_button = new QPushButton(QIcon(_dec->shown() ?
":/icons/shown.png" :
":/icons/hidden.png"), QString(), this);
_show_button->setProperty("index", -1);
connect(_show_button, SIGNAL(clicked()),
this, SLOT(tog_icon()));
_layout->addWidget(_show_button, 0, 2);
// add row show/hide
int index = 0;
const std::map<const pv::data::decode::Row, bool>& rows(_decoder_stack->get_rows_gshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if ((*i).first.decoder() == _dec->decoder()) {
QPushButton *show_button = new QPushButton(QIcon((*i).second ?
":/icons/shown.png" :
":/icons/hidden.png"), QString(), this);
show_button->setProperty("index", index);
connect(show_button, SIGNAL(clicked()), this, SLOT(tog_icon()));
_row_show_button.push_back(show_button);
_layout->addWidget(new QLabel((*i).first.title(), this), _row_show_button.size(), 0);
_layout->addWidget(show_button, _row_show_button.size(), 2);
}
index++;
}
}
void DecoderGroupBox::add_layout(QLayout *layout)
{
assert(layout);
_layout->addLayout(layout, 1, 0, 1, 2);
_layout->addLayout(layout, _row_show_button.size()+1, 0, 1, 3);
}
void DecoderGroupBox::set_decoder_visible(bool visible)
void DecoderGroupBox::tog_icon()
{
_show_hide_button.setIcon(QIcon(visible ?
":/icons/shown.png" :
":/icons/hidden.png"));
QPushButton *sc = dynamic_cast<QPushButton*>(sender());
QVariant id = sc->property("index");
int index = id.toInt();
if (index == -1) {
int i = _index;
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (i-- == 0) {
dec->show(!dec->shown());
sc->setIcon(QIcon(dec->shown() ? ":/icons/shown.png" :
":/icons/hidden.png"));
break;
}
}
} else {
std::map<const pv::data::decode::Row, bool>& rows(_decoder_stack->get_rows_gshow());
for (std::map<const pv::data::decode::Row, bool>::const_iterator i = rows.begin();
i != rows.end(); i++) {
if (index-- == 0) {
_decoder_stack->set_rows_gshow((*i).first, !(*i).second);
//rows[(*i).first] = !(*i).second;
sc->setIcon(QIcon(rows[(*i).first] ? ":/icons/shown.png" :
":/icons/hidden.png"));
break;
}
}
}
}
void DecoderGroupBox::on_del_stack()
{
int i = _index;
BOOST_FOREACH(boost::shared_ptr<data::decode::Decoder> dec,
_decoder_stack->stack()) {
if (i-- == 0) {
del_stack(dec);
break;
}
}
}
} // widgets

View File

@@ -22,11 +22,19 @@
#define DSVIEW_PV_WIDGETS_DECODERGROUPBOX_H
#include <QPushButton>
class QGridLayout;
class QToolBar;
#include <QGridLayout>
#include <QToolBar>
#include <boost/shared_ptr.hpp>
namespace pv {
namespace data{
class DecoderStack;
namespace decode{
class Decoder;
}
}
namespace widgets {
class DecoderGroupBox : public QWidget
@@ -34,18 +42,30 @@ class DecoderGroupBox : public QWidget
Q_OBJECT
public:
DecoderGroupBox(QString title, QWidget *parent = NULL);
DecoderGroupBox(boost::shared_ptr<pv::data::DecoderStack> &decoder_stack,
boost::shared_ptr<data::decode::Decoder> &dec,
QWidget *parent = NULL);
void add_layout(QLayout *layout);
void set_decoder_visible(bool visible);
signals:
void show_hide_decoder();
void show_hide_row();
void del_stack(boost::shared_ptr<data::decode::Decoder> &_dec);
private slots:
void tog_icon();
void on_del_stack();
private:
QGridLayout *const _layout;
QPushButton _show_hide_button;
boost::shared_ptr<pv::data::DecoderStack> &_decoder_stack;
boost::shared_ptr<data::decode::Decoder> &_dec;
int _index;
QGridLayout *const _layout;
QPushButton *_del_button;
QPushButton *_show_button;
std::list <QPushButton *> _row_show_button;
};
} // widgets

View File

@@ -261,4 +261,24 @@ QSlider::add-page:horizontal{
border-radius: 4px;
}
/* <<< QTableView */
QHeaderView::section {
background-color: #646464;
padding: 4px;
font-size: 14pt;
border-style: none;
border-bottom: 1px solid #fffff8;
border-right: 1px solid #fffff8;
}
QHeaderView::section:horizontal
{
border-top: 1px solid #fffff8;
}
QHeaderView::section:vertical
{
border-left: 1px solid #fffff8;
}
/* <<< QDockWidget */