feat: добавить скрипт CI/CD
commit
8b1eb2e880
|
@ -0,0 +1,13 @@
|
|||
name: Build Example
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: stateoftheartio/qt6:6.6-mingw-aqt
|
||||
name: Build
|
||||
steps:
|
||||
- name: Build core
|
||||
run: qmake
|
|
@ -0,0 +1,11 @@
|
|||
build-*/
|
||||
.output/
|
||||
*.user
|
||||
*debug/
|
||||
*release/
|
||||
*DSPFilters/
|
||||
*.qtc_clangd/
|
||||
*Makefile*
|
||||
*.qmake.stash
|
||||
*.gtl
|
||||
log_*
|
|
@ -0,0 +1,73 @@
|
|||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
QT -= gui
|
||||
QT += xml qml
|
||||
|
||||
TEMPLATE = lib
|
||||
DEFINES += CORE_LIBRARY
|
||||
TARGET = gtl_core
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
gtl_analog_data.cpp \
|
||||
gtl_core.cpp \
|
||||
gtl_data_model.cpp \
|
||||
gtl_data_model_node.cpp \
|
||||
gtl_device.cpp \
|
||||
gtl_selection_data_model.cpp \
|
||||
gtl_logger.cpp
|
||||
|
||||
HEADERS += \
|
||||
core_global.h \
|
||||
gtl.h \
|
||||
gtl_analog_data.h \
|
||||
gtl_core.h \
|
||||
gtl_data_model.h \
|
||||
gtl_data_model_node.h \
|
||||
gtl_device.h \
|
||||
gtl_selection_data_model.h \
|
||||
gtl_logger.h
|
||||
|
||||
# Default rules for deployment.
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
}
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
win32:CONFIG(release, debug|release): DESTDIR = ../.output/release
|
||||
else:win32:CONFIG(debug, debug|release): DESTDIR = ../.output/debug
|
||||
else:unix: DESTDIR = ../../.ouput
|
||||
|
||||
INCLUDEPATH += $$PWD/..
|
||||
DEPENDPATH += $$PWD/..
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef CORE_GLOBAL_H
|
||||
#define CORE_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(CORE_LIBRARY)
|
||||
# define CORE_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define CORE_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // CORE_GLOBAL_H
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef GTL_H
|
||||
#define GTL_H
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
enum units
|
||||
{
|
||||
unit,
|
||||
db
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GTL_H
|
|
@ -0,0 +1,216 @@
|
|||
#include "gtl_analog_data.h"
|
||||
|
||||
#include "gtl_device.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
analog_data::analog_data(data_model_node *parent, bool is_hidden)
|
||||
:data_model_node(types::analog, parent, is_hidden)
|
||||
, _color(Qt::black)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
analog_data::analog_data(analog_data *parent, bool is_hidden)
|
||||
:data_model_node(types::analog, parent, is_hidden)
|
||||
{
|
||||
if(parent)
|
||||
_rate = parent->get_rate();
|
||||
else
|
||||
_rate = 100000;
|
||||
|
||||
connect(parent, &analog_data::reference_changed, this, &analog_data::reference_changed);
|
||||
}
|
||||
|
||||
analog_data::analog_data(qreal rate)
|
||||
:data_model_node(types::analog, nullptr, true)
|
||||
{
|
||||
_rate = rate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void analog_data::get_data(std::back_insert_iterator<std::vector<qreal> > data)
|
||||
{
|
||||
std::copy(begin(), end(), data);
|
||||
}
|
||||
|
||||
void analog_data::set_data(iterator begin, iterator end)
|
||||
{
|
||||
|
||||
if(!_history.empty())
|
||||
{
|
||||
int size = (int)std::distance(begin, end);
|
||||
|
||||
int idx = std::max<int>(0, size - (int)_history.size());
|
||||
while(idx != size)
|
||||
{
|
||||
int copy_size = std::min<int>(size - idx, (int)_history.size() - _history_ptr);
|
||||
|
||||
std::copy(begin + idx, begin + idx + copy_size, _history.begin() + _history_ptr);
|
||||
|
||||
_history_ptr = (_history_ptr + copy_size) % _history.size();
|
||||
idx += copy_size;
|
||||
}
|
||||
}
|
||||
|
||||
emit data_changed();
|
||||
|
||||
for(std::vector<data_model_node*>::iterator iter_node = _children.begin(); iter_node != _children.end(); iter_node++)
|
||||
{
|
||||
if((*iter_node)->type() != data_model_node::analog)
|
||||
continue;
|
||||
|
||||
static_cast<analog_data*>(*iter_node)->set_data(this->begin(), this->end());
|
||||
}
|
||||
|
||||
for(auto iter_node : _hidden_children)
|
||||
{
|
||||
if(iter_node->type() != data_model_node::analog)
|
||||
continue;
|
||||
|
||||
static_cast<analog_data*>(iter_node)->set_data(this->begin(), this->end());
|
||||
}
|
||||
}
|
||||
|
||||
void analog_data::set_rate(qreal value)
|
||||
{
|
||||
if(value != _rate)
|
||||
{
|
||||
|
||||
foreach(data_model_node* child, _children)
|
||||
{
|
||||
if(child->type() == data_model_node::analog)
|
||||
{
|
||||
static_cast<analog_data*>(child)->set_rate(value);
|
||||
}
|
||||
}
|
||||
_rate = value;
|
||||
}
|
||||
}
|
||||
|
||||
void analog_data::set_color(int value)
|
||||
{
|
||||
if(value != _color)
|
||||
{
|
||||
_color = value;
|
||||
emit color_changed();
|
||||
}
|
||||
}
|
||||
|
||||
qreal analog_data::get_rate() const
|
||||
{
|
||||
return _rate;
|
||||
}
|
||||
|
||||
void analog_data::lock_device()
|
||||
{
|
||||
data_model_node* root_node = root();
|
||||
if(root_node == NULL)
|
||||
return;
|
||||
if(root_node->type() != data_model_node::device)
|
||||
return;
|
||||
|
||||
static_cast<gtl::device*>(root_node)->lock_ai();
|
||||
}
|
||||
|
||||
void analog_data::unlock_device()
|
||||
{
|
||||
data_model_node* root_node = root();
|
||||
if(root_node == NULL)
|
||||
return;
|
||||
if(root_node->type() != data_model_node::device)
|
||||
return;
|
||||
|
||||
static_cast<gtl::device*>(root_node)->unlock_ai();
|
||||
}
|
||||
|
||||
int analog_data::color() const
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
qreal analog_data::reference() const
|
||||
{
|
||||
if(parent_node())
|
||||
{
|
||||
if(parent_node()->type() == analog)
|
||||
{
|
||||
return static_cast<gtl::analog_data*>(parent_node())->reference();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void analog_data::save(QDomElement &root_element)
|
||||
{
|
||||
data_model_node::save(root_element);
|
||||
|
||||
root_element.setAttribute("color", _color);
|
||||
}
|
||||
|
||||
void analog_data::load(const QDomElement &root_element)
|
||||
{
|
||||
data_model_node::load(root_element);
|
||||
|
||||
_color = root_element.attribute("color", "0").toInt();
|
||||
}
|
||||
|
||||
void analog_data::get_state(QJsonObject &root)
|
||||
{
|
||||
root["color"] = _color;
|
||||
data_model_node::get_state(root);
|
||||
}
|
||||
|
||||
analog_data* analog_data::analog_data_root()
|
||||
{
|
||||
data_model_node* node = this;
|
||||
while(node->parent_node())
|
||||
{
|
||||
if(node->parent_node()->type() != analog)
|
||||
break;
|
||||
|
||||
node = node->parent_node();
|
||||
}
|
||||
|
||||
if(node->type() != analog)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<analog_data*>(node);
|
||||
}
|
||||
|
||||
qreal analog_data::history() const
|
||||
{
|
||||
if(_rate == 0)
|
||||
return 0;
|
||||
|
||||
return _history.size() / _rate;
|
||||
}
|
||||
|
||||
void analog_data::set_history(qreal value)
|
||||
{
|
||||
if(_rate == 0)
|
||||
return;
|
||||
|
||||
_history.resize(qRound(value*_rate));
|
||||
std::fill(_history.begin(), _history.end(), 0);
|
||||
_history_ptr = 0;
|
||||
|
||||
}
|
||||
|
||||
QJsonArray analog_data::getHistoryArray()
|
||||
{
|
||||
QJsonArray array;
|
||||
for(int i = 0; i < _history.size(); i++)
|
||||
array.append(_history[(_history_ptr + i)%_history.size()]);
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
bool analog_data::is_checkable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef ANALOG_DATA_H
|
||||
#define ANALOG_DATA_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
#include "core/gtl_data_model_node.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
class CORE_EXPORT analog_data : public data_model_node, public std::vector<qreal>
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(qreal rate READ get_rate WRITE set_rate NOTIFY rate_changed)
|
||||
Q_PROPERTY(int color READ color WRITE set_color NOTIFY color_changed)
|
||||
Q_PROPERTY(qreal reference READ reference NOTIFY reference_changed)
|
||||
Q_PROPERTY(qreal history READ history WRITE set_history)
|
||||
|
||||
public:
|
||||
analog_data(data_model_node *parent, bool is_hidden = false);
|
||||
analog_data(analog_data *parent, bool is_hidden = false);
|
||||
analog_data(qreal rate);
|
||||
|
||||
void get_data(std::back_insert_iterator<std::vector<qreal>> data);
|
||||
virtual void set_data(std::vector<qreal>::iterator begin, std::vector<qreal>::iterator end);
|
||||
|
||||
qreal get_rate() const;
|
||||
|
||||
void lock_device();
|
||||
void unlock_device();
|
||||
|
||||
int color() const;
|
||||
|
||||
virtual qreal reference() const;
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
virtual void get_state(QJsonObject& root);
|
||||
|
||||
analog_data* analog_data_root();
|
||||
|
||||
protected:
|
||||
qreal _rate;
|
||||
int _color;
|
||||
|
||||
private:
|
||||
std::vector<qreal> _history;
|
||||
int _history_ptr;
|
||||
|
||||
private:
|
||||
qreal history() const;
|
||||
void set_history(qreal value);
|
||||
|
||||
protected:
|
||||
virtual bool is_checkable() const;
|
||||
|
||||
public slots:
|
||||
virtual void set_rate(qreal value);
|
||||
void set_color(int value);
|
||||
QJsonArray getHistoryArray();
|
||||
|
||||
signals:
|
||||
void data_changed();
|
||||
void rate_changed();
|
||||
void color_changed();
|
||||
void reference_changed();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ANALOG_DATA_H
|
|
@ -0,0 +1,5 @@
|
|||
#include "gtl_core.h"
|
||||
|
||||
core::core()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef CORE_H
|
||||
#define CORE_H
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
class CORE_EXPORT core
|
||||
{
|
||||
public:
|
||||
core();
|
||||
};
|
||||
|
||||
#endif // CORE_H
|
|
@ -0,0 +1,296 @@
|
|||
#include "gtl_data_model.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
data_model::data_model(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant data_model::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
// FIXME: Implement me!
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex data_model::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
// FIXME: Implement me!
|
||||
|
||||
if(row >= rowCount(parent))
|
||||
return QModelIndex();
|
||||
|
||||
if(parent.isValid())
|
||||
{
|
||||
return createIndex(row, column, static_cast<gtl::data_model_node*>(parent.internalPointer())->child(row));
|
||||
}
|
||||
|
||||
return createIndex(row, column, _devices[row]);
|
||||
}
|
||||
|
||||
QModelIndex data_model::parent(const QModelIndex &index) const
|
||||
{
|
||||
// FIXME: Implement me!
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
gtl::data_model_node* node = static_cast<gtl::data_model_node*>(index.internalPointer());
|
||||
|
||||
if(node->parent_node() == NULL)
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
else if(node->parent_node()->parent_node() == NULL)
|
||||
{
|
||||
int row = std::find(_devices.begin(), _devices.end(), node->parent_node()) - _devices.begin();
|
||||
return createIndex(row, 0, node->parent_node());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return createIndex(index_of(node->parent_node()), 0, node->parent_node());
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex data_model::index(data_model_node *node)
|
||||
{
|
||||
return index(index_of(node), 0, parent(node));
|
||||
}
|
||||
|
||||
QModelIndex gtl::data_model::parent(data_model_node* node)
|
||||
{
|
||||
QModelIndex parent;
|
||||
if(node->parent_node())
|
||||
{
|
||||
int row_parent = node->parent_node()->index_of();
|
||||
if(row_parent < 0)
|
||||
row_parent = index_of(node->parent_node());
|
||||
|
||||
parent = createIndex(row_parent, 0, node->parent_node());
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
int data_model::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return static_cast<data_model_node*>(parent.internalPointer())->count();
|
||||
|
||||
// FIXME: Implement me!
|
||||
|
||||
return (int)_devices.size();
|
||||
}
|
||||
|
||||
int data_model::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
// FIXME: Implement me!
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant data_model::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
// FIXME: Implement me!
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
return static_cast<data_model_node*>(index.internalPointer())->name();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool data_model::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
data_model_node* node = static_cast<data_model_node*>(index.internalPointer());
|
||||
if(node)
|
||||
{
|
||||
if(role == Qt::EditRole && !value.toString().isEmpty())
|
||||
{
|
||||
node->set_name(value.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
Qt::ItemFlags data_model::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
|
||||
|
||||
data_model_node* node = static_cast<data_model_node*>(index.internalPointer());
|
||||
|
||||
if(node->type() != data_model_node::device)
|
||||
flags |= Qt::ItemFlag::ItemIsEditable;
|
||||
|
||||
while(node->type() == data_model_node::analog)
|
||||
{
|
||||
if(!node->is_enabled())
|
||||
{
|
||||
flags &= ~Qt::ItemFlag::ItemIsEnabled;
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->parent_node();
|
||||
if(node == nullptr)
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void data_model::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
_devices.clear();
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void data_model::add_device(device *d)
|
||||
{
|
||||
if(std::find(_devices.begin(), _devices.end(), d) == _devices.end())
|
||||
{
|
||||
beginInsertRows(QModelIndex(), (int)_devices.size(), (int)_devices.size());
|
||||
|
||||
_devices.push_back(d);
|
||||
|
||||
endInsertRows();
|
||||
|
||||
connect(d, &data_model_node::create_node, this, &data_model::create_node);
|
||||
connect(d, &data_model_node::deleting, this, &data_model::deleting_device);
|
||||
connect(d, &data_model_node::node_name_changed, this, &data_model::node_name_changed);
|
||||
|
||||
connect(d, &data_model_node::begin_insert_children, this, &data_model::begin_add_children);
|
||||
connect(d, &data_model_node::end_insert_children, this, &data_model::end_add_children);
|
||||
|
||||
connect(d, &data_model_node::begin_remove_children, this, &data_model::begin_remove_children);
|
||||
connect(d, &data_model_node::end_remove_children, this, &data_model::end_remove_children);
|
||||
}
|
||||
}
|
||||
|
||||
void data_model::remove(data_model_node *node)
|
||||
{
|
||||
if(node->parent_node())
|
||||
node->parent_node()->remove(node);
|
||||
else
|
||||
{
|
||||
int row = index_of(node);
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
_devices.erase(_devices.begin() + row);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
data_model_node *data_model::node(QString path) const
|
||||
{
|
||||
|
||||
QStringList tokens = path.split("/");
|
||||
if(tokens.empty())
|
||||
return NULL;
|
||||
|
||||
auto iter_device = std::find_if(_devices.cbegin(), _devices.cend(), [=](const gtl::device* d){return d->name() == tokens.first();});
|
||||
|
||||
if(iter_device == _devices.end())
|
||||
return NULL;
|
||||
|
||||
data_model_node* node = *iter_device;
|
||||
for(int i = 1; i < tokens.size(); i++)
|
||||
{
|
||||
node = node->child(tokens[i].toInt());
|
||||
if(node == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
int data_model::index_of(data_model_node *node) const
|
||||
{
|
||||
if(node->type() != data_model_node::device)
|
||||
return node->index_of();
|
||||
|
||||
auto iter = std::find(_devices.cbegin(), _devices.cend(), static_cast<device*>(node));
|
||||
if(iter == _devices.cend())
|
||||
return -1;
|
||||
|
||||
return std::distance(_devices.cbegin(), iter);
|
||||
}
|
||||
|
||||
data_model_node *data_model::node(const QModelIndex& index) const
|
||||
{
|
||||
return static_cast<gtl::data_model_node*>(index.internalPointer());
|
||||
}
|
||||
|
||||
void data_model::save(QDomElement &root_element)
|
||||
{
|
||||
for(auto device_iter: _devices)
|
||||
{
|
||||
QDomElement device_element = root_element.ownerDocument().createElement("device");
|
||||
root_element.appendChild(device_element);
|
||||
|
||||
device_iter->save(device_element);
|
||||
}
|
||||
}
|
||||
|
||||
void data_model::load(const QDomElement &root_element)
|
||||
{
|
||||
QDomElement device_element = root_element.firstChildElement("device");
|
||||
while(!device_element.isNull())
|
||||
{
|
||||
gtl::data_model_node* device = NULL;
|
||||
device = emit create_node(NULL, device_element);
|
||||
if(device)
|
||||
{
|
||||
add_device(static_cast<gtl::device*>(device));
|
||||
device->load(device_element);
|
||||
}
|
||||
|
||||
device_element = device_element.nextSiblingElement("device");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void data_model::begin_add_children(data_model_node* parent, int begin, int end)
|
||||
{
|
||||
QModelIndex parent_index = data_model::index(parent);
|
||||
beginInsertRows(parent_index, begin, end);
|
||||
|
||||
}
|
||||
|
||||
void data_model::end_add_children()
|
||||
{
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void data_model::begin_remove_children(data_model_node *parent, int begin, int end)
|
||||
{
|
||||
QModelIndex parent_index = data_model::index(parent);
|
||||
beginRemoveRows(parent_index, begin, end);
|
||||
}
|
||||
|
||||
void data_model::end_remove_children()
|
||||
{
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void data_model::deleting_device()
|
||||
{
|
||||
remove(static_cast<gtl::data_model_node*>(sender()));
|
||||
}
|
||||
|
||||
void data_model::node_name_changed(data_model_node *node)
|
||||
{
|
||||
QModelIndex node_index = index(node);
|
||||
emit dataChanged(node_index, node_index, QList<int>() << Qt::DisplayRole);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef DATA_MODEL_H
|
||||
#define DATA_MODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDomElement>
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
#include "core/gtl_device.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
class CORE_EXPORT data_model : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit data_model(QObject *parent = nullptr);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Basic functionality:
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
|
||||
QModelIndex index(data_model_node* node);
|
||||
QModelIndex parent(data_model_node* node);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
void clear();
|
||||
|
||||
void add_device(device *d);
|
||||
|
||||
|
||||
gtl::data_model_node* node(QString path) const;
|
||||
|
||||
int index_of(data_model_node* node) const;
|
||||
gtl::data_model_node* node(const QModelIndex& index) const;
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
private:
|
||||
std::vector<gtl::device*> _devices;
|
||||
|
||||
public slots:
|
||||
void remove(gtl::data_model_node* node);
|
||||
|
||||
private slots:
|
||||
void begin_add_children(gtl::data_model_node* parent, int begin, int end);
|
||||
void end_add_children();
|
||||
|
||||
void begin_remove_children(gtl::data_model_node* parent, int begin, int end);
|
||||
void end_remove_children();
|
||||
|
||||
void deleting_device();
|
||||
void node_name_changed(data_model_node *node);
|
||||
|
||||
|
||||
|
||||
signals:
|
||||
gtl::data_model_node* create_node(gtl::data_model_node* parent, QDomElement& node_element);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DATA_MODEL_H
|
|
@ -0,0 +1,264 @@
|
|||
#include "gtl_data_model_node.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "gtl_device.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
data_model_node::data_model_node(types type, data_model_node *parent, bool is_hidden)
|
||||
: QObject(parent)
|
||||
, _is_enabled(true)
|
||||
, _type(type)
|
||||
{
|
||||
if(parent)
|
||||
{
|
||||
if(is_hidden)
|
||||
{
|
||||
parent->add_hidden_child(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->add_child(this);
|
||||
|
||||
connect(this, &data_model_node::create_node, parent, &data_model_node::create_node);
|
||||
connect(this, &data_model_node::deleting, parent, &data_model_node::deleting_child);
|
||||
connect(this, &data_model_node::node_name_changed, parent, &data_model_node::node_name_changed);
|
||||
|
||||
connect(this, &data_model_node::begin_insert_children, parent, &data_model_node::begin_insert_children);
|
||||
connect(this, &data_model_node::end_insert_children, parent, &data_model_node::end_insert_children);
|
||||
|
||||
connect(this, &data_model_node::begin_remove_children, parent, &data_model_node::begin_remove_children);
|
||||
connect(this, &data_model_node::end_remove_children, parent, &data_model_node::end_remove_children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_model_node::~data_model_node()
|
||||
{
|
||||
//for(auto it: _children)
|
||||
while(_children.size() != 0)
|
||||
delete _children[0];
|
||||
|
||||
emit deleting();
|
||||
}
|
||||
|
||||
data_model_node *data_model_node::parent_node() const
|
||||
{
|
||||
return static_cast<data_model_node*>(parent());
|
||||
}
|
||||
|
||||
void data_model_node::set_name(QString name)
|
||||
{
|
||||
if(_name != name)
|
||||
{
|
||||
_name = name;
|
||||
emit name_changed();
|
||||
emit node_name_changed(this);
|
||||
}
|
||||
}
|
||||
|
||||
void data_model_node::deleting_hidden_child()
|
||||
{
|
||||
_hidden_children.erase(std::find(_hidden_children.begin(), _hidden_children.end(), sender()));
|
||||
}
|
||||
|
||||
void data_model_node::deleting_child()
|
||||
{
|
||||
remove(static_cast<data_model_node*>(sender()));
|
||||
}
|
||||
|
||||
QString data_model_node::name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
int data_model_node::count()
|
||||
{
|
||||
return (int)_children.size();
|
||||
}
|
||||
|
||||
int data_model_node::index_of(const data_model_node *child) const
|
||||
{
|
||||
int idx = std::find(_children.begin(), _children.end(), child) - _children.begin();
|
||||
if(idx == _children.size())
|
||||
idx = -1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
int data_model_node::index_of() const
|
||||
{
|
||||
data_model_node* parent = parent_node();
|
||||
if(parent)
|
||||
return parent->index_of(this);
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
data_model_node *data_model_node::child(int idx)
|
||||
{
|
||||
if(idx < 0 || idx >= (int)_children.size())
|
||||
return NULL;
|
||||
|
||||
return _children[idx];
|
||||
}
|
||||
|
||||
void data_model_node::add_child(data_model_node *child)
|
||||
{
|
||||
emit begin_insert_children(this, _children.size(), _children.size());
|
||||
_children.push_back(child);
|
||||
emit end_insert_children();
|
||||
}
|
||||
|
||||
void data_model_node::add_hidden_child(data_model_node *child)
|
||||
{
|
||||
_hidden_children.push_back(child);
|
||||
connect(child, >l::data_model_node::deleting, this, >l::data_model_node::deleting_hidden_child);
|
||||
}
|
||||
|
||||
data_model_node::types data_model_node::type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
QString data_model_node::path() const
|
||||
{
|
||||
std::vector<int> indices;
|
||||
const data_model_node* node = this;
|
||||
while(node->parent_node())
|
||||
{
|
||||
indices.push_back(node->parent_node()->index_of(node));
|
||||
node = node->parent_node();
|
||||
|
||||
}
|
||||
|
||||
QString path = node->name();
|
||||
for(auto it = indices.rbegin(); it != indices.rend(); it++)
|
||||
path += "/" + QString::number(*it);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void data_model_node::save(QDomElement &root_element)
|
||||
{
|
||||
root_element.setAttribute("node", metaObject()->className());
|
||||
root_element.setAttribute("name", _name);
|
||||
save_childs(root_element);
|
||||
}
|
||||
|
||||
void data_model_node::save_childs(QDomElement &root_element)
|
||||
{
|
||||
for(auto it: _children)
|
||||
{
|
||||
QDomElement child_element = root_element.ownerDocument().createElement("child");
|
||||
root_element.appendChild(child_element);
|
||||
|
||||
(*it).save(child_element);
|
||||
}
|
||||
}
|
||||
|
||||
void data_model_node::load(const QDomElement &root_element)
|
||||
{
|
||||
_name = root_element.attribute("name", _name);
|
||||
load_childs(root_element);
|
||||
}
|
||||
|
||||
void data_model_node::load_childs(const QDomElement &root_element)
|
||||
{
|
||||
QDomElement child_element = root_element.firstChildElement("child");
|
||||
int idx = 0;
|
||||
while(!child_element.isNull())
|
||||
{
|
||||
if(idx < count())
|
||||
{
|
||||
child(idx)->load(child_element);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_model_node* node = emit create_node(this, child_element);
|
||||
if(node)
|
||||
{
|
||||
node->load(child_element);
|
||||
}
|
||||
}
|
||||
|
||||
child_element = child_element.nextSiblingElement("child");
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void data_model_node::get_state(QJsonObject &root)
|
||||
{
|
||||
root["name"] = _name;
|
||||
root["node"] = metaObject()->className();
|
||||
}
|
||||
|
||||
bool data_model_node::remove(data_model_node *child)
|
||||
{
|
||||
auto iter = std::find(_children.begin(), _children.end(), child);
|
||||
if(iter == _children.end())
|
||||
return false;
|
||||
|
||||
int idx = std::distance(_children.begin(), iter);
|
||||
|
||||
|
||||
gtl::data_model_node* root = child->root();
|
||||
if(root)
|
||||
if(root->type() == device)
|
||||
static_cast<gtl::device*>(root)->lock_ai();
|
||||
|
||||
|
||||
emit begin_remove_children(this, idx, idx);
|
||||
|
||||
_children.erase(iter);
|
||||
|
||||
emit end_remove_children();
|
||||
|
||||
if(root)
|
||||
if(root->type() == device)
|
||||
static_cast<gtl::device*>(root)->unlock_ai();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void data_model_node::remove_children()
|
||||
{
|
||||
if(_children.empty())
|
||||
return;
|
||||
|
||||
emit begin_remove_children(this, 0, (int)_children.size() - 1);
|
||||
|
||||
_children.clear();
|
||||
|
||||
emit end_remove_children();
|
||||
}
|
||||
|
||||
bool data_model_node::is_child_name_exist(QString name)
|
||||
{
|
||||
return std::find_if(_children.begin(), _children.end(), [=](data_model_node* child){return child->name() == name;}) != _children.end();
|
||||
}
|
||||
|
||||
void data_model_node::set_enabled(bool value)
|
||||
{
|
||||
_is_enabled = value;
|
||||
}
|
||||
|
||||
bool data_model_node::is_enabled() const
|
||||
{
|
||||
return _is_enabled;
|
||||
}
|
||||
|
||||
data_model_node *data_model_node::root()
|
||||
{
|
||||
data_model_node* node = this;
|
||||
while(node->parent_node())
|
||||
node = node->parent_node();
|
||||
|
||||
if(node->type() != device)
|
||||
return nullptr;
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef DATA_MODEL_NODE_H
|
||||
#define DATA_MODEL_NODE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDomElement>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
class CORE_EXPORT data_model_node : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name WRITE set_name NOTIFY name_changed)
|
||||
|
||||
public:
|
||||
enum types
|
||||
{
|
||||
unknown,
|
||||
device,
|
||||
analog
|
||||
};
|
||||
|
||||
public:
|
||||
data_model_node(types type, data_model_node *parent = nullptr, bool is_hidden = false);
|
||||
~data_model_node();
|
||||
data_model_node* parent_node() const;
|
||||
|
||||
|
||||
QString name() const;
|
||||
|
||||
int count();
|
||||
int index_of(const data_model_node* child) const;
|
||||
int index_of() const;
|
||||
data_model_node* child(int idx);
|
||||
|
||||
virtual bool is_checkable() const = 0;
|
||||
|
||||
types type() const;
|
||||
|
||||
QString path() const;
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void save_childs(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
virtual void load_childs(const QDomElement& root_element);
|
||||
virtual void get_state(QJsonObject& root);
|
||||
|
||||
bool remove(data_model_node* child);
|
||||
void remove_children();
|
||||
|
||||
data_model_node* root();
|
||||
|
||||
bool is_child_name_exist(QString name);
|
||||
|
||||
void set_enabled(bool value);
|
||||
bool is_enabled() const;
|
||||
|
||||
protected:
|
||||
QString _name;
|
||||
std::vector<data_model_node*> _children;
|
||||
std::vector<data_model_node*> _hidden_children;
|
||||
bool _is_enabled;
|
||||
|
||||
private:
|
||||
types _type;
|
||||
|
||||
private:
|
||||
void add_child(data_model_node* child);
|
||||
void add_hidden_child(data_model_node* child);
|
||||
|
||||
public slots:
|
||||
void set_name(QString name);
|
||||
void deleting_hidden_child();
|
||||
|
||||
private slots:
|
||||
void deleting_child();
|
||||
|
||||
signals:
|
||||
void name_changed();
|
||||
void node_name_changed(data_model_node*);
|
||||
void deleting();
|
||||
gtl::data_model_node* create_node(gtl::data_model_node* parent, QDomElement& node_element);
|
||||
|
||||
void begin_insert_children(gtl::data_model_node* parent, int begin, int end);
|
||||
void end_insert_children();
|
||||
|
||||
void begin_remove_children(gtl::data_model_node* parent, int begin, int end);
|
||||
void end_remove_children();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DATA_MODEL_NODE_H
|
|
@ -0,0 +1,122 @@
|
|||
#include "gtl_device.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
device::device(data_model_node *parent)
|
||||
: data_model_node(types::device, parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
device::~device()
|
||||
{
|
||||
// lock_ai();
|
||||
}
|
||||
|
||||
gtl::analog_data *device::ai(int idx)
|
||||
{
|
||||
if(idx < 0 || idx >= _ai.size())
|
||||
return NULL;
|
||||
|
||||
return _ai[idx];
|
||||
}
|
||||
|
||||
void device::clear()
|
||||
{
|
||||
for(int i = 0; i < _ai.size(); i++)
|
||||
{
|
||||
// _children.erase(std::find(_children.begin(), _children.end(), _ai[i]));
|
||||
delete _ai[i];
|
||||
}
|
||||
|
||||
_ai.clear();
|
||||
}
|
||||
|
||||
int device::count_ai() const
|
||||
{
|
||||
return (int)_ai.size();
|
||||
}
|
||||
|
||||
void device::add_ai(analog_data *ai)
|
||||
{
|
||||
_ai.push_back(ai);
|
||||
}
|
||||
|
||||
void device::lock_ai()
|
||||
{
|
||||
_ai_mutex.lock();
|
||||
}
|
||||
|
||||
void device::unlock_ai()
|
||||
{
|
||||
_ai_mutex.unlock();
|
||||
}
|
||||
|
||||
void device::save(QDomElement &root_element)
|
||||
{
|
||||
emit save_device(root_element);
|
||||
data_model_node::save(root_element);
|
||||
}
|
||||
|
||||
void device::load(const QDomElement &root_element)
|
||||
{
|
||||
bool is_running = root_element.attribute("is_running", "0").toInt();
|
||||
_id = root_element.attribute("id", "");
|
||||
_rate = root_element.attribute("rate", "0").toDouble();
|
||||
|
||||
emit load_device(root_element);
|
||||
|
||||
emit start(_id, _rate);
|
||||
|
||||
data_model_node::load(root_element);
|
||||
|
||||
if(is_running)
|
||||
emit restart();
|
||||
else
|
||||
emit stop();
|
||||
|
||||
}
|
||||
|
||||
QString device::id() const
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
void device::set_id(QString id)
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
qreal device::rate() const
|
||||
{
|
||||
return _rate;
|
||||
}
|
||||
|
||||
void device::set_rate(qreal rate)
|
||||
{
|
||||
_rate = rate;
|
||||
}
|
||||
|
||||
QString device::device_type() const
|
||||
{
|
||||
return emit get_type();
|
||||
}
|
||||
|
||||
QVariant device::get_parameter(int idx)
|
||||
{
|
||||
QVariant v;
|
||||
emit get_device_parameter(idx, v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void device::set_parameter(int idx, QVariant value)
|
||||
{
|
||||
emit set_device_parameter(idx, value);
|
||||
}
|
||||
|
||||
bool device::is_checkable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QRecursiveMutex>
|
||||
#include <QVariant>
|
||||
|
||||
#include "core/gtl_analog_data.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
class CORE_EXPORT device : public data_model_node
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
device(data_model_node *parent = nullptr);
|
||||
virtual ~device();
|
||||
|
||||
analog_data* ai(int idx);
|
||||
|
||||
void clear();
|
||||
int count_ai() const;
|
||||
|
||||
void add_ai(analog_data* ai);
|
||||
|
||||
void lock_ai();
|
||||
void unlock_ai();
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
QString id() const;
|
||||
void set_id(QString id);
|
||||
|
||||
qreal rate() const;
|
||||
void set_rate(qreal rate);
|
||||
|
||||
QString device_type() const;
|
||||
|
||||
QVariant get_parameter(int idx);
|
||||
void set_parameter(int idx, QVariant value);
|
||||
|
||||
protected:
|
||||
virtual bool is_checkable() const;
|
||||
|
||||
private:
|
||||
std::vector<analog_data*> _ai;
|
||||
QRecursiveMutex _ai_mutex;
|
||||
|
||||
QString _id;
|
||||
qreal _rate;
|
||||
|
||||
|
||||
signals:
|
||||
void save_device(QDomElement& root_element);
|
||||
void load_device(const QDomElement& root_element);
|
||||
void start(QString id, qreal rate);
|
||||
void restart();
|
||||
void stop();
|
||||
void recieved_data();
|
||||
QString get_type() const;
|
||||
|
||||
void get_device_parameter(int idx, QVariant &value);
|
||||
void set_device_parameter(int idx, const QVariant &value);
|
||||
|
||||
void started();
|
||||
void stopped();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DEVICE_H
|
|
@ -0,0 +1,183 @@
|
|||
#include "gtl_logger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QRegularExpression>
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
QFile logger::_log_file;
|
||||
QString logger::_path;
|
||||
QString logger::_file_name;
|
||||
QThread logger::_thread;
|
||||
uint32_t logger::_max_file_size;
|
||||
uint32_t logger::_max_index;
|
||||
|
||||
logger::logger(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
_is_continue = false;
|
||||
open_file();
|
||||
}
|
||||
|
||||
logger::~logger()
|
||||
{
|
||||
if(_log_file.isOpen())
|
||||
_log_file.close();
|
||||
_thread.wait();
|
||||
}
|
||||
|
||||
logger* logger::getInstance()
|
||||
{
|
||||
static logger instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void logger::init(const QString &path, const uint32_t max_file_size, const file_size_unit unit)
|
||||
{
|
||||
_path = path;
|
||||
_max_file_size = max_file_size << get_file_size_unit(unit);
|
||||
_file_name = find_last_file();
|
||||
|
||||
connect(getInstance(), &logger::sgn_info, getInstance(), &logger::slt_info);
|
||||
connect(getInstance(), &logger::sgn_warning, getInstance(), &logger::slt_warning);
|
||||
connect(getInstance(), &logger::sgn_error, getInstance(), &logger::slt_error);
|
||||
connect(getInstance(), &logger::sgn_debug, getInstance(), &logger::slt_debug);
|
||||
|
||||
getInstance()->moveToThread(&_thread);
|
||||
_thread.start();
|
||||
}
|
||||
|
||||
void logger::open_file()
|
||||
{
|
||||
if(_log_file.isOpen())
|
||||
_log_file.close();
|
||||
|
||||
_log_file.setFileName(_file_name );
|
||||
|
||||
_log_file.open( QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text );
|
||||
|
||||
if( !_log_file.isOpen() )
|
||||
throw std::iostream::failure("Cannot open file: " + _file_name.toStdString());
|
||||
}
|
||||
|
||||
QString logger::find_last_file()
|
||||
{
|
||||
QString file_name = _path + QDir::separator() + "log_0000";
|
||||
QRegularExpression reNameLogFile("^log_(\\d{4})$");
|
||||
|
||||
QDir currentDir = QDir(_path);
|
||||
|
||||
if(false == currentDir.exists())
|
||||
currentDir.mkdir(_path);
|
||||
|
||||
QStringList filters;
|
||||
filters << "log_*";
|
||||
QStringList filesList = currentDir.entryList(filters, QDir::Files | QDir::NoSymLinks);
|
||||
|
||||
if(!filesList.isEmpty())
|
||||
{
|
||||
_max_index = 0;
|
||||
uint32_t current_index = 0;
|
||||
bool flagFindCorrectName = false;
|
||||
|
||||
while(!filesList.isEmpty())
|
||||
{
|
||||
QString fName = filesList.at(0);
|
||||
filesList.removeFirst();
|
||||
|
||||
QRegularExpressionMatch match = reNameLogFile.match(fName);
|
||||
if(!match.hasMatch())
|
||||
continue;
|
||||
|
||||
flagFindCorrectName = true;
|
||||
fName.replace("log_", "");
|
||||
current_index = fName.toUInt();
|
||||
|
||||
_max_index = ((_max_index < current_index) ? current_index : _max_index);
|
||||
}
|
||||
|
||||
if(flagFindCorrectName)
|
||||
{
|
||||
file_name = _path + QDir::separator() + "log_" + QString::number(_max_index).rightJustified(4, '0');
|
||||
if(false == check_file_size(file_name))
|
||||
{
|
||||
_max_index += 1;
|
||||
file_name = _path + QDir::separator() + "log_" + QString::number(_max_index).rightJustified(4, '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return file_name;
|
||||
}
|
||||
|
||||
bool logger::check_file_size(const QString& path)
|
||||
{
|
||||
QFileInfo info1(path);
|
||||
return (info1.size() >= _max_file_size) ? false : true;
|
||||
}
|
||||
|
||||
void logger::info(const QString &tag, const QString &str)
|
||||
{
|
||||
if(getInstance() != nullptr)
|
||||
emit getInstance()->sgn_info(tag, str);
|
||||
}
|
||||
|
||||
void logger::warning(const QString &tag, const QString &str)
|
||||
{
|
||||
if(getInstance() != nullptr)
|
||||
emit getInstance()->sgn_warning(tag, str);
|
||||
}
|
||||
|
||||
void logger::error(const QString &tag, const QString &str)
|
||||
{
|
||||
if(getInstance() != nullptr)
|
||||
emit getInstance()->sgn_error(tag, str);
|
||||
}
|
||||
|
||||
void logger::debug(const QString &tag, const QString &str)
|
||||
{
|
||||
if(getInstance() != nullptr)
|
||||
emit getInstance()->sgn_debug(tag, str);
|
||||
}
|
||||
|
||||
uint32_t logger::get_file_size_unit(const file_size_unit unit)
|
||||
{
|
||||
uint32_t temp;
|
||||
switch(unit) {
|
||||
case file_size_unit::b: temp = 0; break;
|
||||
case file_size_unit::kb: temp = 10; break;
|
||||
case file_size_unit::mb: temp = 20; break;
|
||||
case file_size_unit::gb: temp = 30; break;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
QString logger::get_level_string(const log_level level)
|
||||
{
|
||||
QString temp;
|
||||
switch(level) {
|
||||
case log_level::info: temp = "INFO"; break;
|
||||
case log_level::warning: temp = "WARNING"; break;
|
||||
case log_level::debug: temp = "DEBUG"; break;
|
||||
case log_level::error: temp = "ERROR"; break;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
QString logger::get_time_string()
|
||||
{
|
||||
//** for debug **
|
||||
//QThread::sleep(5);
|
||||
//** for debug **
|
||||
|
||||
QDateTime m_dateTime = QDateTime::currentDateTime();
|
||||
return m_dateTime.toString("hh:mm:ss.zzz");
|
||||
}
|
||||
|
||||
QString logger::get_date_string()
|
||||
{
|
||||
QDateTime m_dateTime = QDateTime::currentDateTime();
|
||||
return m_dateTime.toString("dd.MM.yyyy");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
#ifndef GTL_LOGGER_H
|
||||
#define GTL_LOGGER_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QObject>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
#include <QFile>
|
||||
#include "core_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
|
||||
enum class log_level {
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
debug
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CORE_EXPORT logger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum file_size_unit {
|
||||
b,
|
||||
kb,
|
||||
mb,
|
||||
gb
|
||||
};
|
||||
|
||||
static logger *getInstance(void);
|
||||
static void init(const QString &path, const uint32_t max_file_size, const file_size_unit unit);
|
||||
static void info(const QString &tag, const QString &text);
|
||||
static void warning(const QString &tag, const QString &text);
|
||||
static void error(const QString &tag, const QString &text);
|
||||
static void debug(const QString &tag, const QString &text);
|
||||
|
||||
private:
|
||||
static QFile _log_file;
|
||||
static QString _path;
|
||||
static QString _file_name;
|
||||
static QThread _thread;
|
||||
static uint32_t _max_file_size;
|
||||
static uint32_t _max_index;
|
||||
|
||||
static void open_file(void);
|
||||
static QString find_last_file(void);
|
||||
static bool check_file_size(const QString& path);
|
||||
|
||||
protected:
|
||||
logger(QObject *parent = nullptr);
|
||||
~logger();
|
||||
|
||||
bool _is_continue;
|
||||
static uint32_t get_file_size_unit(const file_size_unit unit);
|
||||
QString get_level_string(const log_level level);
|
||||
QString get_time_string(void);
|
||||
QString get_date_string(void);
|
||||
|
||||
|
||||
|
||||
signals:
|
||||
void sgn_info(const QString &tag, const QString &text);
|
||||
void sgn_warning(const QString &tag, const QString &text);
|
||||
void sgn_error(const QString &tag, const QString &text);
|
||||
void sgn_debug(const QString &tag, const QString &text);
|
||||
void sgn_send_to_viewer(const QString &level, const QString &date, const QString &time, const QString &tag, const QString &text);
|
||||
|
||||
|
||||
public slots:
|
||||
void slt_info(const QString &tag, const QString &text) { log(log_level::info, tag, text); }
|
||||
void slt_warning(const QString &tag, const QString &text){ log(log_level::warning, tag, text); }
|
||||
void slt_error(const QString &tag, const QString &text) { log(log_level::error, tag, text); }
|
||||
void slt_debug(const QString &tag, const QString &text) { log(log_level::debug, tag, text); }
|
||||
|
||||
void log(log_level level = log_level::info, const QString &tag = "FLUSH", const QString &text = "flush")
|
||||
{
|
||||
QString s_level = get_level_string(level);
|
||||
QString s_date = get_date_string();
|
||||
QString s_time = get_time_string();
|
||||
|
||||
QString str_new = "[" + s_level + "]::[" +\
|
||||
s_date + "]::[" +\
|
||||
s_time + "]::[" +\
|
||||
tag + "]::" +\
|
||||
text + "\n";
|
||||
|
||||
QTextStream textStream(&_log_file);
|
||||
textStream << str_new.toStdString().c_str();
|
||||
|
||||
if(false == check_file_size(_file_name))
|
||||
{
|
||||
_max_index += 1;
|
||||
_file_name = _path + QDir::separator() + "log_" + QString::number(_max_index).rightJustified(4, '0');
|
||||
|
||||
open_file();
|
||||
}
|
||||
|
||||
emit sgn_send_to_viewer(s_level, s_date, s_time, tag, text);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // GTL_LOGGER_H
|
|
@ -0,0 +1,202 @@
|
|||
#include "gtl_selection_data_model.h"
|
||||
|
||||
#include "core/gtl_data_model.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
selection_data_model::selection_data_model(QObject *source, int count)
|
||||
: QIdentityProxyModel{source}
|
||||
, _count(count)
|
||||
{
|
||||
// setSourceModel(source);
|
||||
_selection = new selection_list(this);
|
||||
}
|
||||
|
||||
void selection_data_model::save(QDomElement &root_element)
|
||||
{
|
||||
for(auto it = _selection->begin(); it != _selection->end(); it++)
|
||||
{
|
||||
QDomElement item_element = root_element.ownerDocument().createElement("item");
|
||||
root_element.appendChild(item_element);
|
||||
item_element.setAttribute("path", (*it)->path());
|
||||
}
|
||||
root_element.setAttribute("count", _count);
|
||||
}
|
||||
|
||||
void gtl::selection_data_model::add_selection(gtl::data_model_node* node)
|
||||
{
|
||||
|
||||
if(std::find(_selection->begin(), _selection->end(), node) != _selection->end())
|
||||
return;
|
||||
|
||||
|
||||
_selection->add(node);
|
||||
connect(node, >l::data_model_node::deleting, this, &selection_data_model::deleting_node);
|
||||
emit selected(static_cast<analog_data*>(node));
|
||||
|
||||
while(_selection->size() > _count && _count > 0)
|
||||
deselect(_selection->front());
|
||||
}
|
||||
|
||||
void selection_data_model::load(const QDomElement &root_element)
|
||||
{
|
||||
clear();
|
||||
|
||||
gtl::data_model* model = static_cast<gtl::data_model*>(sourceModel());
|
||||
|
||||
_count = root_element.attribute("count", "0").toInt();
|
||||
|
||||
QDomElement item_element = root_element.firstChildElement(/*"item"*/);
|
||||
while(!item_element.isNull())
|
||||
{
|
||||
gtl::data_model_node* node = model->node(item_element.attribute("path", ""));
|
||||
if(node)
|
||||
{
|
||||
add_selection(node);
|
||||
QModelIndex index = createIndex(node->index_of(), 0, node);
|
||||
emit dataChanged(index, index, QList<int>() << Qt::CheckStateRole);
|
||||
}
|
||||
|
||||
item_element = item_element.nextSiblingElement("item");
|
||||
}
|
||||
}
|
||||
|
||||
void selection_data_model::clear()
|
||||
{
|
||||
for(auto it = _selection->begin(); it != _selection->end(); it++)
|
||||
emit deselected(static_cast<analog_data*>(*it));
|
||||
|
||||
_selection->remove_all();
|
||||
}
|
||||
|
||||
QAbstractListModel *selection_data_model::selection()
|
||||
{
|
||||
return _selection;
|
||||
}
|
||||
|
||||
Qt::ItemFlags selection_data_model::flags(const QModelIndex &index) const
|
||||
{
|
||||
return QIdentityProxyModel::flags(index) | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
||||
QVariant selection_data_model::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(role == Qt::CheckStateRole)
|
||||
{
|
||||
if(parent(index).isValid())
|
||||
{
|
||||
data_model_node* node = static_cast<data_model_node*>(index.internalPointer());
|
||||
if(std::find(_selection->begin(), _selection->end(), node) == _selection->end())
|
||||
return Qt::Unchecked;
|
||||
else
|
||||
return Qt::Checked;
|
||||
}
|
||||
}
|
||||
|
||||
return QIdentityProxyModel::data(index, role);
|
||||
}
|
||||
|
||||
bool selection_data_model::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if(role == Qt::CheckStateRole)
|
||||
{
|
||||
data_model_node* node = static_cast<data_model_node*>(index.internalPointer());
|
||||
if(node->is_checkable())
|
||||
{
|
||||
if(value.toBool())
|
||||
{
|
||||
add_selection(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_selection->size() > _count)
|
||||
{
|
||||
_selection->remove(node);
|
||||
emit deselected(static_cast<analog_data*>(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return QIdentityProxyModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
void selection_data_model::get_selections(std::back_insert_iterator<std::vector<analog_data *> > ad)
|
||||
{
|
||||
std::copy(_selection->begin(), _selection->end(), ad);
|
||||
}
|
||||
|
||||
void selection_data_model::select(analog_data *node)
|
||||
{
|
||||
QModelIndex index = mapFromSource(static_cast<data_model*>(sourceModel())->index(node));
|
||||
setData(index, true, Qt::CheckStateRole);
|
||||
emit dataChanged(index, index, {Qt::CheckStateRole});
|
||||
}
|
||||
|
||||
void selection_data_model::deselect(analog_data *node)
|
||||
{
|
||||
QModelIndex index = mapFromSource(static_cast<data_model*>(sourceModel())->index(node));
|
||||
setData(index, false, Qt::CheckStateRole);
|
||||
emit dataChanged(index, index, {Qt::CheckStateRole});
|
||||
}
|
||||
|
||||
void selection_data_model::deleting_node()
|
||||
{
|
||||
auto iter_node = std::find(_selection->begin(), _selection->end(), sender());
|
||||
if(iter_node != _selection->end())
|
||||
_selection->remove(*iter_node);
|
||||
}
|
||||
|
||||
selection_list::selection_list(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int selection_list::rowCount(const QModelIndex&) const
|
||||
{
|
||||
return (int)size();
|
||||
}
|
||||
|
||||
QVariant selection_list::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(role == Qt::DisplayRole)
|
||||
return at(index.row())->name();
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
void selection_list::add(data_model_node *node)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), (int)size(), (int)size());
|
||||
|
||||
push_back(static_cast<gtl::analog_data*>(node));
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void selection_list::remove(data_model_node *node)
|
||||
{
|
||||
auto it = std::find(begin(), end(), node);
|
||||
if(it == end())
|
||||
return;
|
||||
|
||||
int idx = std::distance(begin(), it);
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
|
||||
erase(it);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void selection_list::remove_all()
|
||||
{
|
||||
beginResetModel();
|
||||
clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef GTL_SELELCTION_DATA_MODEL_H
|
||||
#define GTL_SELELCTION_DATA_MODEL_H
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <QIdentityProxyModel>
|
||||
#include <QDomElement>
|
||||
|
||||
#include "core/core_global.h"
|
||||
|
||||
#include "core/gtl_analog_data.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
class selection_list : public QAbstractListModel, public std::deque<gtl::analog_data*>
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
selection_list(QObject* parent = NULL);
|
||||
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void add(data_model_node* node);
|
||||
void remove(data_model_node* node);
|
||||
|
||||
void remove_all();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CORE_EXPORT selection_data_model : public QIdentityProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit selection_data_model(QObject *source, int count = 0);
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
void clear();
|
||||
|
||||
QAbstractListModel* selection();
|
||||
|
||||
void get_selections(std::back_insert_iterator<std::vector<gtl::analog_data*>> ad);
|
||||
|
||||
void select(gtl::analog_data* node);
|
||||
void deselect(gtl::analog_data* node);
|
||||
|
||||
protected:
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
virtual QVariant data(const QModelIndex &index, int role/* = Qt::DisplayRole*/) const override;
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
private:
|
||||
selection_list* _selection;
|
||||
int _count;
|
||||
|
||||
private:
|
||||
void add_selection(gtl::data_model_node* node);
|
||||
|
||||
private slots:
|
||||
void deleting_node();
|
||||
|
||||
signals:
|
||||
void selected(gtl::analog_data*);
|
||||
void deselected(gtl::analog_data*);
|
||||
};
|
||||
}
|
||||
#endif // GTL_SELELCTION_DATA_MODEL_H
|
|
@ -0,0 +1,41 @@
|
|||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "gtl_sdk"
|
||||
#define MyAppVersion "0.38"
|
||||
#define MyAppPublisher "GTLab"
|
||||
#define MyAppURL "www.gtlab.pro"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
; Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{F66666BA-CAFC-4712-8325-BDE3CAC56477}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
;AppVerName={#MyAppName} {#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
OutputBaseFilename={#MyAppName}-{#MyAppVersion}-setup
|
||||
OutputDir=e:\setups\gt\gtl_sdk
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
|
||||
[Files]
|
||||
Source: ".\.output\*"; DestDir: "{app}\lib"; Flags: ignoreversion recursesubdirs createallsubdirs; Excludes: "*.exp, *.ilk, *.pdb"
|
||||
Source: ".\core\*.h"; DestDir: "{app}\include\core"; Flags: ignoreversion
|
||||
Source: ".\gui\*.h"; DestDir: "{app}\include\gui"; Flags: ignoreversion recursesubdirs
|
||||
Source: ".\hw\*.h"; DestDir: "{app}\include\hw"; Flags: ignoreversion; Excludes: "adlink.h"
|
||||
Source: ".\math\*.h"; DestDir: "{app}\include\math"; Flags: ignoreversion
|
||||
Source: ".\script\*.h"; DestDir: "{app}\include\script"; Flags: ignoreversion
|
||||
Source: ".\test_gtl\version.h"; DestDir: "{app}\include"; Flags: ignoreversion
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#include "gtl_gui_config_filter_response_chart.h"
|
||||
|
||||
#include "gui/config/gtl_gui_config_filter_response_chart_series.h"
|
||||
#include "gui/config/gtl_gui_config_filter_response_chart_series_axis_y.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
filter_response_chart::filter_response_chart(QWidget* parent)
|
||||
: gtl::gui::chart(parent, new chart_axis_x(), new filter_response_chart_series_axis_y())
|
||||
{
|
||||
_axis_x->set_scale(::chart::axis::logarithmic);
|
||||
}
|
||||
|
||||
void filter_response_chart::set_filter(math::filter_iir *filter)
|
||||
{
|
||||
remove_series();
|
||||
add_ad(filter);
|
||||
}
|
||||
|
||||
chart_series *filter_response_chart::create_series(analog_data *ai)
|
||||
{
|
||||
return new filter_response_chart_series(static_cast<gtl::math::filter_iir*>(ai), _axis_x, _axis_y);
|
||||
}
|
||||
|
||||
void filter_response_chart::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
gtl::gui::chart::resizeEvent(event);
|
||||
|
||||
if(!_series.empty())
|
||||
static_cast<filter_response_chart_series*>(_series.front())->update_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef FILTER_RESPONSE_CHART_H
|
||||
#define FILTER_RESPONSE_CHART_H
|
||||
|
||||
#include "gui/gtl_gui_chart.h"
|
||||
#include "math/gtl_math_filter_iir.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class filter_response_chart : public gtl::gui::chart
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
filter_response_chart(QWidget* parent = NULL);
|
||||
void set_filter(gtl::math::filter_iir* filter);
|
||||
|
||||
private:
|
||||
virtual chart_series* create_series(gtl::analog_data* ai) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FILTER_RESPONSE_CHART_H
|
|
@ -0,0 +1,87 @@
|
|||
#include "gtl_gui_config_filter_response_chart_series.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
filter_response_chart_series::filter_response_chart_series(gtl::math::filter_iir* filter, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y)
|
||||
: gtl::gui::chart_series(filter, axis_x, axis_y)
|
||||
, _y_min(-100)
|
||||
, _y_max(0)
|
||||
{
|
||||
|
||||
connect(filter, >l::math::filter_iir::changed, this, &filter_response_chart_series::update_data);
|
||||
|
||||
connect(axis_x, &::chart::axis_horz::signal_range_changed, this, &filter_response_chart_series::update_data);
|
||||
|
||||
update_data();
|
||||
}
|
||||
|
||||
void filter_response_chart_series::update_data()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
gtl::math::filter_iir* filter = static_cast<gtl::math::filter_iir*>(_ad);
|
||||
qreal rate = filter->get_rate();
|
||||
std::vector<QPointF> data;
|
||||
|
||||
data.push_back(QPointF(1, 20 * log10(std::max<qreal>(1e-5, filter->response(1/rate)))));
|
||||
|
||||
_y_min = 0;
|
||||
_y_max = -100;
|
||||
|
||||
for(int i = 0; i < (_axis_horz->boundingRect().width() + 1)*10; i++)
|
||||
{
|
||||
qreal x = _axis_horz->map_from_widget(i/10.0);
|
||||
qreal y = 1;
|
||||
y = filter->response(x / rate);
|
||||
|
||||
if (qIsNaN(y) || y == qInf() || y == -qInf())
|
||||
continue;
|
||||
|
||||
if (y < 1e-5)
|
||||
y = 1e-5;
|
||||
|
||||
y = 20 * log10(y/* / 0.000001*/);
|
||||
|
||||
if(y < _y_min)
|
||||
_y_min = y;
|
||||
if(y > _y_max)
|
||||
_y_max = y;
|
||||
|
||||
data.push_back(QPointF(x, y));
|
||||
}
|
||||
|
||||
data.push_back(QPointF(rate/2, 20 * log10(std::max<qreal>(filter->response(0.5), 1e-5))));
|
||||
|
||||
set_data(data.begin(), data.end());
|
||||
|
||||
qreal range = _y_max - _y_min;
|
||||
_axis_vert->set_range(_y_min - 0.05*range, _y_max + 0.05*range);
|
||||
|
||||
}
|
||||
|
||||
bool filter_response_chart_series::get_ranges(qreal &x_min, qreal &x_max, qreal &y_min, qreal &y_max)
|
||||
{
|
||||
x_min = 0;
|
||||
x_max = static_cast<gtl::math::filter_iir*>(_ad)->get_rate()/2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool filter_response_chart_series::get_range_y(qreal x_min, qreal x_max, qreal &y_min, qreal &y_max)
|
||||
{
|
||||
// y_min = _y_min;
|
||||
// y_max = _y_max;
|
||||
// qDebug() << _y_min << _y_max;
|
||||
|
||||
// return true;
|
||||
|
||||
return gtl::gui::chart_series::get_range_y(x_min, x_max, y_min, y_max);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef FILTER_RESPONSE_CHART_SERIES_H
|
||||
#define FILTER_RESPONSE_CHART_SERIES_H
|
||||
|
||||
#include "gui/gtl_gui_chart_series.h"
|
||||
#include "math/gtl_math_filter_iir.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class filter_response_chart_series : public gtl::gui::chart_series
|
||||
{
|
||||
public:
|
||||
filter_response_chart_series(gtl::math::filter_iir* filter, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y);
|
||||
|
||||
private:
|
||||
virtual bool get_ranges(qreal &x_min, qreal &x_max, qreal &y_min, qreal &y_max) override;
|
||||
virtual bool get_range_y(qreal x_min, qreal x_max, qreal &y_min, qreal &y_max) override;
|
||||
|
||||
private:
|
||||
qreal _y_min;
|
||||
qreal _y_max;
|
||||
|
||||
public slots:
|
||||
void update_data();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FILTER_RESPONSE_CHART_SERIES_H
|
|
@ -0,0 +1,20 @@
|
|||
#include "gtl_gui_config_filter_response_chart_series_axis_y.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
filter_response_chart_series_axis_y::filter_response_chart_series_axis_y()
|
||||
{
|
||||
_is_autoscale = true;
|
||||
}
|
||||
|
||||
void filter_response_chart_series_axis_y::emit_fit()
|
||||
{
|
||||
emit fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef FILTER_RESPONSE_CHART_SERIES_AXIS_Y_H
|
||||
#define FILTER_RESPONSE_CHART_SERIES_AXIS_Y_H
|
||||
|
||||
#include "gui/gtl_gui_chart_axis_y.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class filter_response_chart_series_axis_y : public chart_axis_y
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
filter_response_chart_series_axis_y();
|
||||
void emit_fit();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // FILTER_RESPONSE_CHART_SERIES_AXIS_Y_H
|
|
@ -0,0 +1,88 @@
|
|||
#include "gtl_gui_config_hardware_dialog.h"
|
||||
#include "ui_gtl_gui_config_hardware_dialog.h"
|
||||
|
||||
#include "gui/config/gtl_gui_config_hw_widget_audio.h"
|
||||
#include "gui/config/gtl_gui_config_hw_widget_dac.h"
|
||||
#include "gui/config/gtl_gui_config_hw_widget_generator.h"
|
||||
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
hardware_dialog::hardware_dialog(QString plugins_path, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, _hw(plugins_path)
|
||||
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
|
||||
_ui.stacked_widget->addWidget(new hw_widget_dac(plugins_path, this));
|
||||
_ui.stacked_widget->addWidget(new hw_widget_generator(this));
|
||||
_ui.stacked_widget->addWidget(new hw_widget_audio(this));
|
||||
}
|
||||
|
||||
hardware_dialog::~hardware_dialog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString hardware_dialog::id() const
|
||||
{
|
||||
|
||||
return static_cast<hw_widget*>(_ui.stacked_widget->currentWidget())->id();
|
||||
}
|
||||
|
||||
qreal hardware_dialog::rate() const
|
||||
{
|
||||
return static_cast<hw_widget*>(_ui.stacked_widget->currentWidget())->rate();
|
||||
}
|
||||
|
||||
QString hardware_dialog::type() const
|
||||
{
|
||||
|
||||
if(_ui.stacked_widget->currentIndex() == 1)
|
||||
return "generator";
|
||||
else if(_ui.stacked_widget->currentIndex() == 2)
|
||||
return "audio";
|
||||
else if(_ui.stacked_widget->currentIndex() == 3)
|
||||
return "player";
|
||||
|
||||
return static_cast<hw_widget_dac*>(_ui.stacked_widget->widget(0))->type();
|
||||
}
|
||||
|
||||
hw::device* hardware_dialog::create_device()
|
||||
{
|
||||
return static_cast<hw_widget*>(_ui.stacked_widget->currentWidget())->create_device();
|
||||
}
|
||||
|
||||
hw::device *hardware_dialog::create_device(QString type)
|
||||
{
|
||||
return static_cast<hw_widget*>(_ui.stacked_widget->widget(get_widget_idex(type)))->create_device();
|
||||
}
|
||||
|
||||
int hardware_dialog::exec(QString type)
|
||||
{
|
||||
_ui.stacked_widget->setCurrentIndex(get_widget_idex(type));
|
||||
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
int hardware_dialog::get_widget_idex(QString type)
|
||||
{
|
||||
if(type == "generator")
|
||||
return 1;
|
||||
else if(type == "audio")
|
||||
return 2;
|
||||
else if(type == "player")
|
||||
return 3;
|
||||
|
||||
static_cast<hw_widget_dac*>(_ui.stacked_widget->widget(0))->set_type(type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef GTL_GUI_CONFIG_HARDWARE_DIALOG_H
|
||||
#define GTL_GUI_CONFIG_HARDWARE_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "hw/gtl_hw.h"
|
||||
|
||||
#include "gui/ui_gtl_gui_config_hardware_dialog.h"
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
#include "gui/config/gtl_gui_config_hw_widget.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class GTL_GUI_EXPORT hardware_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit hardware_dialog(QString plugins_path, QWidget *parent = nullptr);
|
||||
~hardware_dialog();
|
||||
|
||||
QString id() const;
|
||||
qreal rate() const;
|
||||
QString type() const;
|
||||
|
||||
hw::device* create_device();
|
||||
hw::device* create_device(QString type);
|
||||
|
||||
int exec(QString type = "");
|
||||
|
||||
private:
|
||||
Ui::config_hardware_dialog _ui;
|
||||
|
||||
gtl::hw::hw _hw;
|
||||
|
||||
private:
|
||||
int get_widget_idex(QString type);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_HARDWARE_DIALOG_H
|
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_hardware_dialog</class>
|
||||
<widget class="QDialog" name="config_hardware_dialog">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>434</width>
|
||||
<height>132</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add hardware</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QStackedWidget" name="stacked_widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ok_button">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>ok_button</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>config_hardware_dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>181</x>
|
||||
<y>87</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>100</x>
|
||||
<y>80</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>pushButton_2</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>config_hardware_dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>235</x>
|
||||
<y>92</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>33</x>
|
||||
<y>71</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -0,0 +1,16 @@
|
|||
#include "gtl_gui_config_hw_widget.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
hw_widget::hw_widget(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef CONFIG_HW_WIDGET_H
|
||||
#define CONFIG_HW_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "hw/gtl_hw.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class hw_widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit hw_widget(QWidget *parent = nullptr);
|
||||
virtual hw::device* create_device() = 0;
|
||||
virtual QString id() = 0;
|
||||
virtual qreal rate() = 0;
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_HW_WIDGET_H
|
|
@ -0,0 +1,91 @@
|
|||
#include "gtl_gui_config_hw_widget_audio.h"
|
||||
#include "ui_gtl_gui_config_hw_widget_audio.h"
|
||||
|
||||
#include "hw/gtl_hw_audio.h"
|
||||
|
||||
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
hw_widget_audio::hw_widget_audio(QWidget *parent)
|
||||
: hw_widget(parent)
|
||||
, ui(new Ui::config_hw_widget_audio)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
_devices = new QMediaDevices(this);
|
||||
|
||||
connect(ui->devices, &QComboBox::currentIndexChanged, this, &hw_widget_audio::device_changed);
|
||||
|
||||
const auto devices = _devices->audioInputs();
|
||||
for (auto &device_info: devices)
|
||||
ui->devices->addItem(device_info.description(), QVariant::fromValue(device_info));
|
||||
}
|
||||
|
||||
hw_widget_audio::~hw_widget_audio()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
hw::device *hw_widget_audio::create_device()
|
||||
{
|
||||
return new gtl::hw::audio(ui->channels->currentData().toInt(), (QAudioFormat::SampleFormat)ui->sample_format->currentData().toInt());
|
||||
}
|
||||
|
||||
QString hw_widget_audio::id()
|
||||
{
|
||||
return ui->devices->currentData().value<QAudioDevice>().id();
|
||||
}
|
||||
|
||||
qreal hw_widget_audio::rate()
|
||||
{
|
||||
return ui->rate->value();
|
||||
}
|
||||
|
||||
void hw_widget_audio::device_changed(int idx)
|
||||
{
|
||||
QAudioDevice device_info = ui->devices->itemData(idx).value<QAudioDevice>();
|
||||
|
||||
|
||||
ui->rate->setMinimum(device_info.minimumSampleRate());
|
||||
ui->rate->setMaximum(device_info.maximumSampleRate());
|
||||
int sampleValue = qBound(device_info.minimumSampleRate(), 48000,
|
||||
device_info.maximumSampleRate());
|
||||
ui->rate->setValue(sampleValue);
|
||||
|
||||
ui->freq_label->setText(
|
||||
tr("Rate") +
|
||||
" (" + QString::number(device_info.minimumSampleRate()) + " - " + QString::number(device_info.maximumSampleRate()) + ") " +
|
||||
":"
|
||||
);
|
||||
|
||||
ui->channels->clear();
|
||||
for(int i = device_info.minimumChannelCount(); i <= device_info.maximumChannelCount(); i++)
|
||||
ui->channels->addItem(QString::number(i), i);
|
||||
|
||||
ui->sample_format->clear();
|
||||
auto sample_formats = device_info.supportedSampleFormats();
|
||||
for(auto sample_format: sample_formats)
|
||||
{
|
||||
QString sample_format_string = tr("Unknown");
|
||||
if(sample_format == QAudioFormat::UInt8)
|
||||
sample_format_string = tr("Unsigned 8 bit");
|
||||
else if(sample_format == QAudioFormat::Int16)
|
||||
sample_format_string = tr("Signed 16 bit");
|
||||
else if(sample_format == QAudioFormat::Int32)
|
||||
sample_format_string = tr("Signed 32 bit");
|
||||
else if(sample_format == QAudioFormat::Float)
|
||||
sample_format_string = tr("Float");
|
||||
|
||||
ui->sample_format->addItem(sample_format_string, sample_format);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef GTL_GUI_CONFIG_HW_WIDGET_AUDIO_H
|
||||
#define GTL_GUI_CONFIG_HW_WIDGET_AUDIO_H
|
||||
|
||||
#include "gtl_gui_config_hw_widget.h"
|
||||
|
||||
#include <QMediaDevices>
|
||||
#include <QAudioDevice>
|
||||
|
||||
namespace Ui {
|
||||
class config_hw_widget_audio;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class hw_widget_audio : public hw_widget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit hw_widget_audio(QWidget *parent = nullptr);
|
||||
~hw_widget_audio();
|
||||
|
||||
protected:
|
||||
virtual hw::device* create_device() override;
|
||||
virtual QString id() override;
|
||||
virtual qreal rate() override;
|
||||
|
||||
private:
|
||||
Ui::config_hw_widget_audio *ui;
|
||||
QMediaDevices *_devices;
|
||||
|
||||
private slots:
|
||||
void device_changed(int);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_HW_WIDGET_AUDIO_H
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_hw_widget_audio</class>
|
||||
<widget class="QWidget" name="config_hw_widget_audio">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>98</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QComboBox" name="devices"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="freq_label">
|
||||
<property name="text">
|
||||
<string>Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="rate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Channels:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="channels"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Sample Format:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="sample_format"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,52 @@
|
|||
#include "gtl_gui_config_hw_widget_dac.h"
|
||||
#include "ui_gtl_gui_config_hw_widget_dac.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
hw_widget_dac::hw_widget_dac(QString plugins_path, QWidget *parent)
|
||||
: hw_widget(parent)
|
||||
, ui(new Ui::config_hw_widget_dac)
|
||||
, _hw(plugins_path)
|
||||
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->type->addItems(_hw.devices());
|
||||
}
|
||||
|
||||
hw_widget_dac::~hw_widget_dac()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void hw_widget_dac::set_type(QString type)
|
||||
{
|
||||
ui->type->setCurrentText(type);
|
||||
}
|
||||
|
||||
QString hw_widget_dac::type() const
|
||||
{
|
||||
return ui->type->currentText();
|
||||
}
|
||||
|
||||
hw::device *hw_widget_dac::create_device()
|
||||
{
|
||||
return _hw.create_device(ui->type->currentText());
|
||||
}
|
||||
|
||||
QString hw_widget_dac::id()
|
||||
{
|
||||
return ui->id->text();
|
||||
}
|
||||
|
||||
qreal hw_widget_dac::rate()
|
||||
{
|
||||
return ui->rate->value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef GTL_GUI_CONFIG_HW_WIDGET_DAC_H
|
||||
#define GTL_GUI_CONFIG_HW_WIDGET_DAC_H
|
||||
|
||||
#include "gtl_gui_config_hw_widget.h"
|
||||
|
||||
#include "hw/gtl_hw.h"
|
||||
|
||||
namespace Ui {
|
||||
class config_hw_widget_dac;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class hw_widget_dac : public hw_widget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit hw_widget_dac(QString plugins_path, QWidget *parent = nullptr);
|
||||
~hw_widget_dac();
|
||||
|
||||
void set_type(QString type);
|
||||
QString type() const;
|
||||
|
||||
protected:
|
||||
virtual hw::device* create_device() override;
|
||||
virtual QString id() override;
|
||||
virtual qreal rate() override;
|
||||
|
||||
private:
|
||||
Ui::config_hw_widget_dac *ui;
|
||||
gtl::hw::hw _hw;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_HW_WIDGET_DAC_H
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_hw_widget_dac</class>
|
||||
<widget class="QWidget" name="config_hw_widget_dac">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>72</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="type_label">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="type"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="id"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="rate_label">
|
||||
<property name="text">
|
||||
<string>Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="rate">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,40 @@
|
|||
#include "gtl_gui_config_hw_widget_generator.h"
|
||||
#include "ui_gtl_gui_config_hw_widget_generator.h"
|
||||
|
||||
#include "hw/gtl_hw_generator.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
hw_widget_generator::hw_widget_generator(QWidget *parent)
|
||||
: hw_widget(parent)
|
||||
, ui(new Ui::config_hw_widget_generator)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
hw_widget_generator::~hw_widget_generator()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
hw::device *hw_widget_generator::create_device()
|
||||
{
|
||||
return new gtl::hw::generator();
|
||||
}
|
||||
|
||||
QString hw_widget_generator::id()
|
||||
{
|
||||
return ui->id->text();
|
||||
}
|
||||
|
||||
qreal hw_widget_generator::rate()
|
||||
{
|
||||
return ui->rate->value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef GTL_GUI_CONFIG_HW_WIDGET_GENERATOR_H
|
||||
#define GTL_GUI_CONFIG_HW_WIDGET_GENERATOR_H
|
||||
|
||||
#include "gtl_gui_config_hw_widget.h"
|
||||
|
||||
namespace Ui {
|
||||
class config_hw_widget_generator;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class hw_widget_generator : public hw_widget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit hw_widget_generator(QWidget *parent = nullptr);
|
||||
~hw_widget_generator();
|
||||
|
||||
protected:
|
||||
virtual hw::device* create_device() override;
|
||||
virtual QString id() override;
|
||||
virtual qreal rate() override;
|
||||
|
||||
private:
|
||||
Ui::config_hw_widget_generator *ui;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_HW_WIDGET_GENERATOR_H
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_hw_widget_generator</class>
|
||||
<widget class="QWidget" name="config_hw_widget_generator">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>48</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="id"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="rate_label">
|
||||
<property name="text">
|
||||
<string>Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="rate">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,320 @@
|
|||
#include "gtl_gui_config_widget.h"
|
||||
|
||||
#include "gtl_gui_config_widget_device.h"
|
||||
#include "gtl_gui_config_widget_analog.h"
|
||||
|
||||
#include "hw/gtl_hw_player.h"
|
||||
|
||||
#include "math/gtl_math_filter_iir.h"
|
||||
#include "math/gtl_math_intg.h"
|
||||
#include "math/gtl_math_diff.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget::widget(gtl::data_model* model, QString hwplugings_path, QWidget *parent)
|
||||
: QWidget{parent}
|
||||
, _model(model)
|
||||
, _hw_dialog(hwplugings_path)
|
||||
, _popup_node(NULL)
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
|
||||
_ui.view->setModel(_model);
|
||||
_ui.view->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(_ui.view, &QWidget::customContextMenuRequested, this, &widget::menu_reques);
|
||||
|
||||
QItemSelectionModel* selection = new QItemSelectionModel(model);
|
||||
_ui.view->setSelectionModel(selection);
|
||||
connect(selection, &QItemSelectionModel::currentChanged, this, &widget::selection_changed);
|
||||
|
||||
|
||||
_add_hardware_action = new QAction(tr("Add hardware"), this);
|
||||
connect(_add_hardware_action, &QAction::triggered, this, &widget::add_hardware);
|
||||
|
||||
_add_generator_action = new QAction(tr("Add virtual generator"), this);
|
||||
connect(_add_generator_action, &QAction::triggered, this, &widget::add_generator);
|
||||
|
||||
_add_audio_action = new QAction(tr("Add audio input device"), this);
|
||||
connect(_add_audio_action, &QAction::triggered, this, &widget::add_audio);
|
||||
|
||||
|
||||
_add_iir_filter_action = new QAction(tr("Add IIR filter"), this);
|
||||
connect(_add_iir_filter_action, &QAction::triggered, this, &widget::add_iir_filter);
|
||||
|
||||
_add_integrator_action = new QAction(tr("Add integrator"), this);
|
||||
connect(_add_integrator_action, &QAction::triggered, this, &widget::add_integrator);
|
||||
|
||||
_add_differentioator_action = new QAction(tr("Add differentiator"), this);
|
||||
connect(_add_differentioator_action, &QAction::triggered, this, &widget::add_differentiator);
|
||||
|
||||
_add_player_action = new QAction(tr("Add player"), this);
|
||||
connect(_add_player_action, &QAction::triggered, this, &widget::add_player);
|
||||
|
||||
_remove_action = new QAction(tr("Remove"), this);
|
||||
connect(_remove_action, &QAction::triggered, this, &widget::remove);
|
||||
|
||||
_set_config_action = new QAction(tr("Set config"), this);
|
||||
connect(_set_config_action, &QAction::triggered, this, &widget::set_config);
|
||||
|
||||
_get_config_action = new QAction(tr("Get config"), this);
|
||||
connect(_get_config_action, &QAction::triggered, this, &widget::get_config);
|
||||
|
||||
connect(_model, >l::data_model::create_node, this, &widget::create_node);
|
||||
|
||||
|
||||
_ui.stackedWidget->addWidget(new widget_device(this));
|
||||
_ui.stackedWidget->addWidget(new widget_analog(this));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void widget::save(QDomElement &root_element)
|
||||
{
|
||||
QDomElement devices_element = root_element.ownerDocument().createElement("devices");
|
||||
root_element.appendChild(devices_element);
|
||||
|
||||
QDomElement splitter_element = root_element.ownerDocument().createElement("splitter");
|
||||
root_element.appendChild(splitter_element);
|
||||
splitter_element.setAttribute("state", QString(_ui.splitter->saveState().toBase64()));
|
||||
|
||||
_model->save(devices_element);
|
||||
}
|
||||
|
||||
void widget::load(const QDomElement &root_element)
|
||||
{
|
||||
clear();
|
||||
|
||||
QDomElement devices_element = root_element.firstChildElement("devices");
|
||||
|
||||
QDomElement splitter_element = root_element.firstChildElement("splitter");
|
||||
_ui.splitter->restoreState(QByteArray::fromBase64(splitter_element.attribute("state", "").toUtf8()));
|
||||
|
||||
_model->load(devices_element);
|
||||
}
|
||||
|
||||
void widget::clear()
|
||||
{
|
||||
_model->clear();
|
||||
for(auto it = _devices.begin(); it != _devices.end(); it++)
|
||||
delete *it;
|
||||
|
||||
_devices.clear();
|
||||
}
|
||||
|
||||
hw::device* widget::add(hw::device *device)
|
||||
{
|
||||
_model->add_device(device->gtl_device());
|
||||
_devices.push_back(device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void widget::menu_reques(const QPoint &pos)
|
||||
{
|
||||
QMenu menu;
|
||||
|
||||
QModelIndex index = _ui.view->indexAt(pos);
|
||||
_popup_node = static_cast<gtl::data_model_node*>(index.internalPointer());
|
||||
if(_popup_node == NULL)
|
||||
{
|
||||
menu.addAction(_add_hardware_action);
|
||||
menu.addAction(_add_generator_action);
|
||||
menu.addAction(_add_audio_action);
|
||||
menu.addAction(_add_player_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_popup_node->type() == gtl::data_model_node::device)
|
||||
{
|
||||
/*
|
||||
menu.addAction(_set_config_action);
|
||||
menu.addAction(_get_config_action);
|
||||
menu.addSeparator();
|
||||
*/
|
||||
menu.addAction(_remove_action);
|
||||
}
|
||||
else if(_popup_node->type() == gtl::data_model_node::analog)
|
||||
{
|
||||
menu.addAction(_add_iir_filter_action);
|
||||
menu.addAction(_add_integrator_action);
|
||||
menu.addAction(_add_differentioator_action);
|
||||
|
||||
if(_popup_node->parent_node()->type() != gtl::data_model_node::device)
|
||||
{
|
||||
menu.addSeparator();
|
||||
menu.addAction(_remove_action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu.exec(_ui.view->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void widget::add_hardware()
|
||||
{
|
||||
_hw_dialog.setWindowTitle(tr("Add hardware"));
|
||||
if(_hw_dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
if(std::find_if(_devices.begin(), _devices.end(), [=](gtl::hw::device* d){return d->gtl_device()->device_type() == _hw_dialog.type() && d->gtl_device()->id() == _hw_dialog.id();}) == _devices.end())
|
||||
{
|
||||
add(_hw_dialog.create_device())->start(_hw_dialog.id(), _hw_dialog.rate());
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox(QMessageBox::Icon::Warning, tr("Add device"), tr("Such device already exists.")).exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void widget::add_generator()
|
||||
{
|
||||
_hw_dialog.setWindowTitle(tr("Add generator"));
|
||||
if(_hw_dialog.exec("generator") == QDialog::Accepted)
|
||||
{
|
||||
add(_hw_dialog.create_device("generator"))->start(_hw_dialog.id(), _hw_dialog.rate());
|
||||
}
|
||||
}
|
||||
|
||||
void widget::add_audio()
|
||||
{
|
||||
_hw_dialog.setWindowTitle(tr("Add audio input device"));
|
||||
if(_hw_dialog.exec("audio") == QDialog::Accepted)
|
||||
{
|
||||
add(_hw_dialog.create_device("audio"))->start(_hw_dialog.id(), _hw_dialog.rate());
|
||||
}
|
||||
}
|
||||
|
||||
void widget::add_iir_filter()
|
||||
{
|
||||
new gtl::math::filter_iir(static_cast<gtl::analog_data*>(_popup_node));
|
||||
}
|
||||
|
||||
void widget::add_integrator()
|
||||
{
|
||||
new gtl::math::intg(static_cast<gtl::analog_data*>(_popup_node));
|
||||
}
|
||||
|
||||
void widget::add_differentiator()
|
||||
{
|
||||
new gtl::math::diff(static_cast<gtl::analog_data*>(_popup_node));
|
||||
}
|
||||
|
||||
void widget::add_player()
|
||||
{
|
||||
/*
|
||||
_hw_dialog.setWindowTitle(tr("Add player"));
|
||||
if(_hw_dialog.exec("player") == QDialog::Accepted)
|
||||
{
|
||||
add(_hw_dialog.create_device("player"))->start("", 0);
|
||||
}
|
||||
*/
|
||||
|
||||
add(new gtl::hw::player())->start("", 0);
|
||||
}
|
||||
|
||||
void widget::remove()
|
||||
{
|
||||
//_model->remove(_popup_node);
|
||||
|
||||
|
||||
auto iter_device = std::find_if(_devices.begin(), _devices.end(), [=](const gtl::hw::device* d){return d->gtl_device() == _popup_node;});
|
||||
if(iter_device != _devices.end())
|
||||
{
|
||||
delete *iter_device;
|
||||
_devices.erase(iter_device);
|
||||
}
|
||||
else
|
||||
delete _popup_node;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void widget::set_config()
|
||||
{
|
||||
auto iter_device = std::find_if(_devices.begin(), _devices.end(), [=](const gtl::hw::device* d){return d->gtl_device() == _popup_node;});
|
||||
|
||||
if(iter_device == _devices.end())
|
||||
return;
|
||||
|
||||
QJsonDocument config = QJsonDocument::fromJson(QApplication::clipboard()->text().toUtf8());
|
||||
|
||||
if(config.isObject())
|
||||
(*iter_device)->set_config(config.object());
|
||||
else if(config.isArray())
|
||||
(*iter_device)->set_config(config.array());
|
||||
}
|
||||
|
||||
void widget::get_config()
|
||||
{
|
||||
auto iter_device = std::find_if(_devices.begin(), _devices.end(), [=](const gtl::hw::device* d){return d->gtl_device() == _popup_node;});
|
||||
|
||||
if(iter_device == _devices.end())
|
||||
return;
|
||||
|
||||
QByteArray data;
|
||||
if((*iter_device)->config().isObject())
|
||||
data = QJsonDocument((*iter_device)->config().toObject()).toJson();
|
||||
else
|
||||
data = QJsonDocument((*iter_device)->config().toArray()).toJson();
|
||||
|
||||
QApplication::clipboard()->setText(QString(data));
|
||||
|
||||
}
|
||||
|
||||
gtl::data_model_node* widget::create_node(gtl::data_model_node* parent, QDomElement &node_element)
|
||||
{
|
||||
gtl::data_model_node* node = NULL;
|
||||
|
||||
if(node_element.attribute("node", "") == "gtl::device")
|
||||
{
|
||||
QString type = node_element.attribute("type", "");
|
||||
|
||||
gtl::hw::device* d = NULL;
|
||||
if(type == "player")
|
||||
d = new gtl::hw::player();
|
||||
else
|
||||
d = _hw_dialog.create_device(type);
|
||||
|
||||
if(d)
|
||||
{
|
||||
node = d->gtl_device();
|
||||
_devices.push_back(d);
|
||||
}
|
||||
}
|
||||
else if(node_element.attribute("node", "") == "gtl::math::filter_iir")
|
||||
{
|
||||
node = new gtl::math::filter_iir(static_cast<gtl::analog_data*>(parent));
|
||||
}
|
||||
else if(node_element.attribute("node", "") == "gtl::math::intg")
|
||||
{
|
||||
node = new gtl::math::intg(static_cast<gtl::analog_data*>(parent));
|
||||
}
|
||||
else if(node_element.attribute("node", "") == "gtl::math::diff")
|
||||
{
|
||||
node = new gtl::math::diff(static_cast<gtl::analog_data*>(parent));
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void widget::selection_changed(const QModelIndex ¤t, const QModelIndex&)
|
||||
{
|
||||
if(!current.isValid())
|
||||
{
|
||||
_ui.stackedWidget->setCurrentIndex(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
gtl::data_model_node* node = static_cast<gtl::data_model_node*>(current.internalPointer());
|
||||
|
||||
static_cast<widget_node*>(_ui.stackedWidget->widget(node->type()))->set_node(node);
|
||||
_ui.stackedWidget->setCurrentIndex(node->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#ifndef CONFIG_WIDGET_H
|
||||
#define CONFIG_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMenu>
|
||||
#include <QDomElement>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "core/gtl_data_model.h"
|
||||
#include "hw/gtl_hw_device.h"
|
||||
|
||||
#include "gui/config/gtl_gui_config_hardware_dialog.h"
|
||||
#include "gui/ui_gtl_gui_config_widget.h"
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class GTL_GUI_EXPORT widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit widget(gtl::data_model* model, QString hwplugings_path, QWidget *parent = nullptr);
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
Ui::config_widget _ui;
|
||||
|
||||
gtl::data_model* _model;
|
||||
|
||||
QAction* _add_hardware_action;
|
||||
QAction* _add_generator_action;
|
||||
QAction* _add_player_action;
|
||||
QAction* _add_audio_action;
|
||||
|
||||
QAction* _add_iir_filter_action;
|
||||
QAction* _add_integrator_action;
|
||||
QAction* _add_differentioator_action;
|
||||
|
||||
QAction* _remove_action;
|
||||
QAction* _set_config_action;
|
||||
QAction* _get_config_action;
|
||||
|
||||
|
||||
QList<gtl::hw::device*> _devices;
|
||||
|
||||
gtl::gui::config::hardware_dialog _hw_dialog;
|
||||
|
||||
gtl::data_model_node* _popup_node;
|
||||
|
||||
private:
|
||||
hw::device* add(gtl::hw::device* device);
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
void menu_reques(const QPoint &pos);
|
||||
void add_hardware();
|
||||
void add_generator();
|
||||
void add_audio();
|
||||
void add_iir_filter();
|
||||
void add_integrator();
|
||||
void add_differentiator();
|
||||
void add_player();
|
||||
void remove();
|
||||
void set_config();
|
||||
void get_config();
|
||||
|
||||
gtl::data_model_node* create_node(gtl::data_model_node* parent, QDomElement& device_element);
|
||||
void selection_changed(const QModelIndex ¤t, const QModelIndex &prev);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_WIDGET_H
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_widget</class>
|
||||
<widget class="QWidget" name="config_widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="view">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<widget class="QWidget" name="page_2"/>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,297 @@
|
|||
|
||||
#include <QSizePolicy>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "gtl_gui_config_widget_analog.h"
|
||||
#include "ui_gtl_gui_config_widget_analog.h"
|
||||
|
||||
#include "hw/gtl_analog_input.h"
|
||||
#include "hw/gtl_hw_generator_analog_input.h"
|
||||
#include "hw/gtl_hw_player_analog_input.h"
|
||||
#include "math/gtl_math_intg.h"
|
||||
#include "math/gtl_math_diff.h"
|
||||
#include "gui/gtl_gui_chart_widget.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget_analog::widget_analog(QWidget *parent) :
|
||||
widget_node(parent),
|
||||
ui(new Ui::config_widget_analog),
|
||||
_filter_info(new gtl::math::filter_iir_info())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
_color = new color_box(this);
|
||||
_color->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
|
||||
ui->color_layout->setWidget(0, QFormLayout::ItemRole::FieldRole, _color);
|
||||
|
||||
_filter_response_chart = new config::filter_response_chart(this);
|
||||
ui->page_3->layout()->addWidget(new gtl::gui::chart_widget(_filter_response_chart));
|
||||
}
|
||||
|
||||
widget_analog::~widget_analog()
|
||||
{
|
||||
delete ui;
|
||||
delete _filter_info;
|
||||
}
|
||||
|
||||
void widget_analog::set_node(data_model_node *node)
|
||||
{
|
||||
_color->disconnect();
|
||||
_color->set_color(static_cast<gtl::analog_data*>(node)->color());
|
||||
connect(_color, &color_box::icolor_changed, static_cast<gtl::analog_data*>(node), >l::analog_data::set_color);
|
||||
|
||||
QString class_name(node->metaObject()->className());
|
||||
if(class_name == "gtl::hw::analog_input")
|
||||
{
|
||||
gtl::hw::analog_input* input = static_cast<gtl::hw::analog_input*>(node);
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
|
||||
ui->sensitivity->disconnect();
|
||||
ui->sensitivity->setValue(input->sensitivity());
|
||||
connect(ui->sensitivity, &QDoubleSpinBox::valueChanged, input, >l::hw::analog_input::set_sensitivity);
|
||||
|
||||
ui->gain->disconnect();
|
||||
ui->gain->setValue(input->gain());
|
||||
connect(ui->gain, &QDoubleSpinBox::valueChanged, input, >l::hw::analog_input::set_gain);
|
||||
|
||||
ui->offset->disconnect();
|
||||
ui->offset->setValue(input->offset());
|
||||
connect(ui->offset, &QDoubleSpinBox::valueChanged, input, >l::hw::analog_input::set_offset);
|
||||
|
||||
ui->reference->disconnect();
|
||||
ui->reference->setValue(input->reference());
|
||||
connect(ui->reference, &QDoubleSpinBox::valueChanged, input, >l::hw::analog_input::set_reference);
|
||||
|
||||
ui->iepe->disconnect();
|
||||
ui->iepe->setChecked(input->is_iepe());
|
||||
connect(ui->iepe, &QCheckBox::stateChanged, input, >l::hw::analog_input::set_iepe);
|
||||
|
||||
ui->coupling->disconnect();
|
||||
ui->coupling->setCurrentIndex(input->is_coupling());
|
||||
connect(ui->coupling, &QComboBox::currentIndexChanged, input, >l::hw::analog_input::set_coupling);
|
||||
|
||||
ui->inverse->disconnect();
|
||||
ui->inverse->setChecked(input->is_inverting());
|
||||
connect(ui->inverse, &QCheckBox::stateChanged, input, >l::hw::analog_input::set_inverting);
|
||||
}
|
||||
else if(class_name == "gtl::hw::generator_analog_input")
|
||||
{
|
||||
gtl::hw::generator_analog_input* input = static_cast<gtl::hw::generator_analog_input*>(node);
|
||||
ui->stackedWidget->setCurrentIndex(1);
|
||||
|
||||
ui->freq->disconnect();
|
||||
ui->freq->setValue(input->freq());
|
||||
connect(ui->freq, &QDoubleSpinBox::valueChanged, input, >l::hw::generator_analog_input::set_freq);
|
||||
|
||||
ui->phase->disconnect();
|
||||
ui->phase->setValue(input->phase());
|
||||
connect(ui->phase, &QDoubleSpinBox::valueChanged, input, >l::hw::generator_analog_input::set_phase);
|
||||
|
||||
}
|
||||
else if(class_name == "gtl::math::filter_iir")
|
||||
{
|
||||
_filter = static_cast<gtl::math::filter_iir*>(node);
|
||||
|
||||
ui->stackedWidget->setCurrentIndex(2);
|
||||
|
||||
ui->filter_frequency->disconnect();
|
||||
ui->filter_frequency->setValue(_filter->frequency());
|
||||
connect(ui->filter_frequency, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_frequency);
|
||||
|
||||
ui->filter_order->disconnect();
|
||||
ui->filter_order->setValue(_filter->order());
|
||||
connect(ui->filter_order, &QSpinBox::valueChanged, _filter, >l::math::filter_iir::set_order);
|
||||
|
||||
ui->filter_gain->disconnect();
|
||||
ui->filter_gain->setValue(_filter->gain());
|
||||
connect(ui->filter_gain, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_gain);
|
||||
|
||||
ui->filter_width->disconnect();
|
||||
ui->filter_width->setValue(_filter->width());
|
||||
connect(ui->filter_width, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_width);
|
||||
|
||||
ui->filter_slope->disconnect();
|
||||
ui->filter_slope->setValue(_filter->slope());
|
||||
connect(ui->filter_slope, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_slope);
|
||||
|
||||
ui->filter_q->disconnect();
|
||||
ui->filter_q->setValue(_filter->q());
|
||||
connect(ui->filter_q, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_q);
|
||||
|
||||
ui->filter_ripple->disconnect();
|
||||
ui->filter_ripple->setValue(_filter->ripple());
|
||||
connect(ui->filter_ripple, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_ripple);
|
||||
|
||||
ui->filter_stop->disconnect();
|
||||
ui->filter_stop->setValue(_filter->stop());
|
||||
connect(ui->filter_stop, &QDoubleSpinBox::valueChanged, _filter, >l::math::filter_iir::set_stop);
|
||||
|
||||
/// set kind ///
|
||||
ui->filter_kind->disconnect();
|
||||
ui->filter_kind->clear();
|
||||
|
||||
for (QDomNode dom = _filter_info->info().firstChild();
|
||||
!dom.isNull();
|
||||
dom = dom.nextSibling())
|
||||
{
|
||||
if (dom.isElement())
|
||||
{
|
||||
ui->filter_kind->addItem(dom.nodeName());
|
||||
if( _filter->kind() == _filter_info->kind(dom.nodeName()))
|
||||
ui->filter_kind->setCurrentIndex(ui->filter_kind->count() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
connect(ui->filter_kind, &QComboBox::currentIndexChanged, this, &widget_analog::filter_kind_changed);
|
||||
filter_kind_changed();
|
||||
|
||||
|
||||
_filter_response_chart->set_filter(_filter);
|
||||
///////////////
|
||||
}
|
||||
else if(class_name == "gtl::math::intg")
|
||||
{
|
||||
gtl::math::intg* intg = static_cast<gtl::math::intg*>(node);
|
||||
ui->stackedWidget->setCurrentIndex(3);
|
||||
|
||||
ui->intg_taps->disconnect();
|
||||
ui->intg_taps->setValue(intg->taps());
|
||||
connect(ui->intg_taps, &QSpinBox::valueChanged, intg, >l::math::intg::set_taps);
|
||||
|
||||
}
|
||||
else if(class_name == "gtl::math::diff")
|
||||
{
|
||||
gtl::math::diff* diff = static_cast<gtl::math::diff*>(node);
|
||||
ui->stackedWidget->setCurrentIndex(4);
|
||||
|
||||
ui->diff_taps->disconnect();
|
||||
ui->diff_taps->setValue(diff->taps());
|
||||
connect(ui->diff_taps, &QSpinBox::valueChanged, diff, >l::math::diff::set_taps);
|
||||
}
|
||||
else if(class_name == "gtl::hw::player_analog_input")
|
||||
{
|
||||
ui->player_analog_input_info->setPlainText(QJsonDocument(static_cast<gtl::hw::player_analog_input*>(node)->info()).toJson());
|
||||
ui->stackedWidget->setCurrentIndex(5);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void widget_analog::set_color_visible(bool value)
|
||||
{
|
||||
ui->color_label->setVisible(value);
|
||||
_color->setVisible(value);
|
||||
}
|
||||
|
||||
void widget_analog::filter_kind_changed()
|
||||
{
|
||||
if(_filter)
|
||||
{
|
||||
QString name = ui->filter_kind->currentText();
|
||||
|
||||
ui->filter_type->disconnect();
|
||||
ui->filter_type->clear();
|
||||
|
||||
QDomNode kind = _filter_info->info().namedItem(name);
|
||||
for (QDomNode type = kind.firstChild();
|
||||
!type.isNull();
|
||||
type = type.nextSibling())
|
||||
{
|
||||
if (type.isElement())
|
||||
{
|
||||
ui->filter_type->addItem(type.nodeName());
|
||||
if(_filter_info->type(type.nodeName()) == _filter->type())
|
||||
ui->filter_type->setCurrentIndex(ui->filter_type->count() - 1);
|
||||
}
|
||||
}
|
||||
_filter->set_kind(_filter_info->kind(name));
|
||||
}
|
||||
|
||||
connect(ui->filter_type, &QComboBox::currentIndexChanged, this, &widget_analog::filter_type_changed);
|
||||
filter_type_changed();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void widget_analog::filter_type_changed()
|
||||
{
|
||||
if(_filter)
|
||||
{
|
||||
filter_show_property("none");
|
||||
QDomNode kind = _filter_info->info().namedItem(ui->filter_kind->currentText());
|
||||
QDomElement type = kind.namedItem(ui->filter_type->currentText()).toElement();
|
||||
|
||||
if(type.hasAttributes())
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
QString prop = type.attribute(QString::number(i));
|
||||
if(prop != "")
|
||||
filter_show_property(prop);
|
||||
else
|
||||
break;
|
||||
}
|
||||
_filter->set_type(_filter_info->type(ui->filter_type->currentText()));
|
||||
}
|
||||
}
|
||||
|
||||
void widget_analog::filter_show_property(QString property)
|
||||
{
|
||||
if(property == QString("gain"))
|
||||
{
|
||||
ui->filter_gain_label->setVisible(true);
|
||||
ui->filter_gain->setVisible(true);
|
||||
ui->filter_gain->setValue(_filter->gain());
|
||||
}
|
||||
else if(property == QString("q"))
|
||||
{
|
||||
ui->filter_q_label->setVisible(true);
|
||||
ui->filter_q->setVisible(true);
|
||||
ui->filter_q->setValue(_filter->q());
|
||||
}
|
||||
else if(property == QString("ripple"))
|
||||
{
|
||||
ui->filter_ripple_label->setVisible(true);
|
||||
ui->filter_ripple->setVisible(true);
|
||||
ui->filter_ripple->setValue(_filter->ripple());
|
||||
}
|
||||
else if(property == QString("slope"))
|
||||
{
|
||||
ui->filter_slope_label->setVisible(true);
|
||||
ui->filter_slope->setVisible(true);
|
||||
ui->filter_slope->setValue(_filter->slope());
|
||||
}
|
||||
else if(property == QString("stop"))
|
||||
{
|
||||
ui->filter_stop_label->setVisible(true);
|
||||
ui->filter_stop->setVisible(true);
|
||||
ui->filter_stop->setValue(_filter->stop());
|
||||
}
|
||||
else if(property == QString("width"))
|
||||
{
|
||||
ui->filter_width_label->setVisible(true);
|
||||
ui->filter_width->setVisible(true);
|
||||
ui->filter_width->setValue(_filter->width());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->filter_gain_label->setVisible(false);
|
||||
ui->filter_gain->setVisible(false);
|
||||
ui->filter_q_label->setVisible(false);
|
||||
ui->filter_q->setVisible(false);
|
||||
ui->filter_ripple_label->setVisible(false);
|
||||
ui->filter_ripple->setVisible(false);
|
||||
ui->filter_slope_label->setVisible(false);
|
||||
ui->filter_slope->setVisible(false);
|
||||
ui->filter_stop_label->setVisible(false);
|
||||
ui->filter_stop->setVisible(false);
|
||||
ui->filter_width_label->setVisible(false);
|
||||
ui->filter_width->setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef GTL_GUI_CONFIG_WIDGET_ANALOG_H
|
||||
#define GTL_GUI_CONFIG_WIDGET_ANALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "gui/gtl_gui_color_box.h"
|
||||
#include "gui/config/gtl_gui_config_filter_response_chart.h"
|
||||
#include "gtl_gui_config_widget_node.h"
|
||||
#include "math/gtl_math_filter_iir.h"
|
||||
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
namespace Ui {
|
||||
class config_widget_analog;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class GTL_GUI_EXPORT widget_analog : public widget_node
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit widget_analog(QWidget *parent = nullptr);
|
||||
~widget_analog();
|
||||
|
||||
virtual void set_node(gtl::data_model_node* node) override;
|
||||
|
||||
void set_color_visible(bool value);
|
||||
|
||||
private slots:
|
||||
void filter_kind_changed();
|
||||
void filter_type_changed();
|
||||
//
|
||||
|
||||
private:
|
||||
Ui::config_widget_analog *ui;
|
||||
color_box* _color;
|
||||
config::filter_response_chart* _filter_response_chart;
|
||||
|
||||
private:
|
||||
gtl::math::filter_iir *_filter;
|
||||
gtl::math::filter_iir_info *_filter_info;
|
||||
void filter_show_property(QString property);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // GTL_GUI_CONFIG_WIDGET_ANALOG_H
|
|
@ -0,0 +1,723 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_widget_analog</class>
|
||||
<widget class="QWidget" name="config_widget_analog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>488</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="color_layout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="rowWrapPolicy">
|
||||
<enum>QFormLayout::DontWrapRows</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="color_label">
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Sensitivity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="sensitivity">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="gain">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="offset">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="reference">
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="inverse_label">
|
||||
<property name="text">
|
||||
<string>Inverse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="inverse">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="iepe_label">
|
||||
<property name="text">
|
||||
<string>IEPE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="iepe">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_coupling">
|
||||
<property name="text">
|
||||
<string>Coupling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="coupling">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AC/DC</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AC</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Signal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="signal_type">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sin</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="freq">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Phase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="phase">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="filter_kind_label">
|
||||
<property name="text">
|
||||
<string>Kind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="filter_kind"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="filter_type_label">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="filter_type"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="filter_order_label">
|
||||
<property name="text">
|
||||
<string>Order</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="filter_order">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="filter_frequency_label">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_frequency">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="filter_gain_label">
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_gain">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="filter_width_label">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_width">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="filter_ripple_label">
|
||||
<property name="text">
|
||||
<string>Ripple</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_ripple">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="filter_stop_label">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_stop">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="filter_q_label">
|
||||
<property name="text">
|
||||
<string>Q</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_q">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="filter_slope_label">
|
||||
<property name="text">
|
||||
<string>Slope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QDoubleSpinBox" name="filter_slope">
|
||||
<property name="minimum">
|
||||
<double>-100.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_4">
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="tapsLabel">
|
||||
<property name="text">
|
||||
<string>Taps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="intg_taps">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_5">
|
||||
<layout class="QFormLayout" name="formLayout_8">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="tapsLabel_2">
|
||||
<property name="text">
|
||||
<string>Taps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="diff_taps">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_6">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="player_analog_input_info">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="lineWrapMode">
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,49 @@
|
|||
#include "gtl_gui_config_widget_device.h"
|
||||
#include "ui_gtl_gui_config_widget_device.h"
|
||||
|
||||
|
||||
#include "core/gtl_device.h"
|
||||
#include "gui/config/gtl_gui_config_widget_player.h"
|
||||
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget_device::widget_device(QWidget *parent) :
|
||||
widget_node(parent),
|
||||
ui(new Ui::config_widget_device)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
_indices.insert(std::map<QString, int>::value_type("player", ui->stackedWidget->addWidget(new widget_player(this))));
|
||||
}
|
||||
|
||||
widget_device::~widget_device()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void widget_device::set_node(data_model_node *node)
|
||||
{
|
||||
if(QString(node->metaObject()->className()) != "gtl::device")
|
||||
{
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
}
|
||||
if(static_cast<gtl::device*>(node)->device_type() == "player")
|
||||
{
|
||||
static_cast<widget_player*>(ui->stackedWidget->widget(_indices["player"]))->set_player(static_cast<gtl::device*>(node));
|
||||
ui->stackedWidget->setCurrentIndex(_indices["player"]);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->stackedWidget->setCurrentIndex(1);
|
||||
ui->id->setText(static_cast<gtl::device*>(node)->id());
|
||||
ui->rate->setValue(static_cast<gtl::device*>(node)->rate());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef GTL_GUI_CONFIG_WIDGET_DEVICE_H
|
||||
#define GTL_GUI_CONFIG_WIDGET_DEVICE_H
|
||||
|
||||
#include "gtl_gui_config_widget_node.h"
|
||||
|
||||
namespace Ui {
|
||||
class config_widget_device;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class widget_device : public widget_node
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit widget_device(QWidget *parent = nullptr);
|
||||
~widget_device();
|
||||
|
||||
virtual void set_node(gtl::data_model_node* node) override;
|
||||
|
||||
private:
|
||||
Ui::config_widget_device *ui;
|
||||
std::map<QString, int> _indices;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_WIDGET_DEVICE_H
|
|
@ -0,0 +1,150 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_widget_device</class>
|
||||
<widget class="QWidget" name="config_widget_device">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>389</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_3"/>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="id">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="rate">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,16 @@
|
|||
#include "gtl_gui_config_widget_node.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget_node::widget_node(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef CONFIG_WIDGET_NODE_H
|
||||
#define CONFIG_WIDGET_NODE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "core/gtl_data_model_node.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class widget_node : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit widget_node(QWidget *parent = nullptr);
|
||||
|
||||
virtual void set_node(gtl::data_model_node* node) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_WIDGET_NODE_H
|
|
@ -0,0 +1,247 @@
|
|||
#include "gtl_gui_config_widget_player.h"
|
||||
#include "ui_gtl_gui_config_widget_player.h"
|
||||
|
||||
#include "gui/gtl_gui_chart_widget.h"
|
||||
#include "gui/player/gtl_gui_player_resampling_dialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QSettings>
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget_player::widget_player(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::config_widget_player)
|
||||
, _files(this)
|
||||
, _selection(&_files)
|
||||
, _player(NULL)
|
||||
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->play->setEnabled(false);
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout(ui->progress);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(ui->time);
|
||||
ui->progress->setLayout(layout);
|
||||
|
||||
|
||||
_files.setNameFilterDisables(false);
|
||||
_files.setNameFilters(QStringList() << "*.gtr" << "*.wav");
|
||||
_files.setFilter(QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
ui->files->setModel(&_files);
|
||||
ui->files->setSelectionModel(&_selection);
|
||||
|
||||
connect(&_selection, &QItemSelectionModel::currentChanged, this, &widget_player::selection_changed);
|
||||
|
||||
ui->files->setRootIndex(_files.setRootPath(""));
|
||||
ui->files->setSortingEnabled(true);
|
||||
ui->files->header()->setSectionsClickable(true);
|
||||
ui->files->header()->setSortIndicatorShown(true);
|
||||
ui->files->header()->setSortIndicator(0, Qt::SortOrder::AscendingOrder);
|
||||
|
||||
connect(ui->play, &QAbstractButton::clicked, this, &widget_player::play);
|
||||
connect(ui->cyclic, &QAbstractButton::clicked, this, &widget_player::set_cyclic);
|
||||
|
||||
_chart = new player::chart(this);
|
||||
chart_widget *chart_widget_ = new chart_widget(_chart, this);
|
||||
ui->verticalLayout->insertWidget(0, chart_widget_);
|
||||
|
||||
connect(&_timer, &QTimer::timeout, this, &widget_player::update_state);
|
||||
|
||||
_timer.start(100);
|
||||
|
||||
connect(ui->save_as_button, &QAbstractButton::clicked, this, &widget_player::save_as);
|
||||
|
||||
ui->path->setClearButtonEnabled(true);
|
||||
ui->path->setPlaceholderText("Root dir ...");
|
||||
|
||||
connect(ui->select_path_button, &QAbstractButton::clicked, this, &widget_player::select_path);
|
||||
connect(ui->path, &QLineEdit::textChanged, this, &widget_player::set_path);
|
||||
|
||||
QSettings settings;
|
||||
ui->splitter->restoreState(settings.value("player/splitter").toByteArray());
|
||||
QList<QVariant> columns_width = settings.value("player/view/columns").toList();
|
||||
for(int i = 0; i < qMin(columns_width.count(), _files.columnCount()); i++)
|
||||
ui->files->setColumnWidth(i, columns_width[i].toInt());
|
||||
|
||||
}
|
||||
|
||||
widget_player::~widget_player()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
settings.setValue("player/splitter", QVariant(ui->splitter->saveState()));
|
||||
QList<QVariant> columns_width;
|
||||
for(int i = 0; i < _files.columnCount(); i++)
|
||||
columns_width.push_back(ui->files->columnWidth(i));
|
||||
settings.setValue("player/view/columns", QVariant(columns_width));
|
||||
|
||||
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void widget_player::set_player(gtl::device *node)
|
||||
{
|
||||
|
||||
if(_player)
|
||||
{
|
||||
_to_save = false;
|
||||
save_player_state();
|
||||
disconnect(_player, NULL, this, NULL);
|
||||
}
|
||||
|
||||
_to_save = true;
|
||||
|
||||
_player = node;
|
||||
|
||||
ui->cyclic->setChecked(_player->get_parameter(2).toBool());
|
||||
|
||||
connect(_player, >l::device::stopped, this, &widget_player::player_stopped);
|
||||
|
||||
ui->files->clearSelection();
|
||||
|
||||
QModelIndex index;
|
||||
if(_player)
|
||||
index = _files.index(node->id());
|
||||
|
||||
_selection.setCurrentIndex(index, QItemSelectionModel::Select);
|
||||
|
||||
ui->path->setText(QSettings().value("player/root_path/" + get_player_uuid()).toString());
|
||||
|
||||
}
|
||||
|
||||
void widget_player::save_player_state()
|
||||
{
|
||||
if(_player)
|
||||
{
|
||||
QDomDocument state_doc;
|
||||
QDomElement player_element = state_doc.createElement("root");
|
||||
state_doc.appendChild(player_element);
|
||||
_player->save_childs(player_element);
|
||||
QFile file(_player->id() + ".conf");
|
||||
if(file.open(QFile::WriteOnly))
|
||||
{
|
||||
file.write(state_doc.toByteArray());
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString widget_player::get_player_uuid() const
|
||||
{
|
||||
if(_player == nullptr)
|
||||
return "";
|
||||
|
||||
return _player->get_parameter(7).toString();
|
||||
}
|
||||
|
||||
void widget_player::selection_changed(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
{
|
||||
QString path = _files.filePath(current);
|
||||
|
||||
if(_player)
|
||||
{
|
||||
if(_to_save)
|
||||
save_player_state();
|
||||
|
||||
|
||||
_player->start(path, -1);
|
||||
qreal total_time = _player->get_parameter(0).toDouble();
|
||||
|
||||
ui->play->setEnabled(total_time != 0);
|
||||
ui->cyclic->setEnabled(total_time != 0);
|
||||
ui->progress->setMaximum(qRound(total_time*1000));
|
||||
|
||||
QFile file(path + ".conf");
|
||||
if(file.open(QFile::ReadOnly))
|
||||
{
|
||||
QDomDocument state_doc;
|
||||
state_doc.setContent(&file);
|
||||
file.close();
|
||||
|
||||
_player->load_childs(state_doc.firstChildElement("root"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
_chart->set_file(path);
|
||||
|
||||
ui->play->setChecked(false);
|
||||
}
|
||||
|
||||
void widget_player::play(bool value)
|
||||
{
|
||||
if(value)
|
||||
{
|
||||
_chart->save_ranges();
|
||||
_player->start(_files.filePath(ui->files->currentIndex()), 0);
|
||||
ui->progress->setMaximum(qRound(_player->get_parameter(0).toDouble()*1000));
|
||||
}
|
||||
else
|
||||
_player->stop();
|
||||
}
|
||||
|
||||
void widget_player::set_cyclic(bool value)
|
||||
{
|
||||
_player->set_parameter(2, value);
|
||||
}
|
||||
|
||||
void widget_player::save_as()
|
||||
{
|
||||
gtl::gui::player::resampling_dialog* save_as_dialog = new gtl::gui::player::resampling_dialog(_player->id(), this);
|
||||
|
||||
save_as_dialog->exec();
|
||||
|
||||
delete save_as_dialog;
|
||||
}
|
||||
|
||||
void widget_player::player_stopped()
|
||||
{
|
||||
qDebug() << "player stopped";
|
||||
ui->play->setChecked(false);
|
||||
}
|
||||
|
||||
void widget_player::update_state()
|
||||
{
|
||||
if(_player)
|
||||
{
|
||||
qreal time = _player->get_parameter(1).toDouble();
|
||||
ui->time->setText(QString::number(time, 'f', 3) + "/" + QString::number(ui->progress->maximum()/1000.0, 'f', 3));
|
||||
ui->progress->setValue(qRound(time*1000));
|
||||
_chart->set_position(_player->get_parameter(6).toDouble());
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->time->setText("");
|
||||
}
|
||||
}
|
||||
|
||||
void widget_player::select_path()
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Select root path"), ui->path->text());
|
||||
if(path.isEmpty())
|
||||
return;
|
||||
|
||||
ui->path->setText(path);
|
||||
}
|
||||
|
||||
void widget_player::set_path(QString path)
|
||||
{
|
||||
QString current_path = _files.filePath(ui->files->currentIndex()).toLower();
|
||||
ui->files->setRootIndex(_files.index(path));
|
||||
QSettings().setValue("player/root_path/" + get_player_uuid(), path);
|
||||
if(!current_path.contains(path.toLower()))
|
||||
{
|
||||
ui->files->setCurrentIndex(ui->files->rootIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef GTL_GUI_CONFIG_WIDGET_PLAYER_H
|
||||
#define GTL_GUI_CONFIG_WIDGET_PLAYER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QTimer>
|
||||
|
||||
#include "core/gtl_device.h"
|
||||
#include "gui/config/gtl_gui_config_widget_player_files.h"
|
||||
#include "gui/player/gtl_gui_player_chart.h"
|
||||
|
||||
namespace Ui {
|
||||
class config_widget_player;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class widget_player : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit widget_player(QWidget *parent = nullptr);
|
||||
~widget_player();
|
||||
|
||||
void set_player(gtl::device* node);
|
||||
|
||||
private:
|
||||
Ui::config_widget_player *ui;
|
||||
|
||||
widget_player_files _files;
|
||||
QItemSelectionModel _selection;
|
||||
|
||||
gtl::device* _player;
|
||||
player::chart *_chart;
|
||||
|
||||
QTimer _timer;
|
||||
|
||||
bool _to_save;
|
||||
|
||||
private:
|
||||
void save_player_state();
|
||||
QString get_player_uuid() const;
|
||||
|
||||
|
||||
private slots:
|
||||
void selection_changed(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void play(bool value);
|
||||
void set_cyclic(bool value);
|
||||
void save_as();
|
||||
|
||||
void player_stopped();
|
||||
|
||||
void update_state();
|
||||
|
||||
void select_path();
|
||||
void set_path(QString path);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_WIDGET_PLAYER_H
|
|
@ -0,0 +1,192 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>config_widget_player</class>
|
||||
<widget class="QWidget" name="config_widget_player">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="path">
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="select_path_button">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="files"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QToolButton" name="save_as_button">
|
||||
<property name="toolTip">
|
||||
<string>Save as</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../gui.qrc">
|
||||
<normaloff>:/player/resources/save_32.png</normaloff>:/player/resources/save_32.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::DelayedPopup</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="time">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progress">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="cyclic">
|
||||
<property name="toolTip">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../gui.qrc">
|
||||
<normaloff>:/player/resources/REFRESH.png</normaloff>:/player/resources/REFRESH.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::DelayedPopup</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="play">
|
||||
<property name="toolTip">
|
||||
<string>Play/Pause</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../gui.qrc">
|
||||
<normaloff>:/player/play</normaloff>
|
||||
<normalon>:/player/resources/stop.png</normalon>:/player/play</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::DelayedPopup</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../gui.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,92 @@
|
|||
#include "gtl_gui_config_widget_player_files.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
widget_player_files::widget_player_files(QObject *parent)
|
||||
: QFileSystemModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
widget_player_files::~widget_player_files()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int widget_player_files::columnCount(const QModelIndex &parent /* = QModelIndex() */) const
|
||||
{
|
||||
return /*QFileSystemModel::columnCount(parent) + 1*/3;
|
||||
}
|
||||
|
||||
QVariant widget_player_files::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
|
||||
{
|
||||
QString value;
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 2)
|
||||
{
|
||||
QFileInfo info = fileInfo(index);
|
||||
if (info.isFile())
|
||||
return QVariant(info.lastModified());
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
//QString str_info;
|
||||
//QVariant value;
|
||||
QFileInfo info = fileInfo(index);
|
||||
if (info.suffix().toLower() == "gtr")
|
||||
{
|
||||
gtl::hw::player_file_gtr file(NULL, filePath(index));
|
||||
value = file.info();
|
||||
}
|
||||
else if (info.suffix().toLower() == "wav")
|
||||
{
|
||||
gtl::hw::player_file_wav file(NULL, filePath(index));
|
||||
value = file.info();
|
||||
}
|
||||
//value = "1234";
|
||||
|
||||
//return value;
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
//return data;
|
||||
|
||||
return QFileSystemModel::data(index, role);
|
||||
}
|
||||
|
||||
QVariant widget_player_files::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const
|
||||
{
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (orientation == Qt::Orientation::Horizontal)
|
||||
{
|
||||
if (section == 0)
|
||||
return tr("name");
|
||||
else if (section == 1)
|
||||
return tr("size");
|
||||
else if (section == 2)
|
||||
return tr("date modified");
|
||||
else if (section == 3)
|
||||
return tr("info");
|
||||
// else
|
||||
// return "";
|
||||
}
|
||||
}
|
||||
|
||||
return QFileSystemModel::headerData(section, orientation, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef GTL_GUI_CONFIG_WIDGET_PLAYER_FILES_H
|
||||
#define GTL_GUI_CONFIG_WIDGET_PLAYER_FILES_H
|
||||
|
||||
#include <QFileSystemModel>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "hw/gtl_hw_player_file_gtr.h"
|
||||
#include "hw/gtl_hw_player_file_wav.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
namespace config
|
||||
{
|
||||
class widget_player_files : public QFileSystemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
widget_player_files(QObject *parent);
|
||||
~widget_player_files();
|
||||
|
||||
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GTL_GUI_CONFIG_WIDGET_PLAYER_FILES_H
|
|
@ -0,0 +1,5 @@
|
|||
#include "gtl_gui.h"
|
||||
|
||||
Gui::Gui()
|
||||
{
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef GUI_H
|
||||
#define GUI_H
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
class GTL_GUI_EXPORT Gui
|
||||
{
|
||||
public:
|
||||
Gui();
|
||||
};
|
||||
|
||||
#endif // GUI_H
|
|
@ -0,0 +1,244 @@
|
|||
#include "gtl_gui_apfc_chart.h"
|
||||
|
||||
namespace gtl {
|
||||
namespace gui {
|
||||
|
||||
apfc_chart::apfc_chart(QWidget* parent)
|
||||
: chart(parent)
|
||||
, _afc(0)
|
||||
, _pfc(0)
|
||||
, _frequency(200)
|
||||
, _resolution(10)
|
||||
, _window(5)
|
||||
, _lines(20)
|
||||
, _average(1)
|
||||
, _overlap(0)
|
||||
, _threshold(50)
|
||||
{
|
||||
set_axis_y_mode(true);
|
||||
}
|
||||
|
||||
apfc_chart::~apfc_chart()
|
||||
{
|
||||
if(_apfc)
|
||||
delete _apfc;
|
||||
}
|
||||
|
||||
void apfc_chart::set_x_log(bool value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
chart_series *apfc_chart::create_series(analog_data *ai)
|
||||
{
|
||||
|
||||
if(!_series.size())
|
||||
_ref = ai;
|
||||
|
||||
if(_series.size() == 1 && static_cast<chart_series*>(_series[0])->ad() != _ref)
|
||||
_ref = _data;
|
||||
|
||||
_data = ai;
|
||||
|
||||
while(_series.size())
|
||||
remove_series(static_cast<chart_series*>(_series.back()));
|
||||
|
||||
|
||||
if(!_apfc)
|
||||
{
|
||||
_apfc = new gtl::math::apfc(_ref, _data);
|
||||
connect(_apfc, >l::math::apfc::afc_changed, this, >l::gui::apfc_chart::afc_changed);
|
||||
connect(_apfc, >l::math::apfc::pfc_changed, this, >l::gui::apfc_chart::pfc_changed);
|
||||
connect(_apfc, >l::math::apfc::frequency_changed, this, >l::gui::apfc_chart::frequency_changed);
|
||||
connect(_apfc, >l::math::apfc::resolution_changed, this, >l::gui::apfc_chart::resolution_changed);
|
||||
connect(_apfc, >l::math::apfc::window_changed, this, >l::gui::apfc_chart::window_changed);
|
||||
connect(_apfc, >l::math::apfc::lines_changed, this, >l::gui::apfc_chart::lines_changed);
|
||||
connect(_apfc, >l::math::apfc::average_changed, this, >l::gui::apfc_chart::average_changed);
|
||||
connect(_apfc, >l::math::apfc::overlap_changed, this, >l::gui::apfc_chart::overlap_changed);
|
||||
connect(_apfc, >l::math::apfc::threshold_changed, this, >l::gui::apfc_chart::threshold_changed);
|
||||
|
||||
_apfc->set_average(_average);
|
||||
_apfc->set_overlap(_overlap);
|
||||
_apfc->set_frequency(_frequency);
|
||||
_apfc->set_lines(_lines);
|
||||
_apfc->set_window(static_cast<gtl::math::apfc::windows>(_window));
|
||||
_apfc->set_afc(static_cast<gtl::math::apfc::afcs>(_afc));
|
||||
_apfc->set_pfc(static_cast<gtl::math::apfc::pfcs>(_pfc));
|
||||
_apfc->set_threshold(_threshold);
|
||||
}
|
||||
_apfc->set_ref(_ref);
|
||||
_apfc->set_data(_data);
|
||||
|
||||
_signals.clear();
|
||||
_signals.push_back(_ref->name());
|
||||
_signals.push_back(_data->name());
|
||||
emit signals_changed(&_signals);
|
||||
|
||||
|
||||
apfc_series *seriesA = new apfc_series(is_updating(), true, _apfc, _ref, _axis_x, _axis_y);
|
||||
seriesA->set_name(tr("AFC"));
|
||||
add_series(seriesA);
|
||||
|
||||
apfc_series *series = new apfc_series(is_updating(), false, _apfc, _data, _axis_x, _axis_y);
|
||||
series->set_name(tr("PFC"));
|
||||
series->update();
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
qreal apfc_chart::threshold() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->threshold();
|
||||
return _threshold;
|
||||
}
|
||||
|
||||
void apfc_chart::set_threshold(qreal newThreshold)
|
||||
{
|
||||
if (qFuzzyCompare(_threshold, newThreshold))
|
||||
return;
|
||||
_threshold = newThreshold;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_threshold(_threshold);
|
||||
}
|
||||
|
||||
int apfc_chart::afc() const
|
||||
{
|
||||
if(_apfc)
|
||||
return static_cast<int>(_apfc->afc());
|
||||
return _afc;
|
||||
}
|
||||
|
||||
void apfc_chart::set_afc(int newAfc)
|
||||
{
|
||||
if (_afc == newAfc)
|
||||
return;
|
||||
_afc = newAfc;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_afc(static_cast<gtl::math::apfc::afcs>(_afc));
|
||||
}
|
||||
|
||||
int apfc_chart::pfc() const
|
||||
{
|
||||
if(_apfc)
|
||||
return static_cast<int>(_apfc->pfc());
|
||||
return _pfc;
|
||||
}
|
||||
|
||||
void apfc_chart::set_pfc(int newPfc)
|
||||
{
|
||||
if (_pfc == newPfc)
|
||||
return;
|
||||
_pfc = newPfc;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_pfc(static_cast<gtl::math::apfc::pfcs>(_pfc));
|
||||
}
|
||||
|
||||
qreal apfc_chart::frequency() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->frequency();
|
||||
return _frequency;
|
||||
}
|
||||
|
||||
void apfc_chart::set_frequency(qreal newFrequency)
|
||||
{
|
||||
if (qFuzzyCompare(_frequency, newFrequency))
|
||||
return;
|
||||
_frequency = newFrequency;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_frequency(_frequency);
|
||||
}
|
||||
|
||||
qreal apfc_chart::resolution() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->resolution();
|
||||
return _resolution;
|
||||
}
|
||||
|
||||
void apfc_chart::set_resolution(qreal newResolution)
|
||||
{
|
||||
if (qFuzzyCompare(_resolution, newResolution))
|
||||
return;
|
||||
_resolution = newResolution;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_resolution(_resolution);
|
||||
}
|
||||
|
||||
int apfc_chart::window() const
|
||||
{
|
||||
if(_apfc)
|
||||
return static_cast<int>(_apfc->window());
|
||||
return _window;
|
||||
}
|
||||
|
||||
void apfc_chart::set_window(int newWindow)
|
||||
{
|
||||
if (_window == newWindow)
|
||||
return;
|
||||
_window = newWindow;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_window(static_cast<gtl::math::apfc::windows>(_window));
|
||||
}
|
||||
|
||||
int apfc_chart::lines() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->lines();
|
||||
return _lines;
|
||||
}
|
||||
|
||||
void apfc_chart::set_lines(int newLines)
|
||||
{
|
||||
if (_lines == newLines)
|
||||
return;
|
||||
_lines = newLines;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_lines(_lines);
|
||||
}
|
||||
|
||||
int apfc_chart::average() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->average();
|
||||
return _average;
|
||||
}
|
||||
|
||||
void apfc_chart::set_average(int newAverage)
|
||||
{
|
||||
if (_average == newAverage)
|
||||
return;
|
||||
_average = newAverage;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_average(_average);
|
||||
}
|
||||
|
||||
qreal apfc_chart::overlap() const
|
||||
{
|
||||
if(_apfc)
|
||||
return _apfc->overlap();
|
||||
return _overlap;
|
||||
}
|
||||
|
||||
void apfc_chart::set_overlap(qreal newOverlap)
|
||||
{
|
||||
if (qFuzzyCompare(_overlap, newOverlap))
|
||||
return;
|
||||
_overlap = newOverlap;
|
||||
if(_apfc && _ref && _data)
|
||||
_apfc->set_overlap(_overlap);
|
||||
}
|
||||
|
||||
void apfc_chart::set_ref(const QString &name)
|
||||
{
|
||||
if(_apfc && name != _ref->name())
|
||||
{
|
||||
std::swap(_ref, _data);
|
||||
_apfc->set_ref(_ref);
|
||||
_apfc->set_data(_data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
|
@ -0,0 +1,88 @@
|
|||
#ifndef GTL_GUI_APFC_CHART_H
|
||||
#define GTL_GUI_APFC_CHART_H
|
||||
|
||||
#include "gtl_gui_chart.h"
|
||||
#include "gui/gtl_gui_apfc_series.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl {
|
||||
namespace gui {
|
||||
|
||||
class GTL_GUI_EXPORT apfc_chart : public gtl::gui::chart
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
apfc_chart(QWidget* parent = NULL);
|
||||
~apfc_chart();
|
||||
|
||||
int afc() const;
|
||||
void set_afc(int newAfc);
|
||||
int pfc() const;
|
||||
void set_pfc(int newPfc);
|
||||
qreal frequency() const;
|
||||
void set_frequency(qreal newFrequency);
|
||||
qreal resolution() const;
|
||||
void set_resolution(qreal newResolution);
|
||||
int window() const;
|
||||
void set_window(int newWindow);
|
||||
int lines() const;
|
||||
void set_lines(int newLines);
|
||||
int average() const;
|
||||
void set_average(int newAverage);
|
||||
qreal overlap() const;
|
||||
void set_overlap(qreal newOverlap);
|
||||
qreal threshold() const;
|
||||
void set_threshold(qreal newThreshold);
|
||||
|
||||
public slots:
|
||||
void set_x_log(bool value);
|
||||
void set_ref(const QString &name);
|
||||
|
||||
signals:
|
||||
|
||||
void afc_changed();
|
||||
void pfc_changed();
|
||||
void frequency_changed();
|
||||
void resolution_changed();
|
||||
void window_changed();
|
||||
void lines_changed();
|
||||
void average_changed();
|
||||
void overlap_changed();
|
||||
void signals_changed(QList<QString> *sigs);
|
||||
void threshold_changed();
|
||||
|
||||
protected:
|
||||
virtual chart_series* create_series(gtl::analog_data* ai);
|
||||
|
||||
private:
|
||||
gtl::math::apfc *_apfc = nullptr;
|
||||
analog_data *_ref = nullptr;
|
||||
analog_data *_data = nullptr;
|
||||
|
||||
int _afc;
|
||||
int _pfc;
|
||||
qreal _frequency;
|
||||
qreal _resolution;
|
||||
int _window;
|
||||
int _lines;
|
||||
int _average;
|
||||
qreal _overlap;
|
||||
qreal _threshold;
|
||||
QList<QString> _signals;
|
||||
|
||||
Q_PROPERTY(int afc READ afc WRITE set_afc NOTIFY afc_changed)
|
||||
Q_PROPERTY(int pfc READ pfc WRITE set_pfc NOTIFY pfc_changed)
|
||||
Q_PROPERTY(qreal frequency READ frequency WRITE set_frequency NOTIFY frequency_changed)
|
||||
Q_PROPERTY(qreal resolution READ resolution WRITE set_resolution NOTIFY resolution_changed)
|
||||
Q_PROPERTY(int window READ window WRITE set_window NOTIFY window_changed)
|
||||
Q_PROPERTY(int lines READ lines WRITE set_lines NOTIFY lines_changed)
|
||||
Q_PROPERTY(int average READ average WRITE set_average NOTIFY average_changed)
|
||||
Q_PROPERTY(qreal overlap READ overlap WRITE set_overlap NOTIFY overlap_changed)
|
||||
Q_PROPERTY(qreal threshold READ threshold WRITE set_threshold NOTIFY threshold_changed)
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
||||
|
||||
#endif // GTL_GUI_APFC_CHART_H
|
|
@ -0,0 +1,63 @@
|
|||
#include "gtl_gui_apfc_series.h"
|
||||
|
||||
namespace gtl {
|
||||
namespace gui {
|
||||
|
||||
apfc_series::apfc_series(bool is_updating, bool is_amplitude, gtl::math::apfc* apfc, gtl::analog_data* ai, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y)
|
||||
: chart_series(ai, axis_x, axis_y)
|
||||
, _apfc(apfc)
|
||||
, _is_ampl(is_amplitude)
|
||||
{
|
||||
_is_updating = is_updating;
|
||||
|
||||
connect(_apfc, >l::math::apfc::changed, this, &apfc_series::update);
|
||||
connect(_apfc, >l::math::apfc::initialized, this, &apfc_series::update);
|
||||
}
|
||||
|
||||
apfc_series::~apfc_series()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void apfc_series::set_apfc(math::apfc *apfc)
|
||||
{
|
||||
disconnect(_apfc, >l::math::apfc::changed, this, &apfc_series::update);
|
||||
disconnect(_apfc, >l::math::apfc::initialized, this, &apfc_series::update);
|
||||
_apfc = apfc;
|
||||
connect(_apfc, >l::math::apfc::changed, this, &apfc_series::update);
|
||||
connect(_apfc, >l::math::apfc::initialized, this, &apfc_series::update);
|
||||
}
|
||||
|
||||
QString apfc_series::name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
void apfc_series::set_name(const QString &newName)
|
||||
{
|
||||
_name = newName;
|
||||
}
|
||||
|
||||
void apfc_series::update()
|
||||
{
|
||||
clear();
|
||||
|
||||
if(_apfc)
|
||||
{
|
||||
axis_x()->set_boundaries(0, _apfc->frequency());
|
||||
qreal res = _apfc->resolution();
|
||||
|
||||
for(int i = 0; i < _apfc->size(); i++)
|
||||
{
|
||||
if(_is_ampl)
|
||||
add(QPointF(i*res, _apfc->at(i).first));
|
||||
else
|
||||
add(QPointF(i*res, _apfc->at(i).second));
|
||||
}
|
||||
|
||||
emit data_changed();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef GTL_GUI_APFC_SERIES_H
|
||||
#define GTL_GUI_APFC_SERIES_H
|
||||
|
||||
#include "math/gtl_math_apfc.h"
|
||||
|
||||
#include "gtl_gui_chart_series.h"
|
||||
|
||||
namespace gtl {
|
||||
namespace gui {
|
||||
|
||||
class apfc_series : public gtl::gui::chart_series
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
apfc_series(bool is_updating, bool is_amplitude, gtl::math::apfc* apfc, gtl::analog_data* ai, ::chart::axis_horz* axis_x, ::chart::axis_vert* axis_y);
|
||||
~apfc_series();
|
||||
|
||||
void set_apfc(gtl::math::apfc *apfc);
|
||||
|
||||
QString name() const;
|
||||
void set_name(const QString &newName);
|
||||
|
||||
private:
|
||||
gtl::math::apfc *_apfc = nullptr;
|
||||
bool _is_ampl = true;
|
||||
QString _name = "";
|
||||
|
||||
public slots:
|
||||
void update();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
||||
|
||||
#endif // GTL_GUI_APFC_SERIES_H
|
|
@ -0,0 +1,142 @@
|
|||
#include "gtl_gui_apfc_widget.h"
|
||||
#include "gui/ui_gtl_gui_apfc_widget.h"
|
||||
|
||||
#include "gui/gtl_gui_chart_widget.h"
|
||||
namespace gtl {
|
||||
namespace gui {
|
||||
|
||||
apfc_widget::apfc_widget(QWidget *parent, gtl::data_model* model) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::apfc_widget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
_selection_data_model = new gtl::selection_data_model(this);
|
||||
_selection_data_model->setSourceModel(model);
|
||||
|
||||
ui->signals_->setModel(_selection_data_model);
|
||||
ui->signals_->expandAll();
|
||||
|
||||
_chart = new gtl::gui::apfc_chart(this);
|
||||
gtl::gui::chart_widget *chart_widget = new gtl::gui::chart_widget(_chart, this);
|
||||
ui->splitter->insertWidget(0, chart_widget);
|
||||
|
||||
connect(_selection_data_model, >l::selection_data_model::selected, _chart, >l::gui::chart::add_ad);
|
||||
connect(_selection_data_model, >l::selection_data_model::deselected, _chart, >l::gui::chart::remove_ad);
|
||||
|
||||
QMetaEnum meta_enum = QMetaEnum::fromType<gtl::math::apfc::afcs>();
|
||||
ui->afc->disconnect();
|
||||
ui->afc->clear();
|
||||
for(int i = 0; i < meta_enum.keyCount(); i++)
|
||||
{
|
||||
ui->afc->addItem(meta_enum.valueToKey(i));
|
||||
}
|
||||
ui->afc->setCurrentIndex(_chart->afc());
|
||||
connect(ui->afc, &QComboBox::currentIndexChanged, _chart, >l::gui::apfc_chart::set_afc);
|
||||
|
||||
meta_enum = QMetaEnum::fromType<gtl::math::apfc::pfcs>();
|
||||
ui->pfc->disconnect();
|
||||
ui->pfc->clear();
|
||||
for(int i = 0; i < meta_enum.keyCount(); i++)
|
||||
{
|
||||
ui->pfc->addItem(meta_enum.valueToKey(i));
|
||||
}
|
||||
ui->pfc->setCurrentIndex(_chart->pfc());
|
||||
connect(ui->pfc, &QComboBox::currentIndexChanged, _chart, >l::gui::apfc_chart::set_pfc);
|
||||
|
||||
meta_enum = QMetaEnum::fromType<gtl::math::apfc::windows>();
|
||||
ui->window->disconnect();
|
||||
ui->window->clear();
|
||||
for(int i = 0; i < meta_enum.keyCount(); i++)
|
||||
{
|
||||
ui->window->addItem(meta_enum.valueToKey(i));
|
||||
}
|
||||
ui->window->setCurrentIndex(_chart->window());
|
||||
connect(ui->window, &QComboBox::currentIndexChanged, _chart, >l::gui::apfc_chart::set_window);
|
||||
|
||||
ui->frequency->disconnect();
|
||||
ui->frequency->setMaximum(100000);
|
||||
ui->frequency->setValue(_chart->frequency());
|
||||
connect(ui->frequency, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_frequency);
|
||||
|
||||
ui->resolution->disconnect();
|
||||
ui->resolution->setMaximum(100000);
|
||||
ui->resolution->setValue(_chart->resolution());
|
||||
connect(ui->resolution, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_resolution);
|
||||
|
||||
ui->lines->disconnect();
|
||||
ui->lines->setMaximum(100000);
|
||||
ui->lines->setValue(_chart->lines());
|
||||
connect(ui->lines, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_lines);
|
||||
|
||||
ui->average->disconnect();
|
||||
ui->average->setMaximum(100);
|
||||
ui->average->setValue(_chart->average());
|
||||
connect(ui->average, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_average);
|
||||
|
||||
ui->overlap->disconnect();
|
||||
ui->overlap->setMaximum(99);
|
||||
ui->overlap->setValue(_chart->overlap());
|
||||
connect(ui->overlap, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_overlap);
|
||||
|
||||
ui->threshold->disconnect();
|
||||
ui->threshold->setMaximum(99);
|
||||
ui->threshold->setValue(_chart->threshold());
|
||||
connect(ui->threshold, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_threshold);
|
||||
|
||||
connect(_chart, >l::gui::apfc_chart::frequency_changed, this, >l::gui::apfc_widget::update_parameters);
|
||||
connect(_chart, >l::gui::apfc_chart::resolution_changed, this, >l::gui::apfc_widget::update_parameters);
|
||||
connect(_chart, >l::gui::apfc_chart::lines_changed, this, >l::gui::apfc_widget::update_parameters);
|
||||
|
||||
ui->x_log->setVisible(false);
|
||||
connect(ui->x_log, &QCheckBox::toggled, _chart, >l::gui::apfc_chart::set_x_log);
|
||||
|
||||
connect(_chart, >l::gui::apfc_chart::signals_changed, this, >l::gui::apfc_widget::handle_chart_signals_changed);
|
||||
}
|
||||
|
||||
apfc_widget::~apfc_widget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void apfc_widget::save(QDomElement &root_element)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void apfc_widget::load(const QDomElement &root_element)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void apfc_widget::update_parameters()
|
||||
{
|
||||
ui->frequency->disconnect();
|
||||
ui->resolution->disconnect();
|
||||
ui->lines->disconnect();
|
||||
|
||||
if( ui->frequency->value() != _chart->frequency() )
|
||||
ui->frequency->setValue(_chart->frequency());
|
||||
|
||||
if( ui->resolution->value() != _chart->resolution() )
|
||||
ui->resolution->setValue(_chart->resolution());
|
||||
|
||||
if( ui->lines->value() != (int) _chart->lines() )
|
||||
ui->lines->setValue(_chart->lines());
|
||||
|
||||
connect(ui->frequency, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_frequency);
|
||||
connect(ui->resolution, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_resolution);
|
||||
connect(ui->lines, &QDoubleSpinBox::valueChanged, _chart, >l::gui::apfc_chart::set_lines);
|
||||
}
|
||||
|
||||
void apfc_widget::handle_chart_signals_changed(QList<QString> *sigs)
|
||||
{
|
||||
disconnect(ui->reference, &QComboBox::currentTextChanged, _chart, >l::gui::apfc_chart::set_ref);
|
||||
ui->reference->clear();
|
||||
foreach (QString sig, *sigs)
|
||||
ui->reference->addItem(sig);
|
||||
connect(ui->reference, &QComboBox::currentTextChanged, _chart, >l::gui::apfc_chart::set_ref);
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef GTL_GUI_GTL_GUI_APFC_WIDGET_H
|
||||
#define GTL_GUI_GTL_GUI_APFC_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "core/gtl_data_model.h"
|
||||
#include "core/gtl_selection_data_model.h"
|
||||
#include "gui/gtl_gui_apfc_chart.h"
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace Ui {
|
||||
class apfc_widget;
|
||||
}
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT apfc_widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit apfc_widget(QWidget *parent = nullptr, gtl::data_model* model = nullptr);
|
||||
~apfc_widget();
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
private:
|
||||
Ui::apfc_widget *ui;
|
||||
gtl::selection_data_model* _selection_data_model;
|
||||
gtl::gui::apfc_chart* _chart;
|
||||
|
||||
private:
|
||||
void update_parameters();
|
||||
|
||||
private slots:
|
||||
void handle_chart_signals_changed(QList<QString> *sigs);
|
||||
};
|
||||
|
||||
|
||||
} // namespace gui
|
||||
} // namespace gtl
|
||||
#endif // GTL_GUI_GTL_GUI_APFC_WIDGET_H
|
|
@ -0,0 +1,241 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>apfc_widget</class>
|
||||
<widget class="QWidget" name="apfc_widget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>624</width>
|
||||
<height>586</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeView" name="signals_"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="referenceLabel">
|
||||
<property name="text">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="reference"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="amplitudeLabel">
|
||||
<property name="text">
|
||||
<string>Amplitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="afc"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="phaseLabel">
|
||||
<property name="text">
|
||||
<string>Phase</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="pfc"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="thresholdLabel">
|
||||
<property name="text">
|
||||
<string>Threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QDoubleSpinBox" name="threshold">
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="frequencyLabel">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="frequency"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="resolutionLabel">
|
||||
<property name="text">
|
||||
<string>Resolution</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="resolution"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="linesLabel">
|
||||
<property name="text">
|
||||
<string>Lines</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="lines"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="windowLabel">
|
||||
<property name="text">
|
||||
<string>Window</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="window"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="averagesLabel">
|
||||
<property name="text">
|
||||
<string>Average</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="average">
|
||||
<property name="minimum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="overlapLabel">
|
||||
<property name="text">
|
||||
<string>Overlap</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="overlap">
|
||||
<property name="maximum">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="x_log">
|
||||
<property name="text">
|
||||
<string>log x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,637 @@
|
|||
#include "gtl_gui_chart.h"
|
||||
|
||||
#include "core/gtl_device.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart::chart(QWidget* parent, chart_axis_x *axis_x, chart_axis_y *axis_y)
|
||||
: ::chart::widget(parent, axis_x == nullptr ? new chart_axis_x() : axis_x, axis_y == nullptr ? new chart_axis_y() : axis_y)
|
||||
, _is_multi_y(false)
|
||||
, _is_updating(true)
|
||||
, _is_cyclic(true)
|
||||
|
||||
{
|
||||
setBackgroundBrush(QBrush(Qt::white));
|
||||
|
||||
connect(static_cast<chart_axis_y*>(_axis_y), &chart_axis_y::get_series, this, &chart::get_axis_series);
|
||||
|
||||
setContextMenuPolicy(Qt::DefaultContextMenu);
|
||||
|
||||
_marker_series = new ::chart::series::xy::line(_axis_x, _axis_y);
|
||||
scene()->addItem(_marker_series);
|
||||
|
||||
_menu = new QMenu(this);
|
||||
_markers_menu = _menu->addMenu(tr("Markers"));
|
||||
|
||||
_marker_action_add = _markers_menu->addAction(tr("Add marker"));
|
||||
connect(_marker_action_add, &QAction::triggered, this, &chart::add_marker);
|
||||
|
||||
_marker_action_remove = _markers_menu->addAction(tr("Remove marker"));
|
||||
connect(_marker_action_remove, &QAction::triggered, this, &chart::delete_marker);
|
||||
|
||||
_marker_action_clear = _markers_menu->addAction(tr("Clear marker"));
|
||||
connect(_marker_action_clear, &QAction::triggered, this, &chart::clear_markers);
|
||||
|
||||
_menu->addSeparator();
|
||||
_set_theme_action = _menu->addAction("Set dark theme");
|
||||
_set_theme_action->setCheckable(true);
|
||||
connect(_set_theme_action, &QAction::toggled, this, &chart::set_theme);
|
||||
|
||||
|
||||
|
||||
|
||||
_markers = new chart_markers(this);
|
||||
_single_markers = new chart_single_markers(this);
|
||||
|
||||
}
|
||||
|
||||
chart::~chart()
|
||||
{
|
||||
delete _marker_series;
|
||||
}
|
||||
|
||||
void chart::set_axis_y_mode(bool is_multi_y)
|
||||
{
|
||||
if(is_multi_y != _is_multi_y)
|
||||
{
|
||||
_is_multi_y = is_multi_y;
|
||||
set_axes_y();
|
||||
|
||||
emit axis_y_mode_changed(_is_multi_y);
|
||||
}
|
||||
}
|
||||
|
||||
void chart::add_marker()
|
||||
{
|
||||
chart_marker* marker = new chart_marker(_marker_series, _set_theme_action->isChecked());
|
||||
add(marker);
|
||||
|
||||
connect(marker, &chart_marker::get_nearest_x, this, &chart::get_neares_series_x);
|
||||
connect(marker, &chart_marker::get_series_data, this, &chart::get_series_data);
|
||||
connect(marker, &chart_marker::get_series_values, this, &chart::get_series_values);
|
||||
connect(marker, &chart_marker::deleting, this, &chart::remove_marker);
|
||||
|
||||
marker->set_pos(_mouse_pos_release);
|
||||
|
||||
_markers->add_marker(marker);
|
||||
_single_markers->add(marker);
|
||||
|
||||
}
|
||||
|
||||
void chart::remove_marker()
|
||||
{
|
||||
chart_marker* marker = static_cast<chart_marker*>(sender());
|
||||
_markers->remove_marker(marker);
|
||||
// _single_markers->remove(marker);
|
||||
remove(marker);
|
||||
}
|
||||
|
||||
void chart::clear_markers()
|
||||
{
|
||||
while(_markers->count_markers() != 0)
|
||||
{
|
||||
chart_marker* marker = _markers->marker(0);
|
||||
_markers->remove_marker(marker);
|
||||
// _single_markers->remove(marker);
|
||||
remove(marker);
|
||||
delete marker;
|
||||
}
|
||||
}
|
||||
|
||||
void chart::get_neares_series_x(qreal &x, chart_line::pos_behaviors behavior)
|
||||
{
|
||||
if(behavior == chart_line::magnetic_to_sample)
|
||||
{
|
||||
qreal neares_x = x;
|
||||
qreal delta_min = qInf();
|
||||
foreach(::chart::series::series *s, _series)
|
||||
{
|
||||
::chart::series::xy::xy *s_xy = static_cast<::chart::series::xy::xy*>(s);
|
||||
if(s_xy->size() < 2)
|
||||
continue;
|
||||
|
||||
auto it = std::lower_bound(s_xy->begin_data(), s_xy->end_data(), QPointF(x, 0), [](
|
||||
const QPointF &p0, const QPointF &p1)
|
||||
{
|
||||
return p0.x() < p1.x();
|
||||
}
|
||||
);
|
||||
|
||||
int idx0 = std::min<int>(std::distance(s_xy->begin_data(), it), (int)s_xy->size() - 1);
|
||||
int idx1 = std::max<int>(idx0 - 1, 0);
|
||||
|
||||
qreal delta = qAbs(x - s_xy->at_x(idx0));
|
||||
if(delta < delta_min)
|
||||
{
|
||||
delta_min = delta;
|
||||
neares_x = s_xy->at_x(idx0);
|
||||
}
|
||||
|
||||
delta = qAbs(x - s_xy->at_x(idx1));
|
||||
if(delta < delta_min)
|
||||
{
|
||||
delta_min = delta;
|
||||
neares_x = s_xy->at_x(idx1);
|
||||
}
|
||||
}
|
||||
|
||||
x = neares_x;
|
||||
}
|
||||
else{
|
||||
qreal min = qInf(), max = -qInf();
|
||||
|
||||
for(auto s : _series)
|
||||
{
|
||||
::chart::series::xy::xy *s_xy = static_cast<::chart::series::xy::xy*>(s);
|
||||
if(s_xy->empty())
|
||||
continue;
|
||||
|
||||
if(s_xy->front_x() < min)
|
||||
min = s_xy->front_x();
|
||||
if(s_xy->back_x() > max)
|
||||
max = s_xy->back_x();
|
||||
}
|
||||
|
||||
if(min == qInf() || max == -qInf())
|
||||
{
|
||||
min = _axis_x->min_boundary();
|
||||
max = _axis_x->max_boundary();
|
||||
}
|
||||
|
||||
if(x < min)
|
||||
x = min;
|
||||
else if(x > max)
|
||||
x = max;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void chart::get_series_data(qreal x, bool is_widget_pos, QVariantList &data)
|
||||
{
|
||||
foreach(::chart::series::series *s, _series)
|
||||
{
|
||||
::chart::series::xy::xy *s_xy = static_cast<::chart::series::xy::xy*>(s);
|
||||
|
||||
if(s_xy->size() < 2)
|
||||
{
|
||||
data.push_back(QVariant(qQNaN()));
|
||||
data.push_back(QVariant(QColor(Qt::black)));
|
||||
}
|
||||
|
||||
auto it = std::lower_bound(s_xy->begin_data(), s_xy->end_data(), QPointF(x, 0), [](
|
||||
const QPointF &p0, const QPointF &p1)
|
||||
{
|
||||
return p0.x() < p1.x();
|
||||
}
|
||||
);
|
||||
|
||||
if(it == s_xy->end_data())
|
||||
{
|
||||
data.push_back(QVariant(qQNaN()));
|
||||
data.push_back(QVariant(QColor(Qt::black)));
|
||||
}
|
||||
else if(it->x() == x)
|
||||
{
|
||||
if(is_widget_pos)
|
||||
data.push_back(QVariant(s_xy->axis_y()->map_to_widget(it->y())));
|
||||
else
|
||||
data.push_back(QVariant(it->y()));
|
||||
data.push_back(QVariant(s_xy->color()));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it_prev = std::prev(it);
|
||||
qreal k = (it_prev->y() - it->y())/(it_prev->x() - it->x());
|
||||
qreal y = k*x + it_prev->y() - k*it_prev->x();
|
||||
|
||||
if(is_widget_pos)
|
||||
data.push_back(QVariant(s_xy->axis_y()->map_to_widget(y)));
|
||||
else
|
||||
data.push_back(QVariant(y));
|
||||
data.push_back(QVariant(s_xy->color()));
|
||||
|
||||
/*
|
||||
data.push_back(QVariant(qQNaN()));
|
||||
data.push_back(QVariant(QColor(Qt::black)));
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chart::get_series_values(qreal x_min, qreal x_max, int series_idx, QVariantList &data)
|
||||
{
|
||||
::chart::series::xy::xy *s_xy = static_cast<::chart::series::xy::xy*>(_series[series_idx]);
|
||||
|
||||
auto it_min = std::lower_bound(s_xy->begin_data(), s_xy->end_data(), QPointF(x_min, 0), [](
|
||||
const QPointF &p0, const QPointF &p1)
|
||||
{
|
||||
return p0.x() < p1.x();
|
||||
}
|
||||
);
|
||||
|
||||
auto it_max = std::upper_bound(s_xy->begin_data(), s_xy->end_data(), QPointF(x_max, 0), [](
|
||||
const QPointF &p0, const QPointF &p1)
|
||||
{
|
||||
return p0.x() < p1.x();
|
||||
}
|
||||
);
|
||||
|
||||
for(auto it = it_min; it != it_max; it++)
|
||||
data.push_back(it->y());
|
||||
|
||||
}
|
||||
|
||||
void chart::delete_marker()
|
||||
{
|
||||
delete _marker_popup;
|
||||
}
|
||||
|
||||
void chart::deleting_ad()
|
||||
{
|
||||
remove_ad(static_cast<gtl::analog_data*>(sender()));
|
||||
}
|
||||
|
||||
void chart::get_axis_series(QList<chart_series*> &series)
|
||||
{
|
||||
for(auto s: _series)
|
||||
{
|
||||
if(s->axis_y() == sender())
|
||||
series.push_back(static_cast<chart_series*>(s));
|
||||
}
|
||||
}
|
||||
|
||||
void chart::set_theme(bool is_dack)
|
||||
{
|
||||
if(is_dack)
|
||||
{
|
||||
setBackgroundBrush(QBrush(Qt::black));
|
||||
_markers->set_bgnd_color(Qt::black);
|
||||
_markers->set_color(Qt::white);
|
||||
}
|
||||
else
|
||||
{
|
||||
setBackgroundBrush(QBrush(Qt::white));
|
||||
_markers->set_bgnd_color(Qt::white);
|
||||
_markers->set_color(Qt::black);
|
||||
}
|
||||
|
||||
static_cast<chart_axis_x*>(_axis_x)->set_theme(is_dack);
|
||||
static_cast<chart_axis_y*>(_axis_y)->set_theme(is_dack);
|
||||
foreach(::chart::series::series *s, _series)
|
||||
static_cast<chart_axis_y*>(s->axis_y())->set_theme(is_dack);
|
||||
}
|
||||
|
||||
void chart::device_recieved_data()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool chart::is_axis_y_multi() const
|
||||
{
|
||||
return _is_multi_y;
|
||||
}
|
||||
|
||||
bool chart::is_updating() const
|
||||
{
|
||||
return _is_updating;
|
||||
}
|
||||
|
||||
bool chart::is_cyclic() const
|
||||
{
|
||||
return _is_cyclic;
|
||||
}
|
||||
|
||||
void chart::set_cyclic(bool value)
|
||||
{
|
||||
if(_is_cyclic != value)
|
||||
{
|
||||
qDebug() << value;
|
||||
_is_cyclic = value;
|
||||
emit cyclic_changed(value);
|
||||
}
|
||||
}
|
||||
|
||||
chart_markers *chart::chart_markers_model() const
|
||||
{
|
||||
return _markers;
|
||||
}
|
||||
|
||||
void chart::save(QDomElement &root_element)
|
||||
{
|
||||
root_element.setAttribute("is_updating", _is_updating);
|
||||
root_element.setAttribute("is_cyclic", _is_cyclic);
|
||||
root_element.setAttribute("is_multi_y", _is_multi_y);
|
||||
|
||||
QDomElement axes_element = root_element.ownerDocument().createElement("axes");
|
||||
root_element.appendChild(axes_element);
|
||||
|
||||
if(_is_multi_y)
|
||||
{
|
||||
for(int i = 0; i < (int)_series.size(); i++)
|
||||
{
|
||||
QDomElement axis_element = root_element.ownerDocument().createElement("axis");
|
||||
axes_element.appendChild(axis_element);
|
||||
|
||||
static_cast<gtl::gui::chart_axis_y*>(_series[i]->axis_y())->save(axis_element);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QDomElement axis_element = root_element.ownerDocument().createElement("axis");
|
||||
axes_element.appendChild(axis_element);
|
||||
|
||||
static_cast<gtl::gui::chart_axis_y*>(_axis_y)->save(axis_element);
|
||||
}
|
||||
}
|
||||
|
||||
void chart::load(const QDomElement &root_element)
|
||||
{
|
||||
set_updating(root_element.attribute("is_updating", "1").toInt() == 1);
|
||||
set_cyclic(root_element.attribute("is_cyclic", "1").toInt() == 1);
|
||||
set_axis_y_mode(root_element.attribute("is_multi_y", "0").toInt() == 1);
|
||||
|
||||
QDomElement axes_element = root_element.firstChildElement("axes");
|
||||
QDomElement axis_element = axes_element.firstChildElement("axis");
|
||||
|
||||
if(_is_multi_y)
|
||||
{
|
||||
for(int i = 0; i < (int)_series.size(); i++)
|
||||
{
|
||||
static_cast<gtl::gui::chart_axis_y*>(_series[i]->axis_y())->load(axis_element);
|
||||
|
||||
axis_element = axis_element.nextSiblingElement("axis");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
static_cast<gtl::gui::chart_axis_y*>(_axis_y)->load(axis_element);
|
||||
}
|
||||
}
|
||||
|
||||
bool chart::is_multi_y() const
|
||||
{
|
||||
return _is_multi_y;
|
||||
}
|
||||
|
||||
void chart::set_background(QColor color)
|
||||
{
|
||||
setBackgroundBrush(QBrush(color));
|
||||
_markers->set_bgnd_color(color);
|
||||
}
|
||||
|
||||
chart_single_markers *chart::single_markers() const
|
||||
{
|
||||
return _single_markers;
|
||||
}
|
||||
|
||||
void chart::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void gtl::gui::chart::add_series(chart_series *series)
|
||||
{
|
||||
add(series);
|
||||
|
||||
_markers->add_series(series);
|
||||
|
||||
set_axes_y();
|
||||
|
||||
set_bounds_x();
|
||||
|
||||
if(_series.size() == 1)
|
||||
_axis_x->set_range();
|
||||
}
|
||||
|
||||
void chart::add_ad(analog_data *ad)
|
||||
{
|
||||
chart_series *series = create_series(ad);
|
||||
|
||||
gtl::data_model_node* device = ad->root();
|
||||
|
||||
if(_devices.find(device) == _devices.end())
|
||||
connect(static_cast<gtl::device*>(device), >l::device::recieved_data, this, &chart::device_recieved_data);
|
||||
|
||||
_devices[device].push_back(series);
|
||||
|
||||
connect(ad, >l::data_model_node::deleting, this, &chart::deleting_ad);
|
||||
|
||||
add_series(series);
|
||||
}
|
||||
|
||||
void gtl::gui::chart::remove_series(chart_series *series)
|
||||
{
|
||||
|
||||
if(_is_multi_y)
|
||||
{
|
||||
::chart::axis* axis = series->axis_y();
|
||||
series->set_axis_y(_axis_y);
|
||||
remove(axis);
|
||||
delete axis;
|
||||
}
|
||||
|
||||
_markers->remove_series(static_cast<chart_series*>(series));
|
||||
|
||||
remove(series);
|
||||
|
||||
set_axes_y();
|
||||
|
||||
set_bounds_x();
|
||||
}
|
||||
|
||||
void chart::remove_series()
|
||||
{
|
||||
while(!_series.empty())
|
||||
{
|
||||
gtl::gui::chart_series* series = static_cast<gtl::gui::chart_series*>(_series.front());
|
||||
remove_series(series);
|
||||
|
||||
delete series;
|
||||
}
|
||||
|
||||
_series.clear();
|
||||
}
|
||||
|
||||
void chart::remove_ad(analog_data *ad)
|
||||
{
|
||||
for(int i = 0; i < (int)_series.size(); i++)
|
||||
{
|
||||
if(static_cast<chart_series*>(_series[i])->ad() == ad)
|
||||
{
|
||||
gtl::data_model_node* device = ad->root();
|
||||
_devices[device].remove(static_cast<chart_series*>(_series[i]));
|
||||
if(_devices[device].empty())
|
||||
{
|
||||
disconnect(static_cast<gtl::device*>(device), >l::device::recieved_data, this, &chart::device_recieved_data);
|
||||
_devices.erase(device);
|
||||
}
|
||||
|
||||
chart_series *series = static_cast<chart_series*>(_series[i]);
|
||||
remove_series(series);
|
||||
delete series;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chart::set_updating(bool value)
|
||||
{
|
||||
if(_is_updating != value)
|
||||
{
|
||||
for(std::vector<::chart::series::series*>::iterator iter_series = _series.begin(); iter_series != _series.end(); iter_series++)
|
||||
static_cast<chart_series*>(*iter_series)->set_updating(value);
|
||||
|
||||
_is_updating = value;
|
||||
|
||||
emit updating_changed(value);
|
||||
}
|
||||
}
|
||||
|
||||
void chart::set_bounds_x()
|
||||
{
|
||||
qreal min = qInf(), max = -qInf();
|
||||
for(int i = 0; i < _series.size(); i++)
|
||||
{
|
||||
::chart::series::xy::xy* s = static_cast<::chart::series::xy::xy*>(_series[i]);
|
||||
if(s->empty())
|
||||
continue;
|
||||
|
||||
min = std::min<qreal>(min, s->front_x());
|
||||
max = std::max<qreal>(max, s->back_x());
|
||||
}
|
||||
|
||||
if((min == qInf() && max == -qInf()) || (min == max))
|
||||
_axis_x->set_boundaries(0, 100);
|
||||
else
|
||||
_axis_x->set_boundaries(min, max);
|
||||
}
|
||||
|
||||
void chart::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
if(_mouse_pos_press != _mouse_pos_release)
|
||||
return;
|
||||
|
||||
_marker_popup = _markers->marker_at(event->pos());
|
||||
_marker_action_remove->setVisible(_marker_popup != NULL);
|
||||
|
||||
_marker_action_clear->setVisible(_markers->count_markers() != 0);
|
||||
|
||||
_set_theme_action->setText(_set_theme_action->isChecked() ? tr("Set light theme") : tr("Set dark theme"));
|
||||
_set_theme_action->setIcon(_set_theme_action->isChecked() ? QIcon(":chart/light_theme") : QIcon(":chart/dark_theme"));
|
||||
|
||||
_menu->popup(event->globalPos());
|
||||
}
|
||||
|
||||
void chart::set_axes_y()
|
||||
{
|
||||
if(!_is_multi_y)
|
||||
{
|
||||
for(int i = 0; i < _series.size(); i++)
|
||||
{
|
||||
::chart::axis* axis = _series[i]->axis_y();
|
||||
if(axis != _axis_y)
|
||||
{
|
||||
_series[i]->set_axis_y(_axis_y);
|
||||
remove(axis);
|
||||
delete axis;
|
||||
}
|
||||
}
|
||||
|
||||
_axis_y->setVisible(true);
|
||||
fit_axis(_axis_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < _series.size(); i++)
|
||||
{
|
||||
::chart::axis* axis = _series[i]->axis_y();
|
||||
if(axis == _axis_y)
|
||||
{
|
||||
chart_axis_y* axis = create_axis_y();
|
||||
connect(axis, &chart_axis_y::get_series, this, &chart::get_axis_series);
|
||||
_series[i]->set_axis_y(axis);
|
||||
add(axis);
|
||||
fit_axis(axis);
|
||||
}
|
||||
|
||||
_series[i]->axis_y()->set_pos(i / (qreal)_series.size(), (i + 1) / (qreal)_series.size());
|
||||
|
||||
|
||||
}
|
||||
|
||||
_axis_y->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void chart::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
_mouse_pos_press = event->pos();
|
||||
|
||||
chart::widget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void chart::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
_mouse_pos_release = event->pos();
|
||||
|
||||
chart::widget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void chart::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if(event->button() == Qt::LeftButton)
|
||||
{
|
||||
QPointF pos = mapToScene(event->pos());
|
||||
|
||||
for(std::vector<::chart::axis*>::iterator iter_axis = _axes.begin(); iter_axis != _axes.end(); iter_axis++)
|
||||
{
|
||||
QRectF rect_axis = (*iter_axis)->boundingRect();
|
||||
if(rect_axis.contains(pos))
|
||||
{
|
||||
if(_is_multi_y)
|
||||
{
|
||||
if((*iter_axis)->orient() == ::chart::axis::vert)
|
||||
{
|
||||
fit_axis(*iter_axis);
|
||||
|
||||
auto series_iterator = std::find_if(_series.begin(), _series.end(), [=](::chart::series::series* series){return series->axis_y() == *iter_axis;});
|
||||
if(series_iterator != _series.end())
|
||||
{
|
||||
(*series_iterator)->axis_x()->set_range(static_cast<chart_series*>((*series_iterator))->left(), static_cast<chart_series*>((*series_iterator))->right());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fit_axis(*iter_axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chart::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if(!_tool_zooming->isVisible())
|
||||
{
|
||||
for(auto it : _series)
|
||||
static_cast<chart_series*>(it)->set_tool_tip(event->pos());
|
||||
}
|
||||
|
||||
chart::widget::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
chart_axis_y *chart::create_axis_y() const
|
||||
{
|
||||
chart_axis_y* axis = new chart_axis_y();
|
||||
axis->set_theme(_set_theme_action->isChecked());
|
||||
|
||||
return axis;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
#ifndef CHART_H
|
||||
#define CHART_H
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "chart/widget_chart.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
#include "gtl_gui_chart_axis_x.h"
|
||||
#include "gtl_gui_chart_axis_y.h"
|
||||
#include "gtl_gui_chart_series.h"
|
||||
|
||||
#include "core/gtl_analog_data.h"
|
||||
|
||||
#include "gtl_gui_chart_marker.h"
|
||||
#include "gtl_gui_chart_single_markers.h"
|
||||
|
||||
#include "gtl_gui_chart_markers.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart : public ::chart::widget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart(QWidget* parent = NULL, chart_axis_x *axis_x = NULL, chart_axis_y *axis_y = NULL);
|
||||
virtual ~chart();
|
||||
|
||||
bool is_axis_y_multi() const;
|
||||
bool is_updating() const;
|
||||
bool is_cyclic() const;
|
||||
|
||||
chart_markers* chart_markers_model() const;
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
|
||||
bool is_multi_y() const;
|
||||
|
||||
void set_background(QColor color);
|
||||
|
||||
chart_single_markers* single_markers() const;
|
||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
|
||||
private:
|
||||
bool _is_multi_y;
|
||||
|
||||
QPoint _mouse_pos_press;
|
||||
chart_marker* _marker_popup;
|
||||
|
||||
protected:
|
||||
::chart::series::series* _marker_series;
|
||||
chart_markers* _markers;
|
||||
chart_single_markers* _single_markers;
|
||||
QPoint _mouse_pos_release;
|
||||
|
||||
private:
|
||||
void set_axes_y();
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
protected:
|
||||
virtual chart_axis_y* create_axis_y() const;
|
||||
|
||||
|
||||
private:
|
||||
bool _is_updating;
|
||||
bool _is_cyclic;
|
||||
|
||||
protected:
|
||||
QMenu *_menu;
|
||||
QMenu* _markers_menu;
|
||||
|
||||
QAction* _marker_action_add;
|
||||
QAction* _marker_action_remove;
|
||||
QAction* _marker_action_clear;
|
||||
QAction* _set_theme_action;
|
||||
|
||||
std::map<gtl::data_model_node*, std::list<chart_series*>> _devices;
|
||||
|
||||
|
||||
protected:
|
||||
virtual chart_series* create_series(gtl::analog_data* ai) = 0;
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
|
||||
void add_series(chart_series *series);
|
||||
void remove_series(chart_series *series);
|
||||
void remove_series();
|
||||
|
||||
signals:
|
||||
void updating_changed(bool);
|
||||
void cyclic_changed(bool);
|
||||
void axis_y_mode_changed(bool);
|
||||
|
||||
public slots:
|
||||
virtual void add_ad(gtl::analog_data* ad);
|
||||
virtual void remove_ad(gtl::analog_data* ad);
|
||||
|
||||
void set_updating(bool value);
|
||||
void set_cyclic(bool value);
|
||||
|
||||
void set_axis_y_mode(bool is_multi_y);
|
||||
|
||||
|
||||
private slots:
|
||||
void add_marker();
|
||||
void delete_marker();
|
||||
void clear_markers();
|
||||
void deleting_ad();
|
||||
void get_axis_series(QList<chart_series*> &series);
|
||||
void set_theme(bool);
|
||||
|
||||
protected slots:
|
||||
virtual void device_recieved_data();
|
||||
void set_bounds_x();
|
||||
void get_neares_series_x(qreal &x, chart_line::pos_behaviors);
|
||||
void get_series_data(qreal x, bool is_widget_pos, QVariantList &data);
|
||||
void get_series_values(qreal x_min, qreal x_max, int series_idx, QVariantList &data);
|
||||
void remove_marker();
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_H
|
|
@ -0,0 +1,21 @@
|
|||
#include "gtl_gui_chart_axis_x.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_axis_x::chart_axis_x()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void chart_axis_x::set_theme(bool is_dack)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
if (is_dack)
|
||||
_color_labels = Qt::white;
|
||||
else
|
||||
_color_labels = Qt::black;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef CHART_AXIS_X_H
|
||||
#define CHART_AXIS_X_H
|
||||
|
||||
#include "chart/axis_horz.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_axis_x : public ::chart::axis_horz
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_axis_x();
|
||||
void set_theme(bool is_dack);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_AXIS_X_H
|
|
@ -0,0 +1,84 @@
|
|||
#include "gtl_gui_chart_axis_y.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_axis_y::chart_axis_y(qreal pos_min, qreal pos_max)
|
||||
: ::chart::axis_vert(down_to_up, false)
|
||||
{
|
||||
_pos_min = pos_min;
|
||||
_pos_max = pos_max;
|
||||
}
|
||||
|
||||
void chart_axis_y::save(QDomElement &root_element)
|
||||
{
|
||||
root_element.setAttribute("min", min());
|
||||
root_element.setAttribute("max", max());
|
||||
}
|
||||
|
||||
void chart_axis_y::load(const QDomElement &root_element)
|
||||
{
|
||||
set_range(root_element.attribute("min", "-1").toDouble(), root_element.attribute("max", "1").toDouble());
|
||||
}
|
||||
|
||||
void chart_axis_y::set_theme(bool is_dack)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
if (is_dack)
|
||||
_color_labels = Qt::white;
|
||||
else
|
||||
_color_labels = Qt::black;
|
||||
}
|
||||
|
||||
void chart_axis_y::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
::chart::axis_vert::paint(painter, option, widget);
|
||||
|
||||
QList<chart_series*> series;
|
||||
emit get_series(series);
|
||||
|
||||
QRectF boundary = boundingRect();
|
||||
|
||||
int left = boundary.right();
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
int y = 5;
|
||||
for (auto s: series)
|
||||
{
|
||||
if (!s->isVisible())
|
||||
continue;
|
||||
|
||||
QRectF rect(boundary.right() - 105, boundary.top() + y, 100, 20);
|
||||
QString text = s->name();
|
||||
|
||||
int flags_alignment = Qt::AlignRight | Qt::AlignTop;
|
||||
painter->setPen(s->color());
|
||||
rect = painter->boundingRect(rect, flags_alignment, text);
|
||||
|
||||
if (rect.left() < left)
|
||||
left = rect.left();
|
||||
|
||||
draw_label(painter, rect,flags_alignment, s->color(), text);
|
||||
|
||||
/*
|
||||
QString unit = "";
|
||||
|
||||
if (!unit.isEmpty())
|
||||
{
|
||||
QRectF r = painter->boundingRect(QRectF(), Qt::AlignCenter, unit);
|
||||
width += r.width() + 10;
|
||||
if (r.height() > height)
|
||||
height = r.height();
|
||||
|
||||
}
|
||||
*/
|
||||
y += 15;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef AXIS_Y_H
|
||||
#define AXIS_Y_H
|
||||
|
||||
#include <QDomElement>
|
||||
|
||||
#include "chart/axis_vert.h"
|
||||
|
||||
#include "gtl_gui_chart_series.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_axis_y : public ::chart::axis_vert
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_axis_y(qreal pos_min = 0, qreal pos_max = 1);
|
||||
|
||||
virtual void save(QDomElement& root_element);
|
||||
virtual void load(const QDomElement& root_element);
|
||||
void set_theme(bool is_dack);
|
||||
|
||||
private:
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
signals:
|
||||
void get_series(QList<gtl::gui::chart_series*> &series);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // AXIS_Y_H
|
|
@ -0,0 +1,85 @@
|
|||
#include "gtl_gui_chart_line.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_line::chart_line(::chart::series::series *parent, Qt::Orientation orientation)
|
||||
: ::chart::instrument::primitive::line(parent)
|
||||
, _orientation(orientation)
|
||||
, _behavior(magnetic_to_sample)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIsMovable, true);
|
||||
|
||||
if(_orientation == Qt::Vertical)
|
||||
_cursor = Qt::SplitHCursor;
|
||||
else
|
||||
_cursor = Qt::SplitVCursor;
|
||||
|
||||
_pen.setStyle(Qt::PenStyle::DashLine);
|
||||
|
||||
set_pos(0);
|
||||
}
|
||||
|
||||
void chart_line::set_pos(qreal x)
|
||||
{
|
||||
emit get_nearest_x(x, _behavior);
|
||||
if(_orientation == Qt::Vertical)
|
||||
set_line(x, 0, x, 1);
|
||||
else
|
||||
set_line(0, x, 1, x);
|
||||
}
|
||||
|
||||
qreal chart_line::pos()
|
||||
{
|
||||
if(_orientation == Qt::Vertical)
|
||||
return _p0.x();
|
||||
else
|
||||
return _p0.y();
|
||||
}
|
||||
|
||||
chart_line::pos_behaviors chart_line::behavior() const
|
||||
{
|
||||
return _behavior;
|
||||
}
|
||||
|
||||
void chart_line::set_behavior(pos_behaviors behavior)
|
||||
{
|
||||
_behavior = behavior;
|
||||
set_pos(pos());
|
||||
}
|
||||
|
||||
void chart_line::set_width(qreal value)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
_pen.setWidth(value);
|
||||
}
|
||||
|
||||
qreal chart_line::width() const
|
||||
{
|
||||
return _pen.width();
|
||||
}
|
||||
|
||||
QVariant chart_line::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
if (change == ItemPositionChange)
|
||||
{
|
||||
blockSignals(true);
|
||||
QVariant value0 = chart::instrument::primitive::line::itemChange(change, value);
|
||||
blockSignals(false);
|
||||
|
||||
qreal x = pos();
|
||||
// emit get_nearest_x(x, _behavior);
|
||||
set_pos(x);
|
||||
|
||||
|
||||
emit signal_moved();
|
||||
|
||||
return value0;
|
||||
|
||||
}
|
||||
|
||||
return chart::instrument::primitive::line::itemChange(change, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef CHART_LINE_H
|
||||
#define CHART_LINE_H
|
||||
|
||||
#include "chart/instruments/primitives/primitive_line.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_line : public ::chart::instrument::primitive::line
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum pos_behaviors{
|
||||
magnetic_to_sample,
|
||||
free
|
||||
};
|
||||
|
||||
public:
|
||||
chart_line(::chart::series::series *parent, Qt::Orientation orientation = Qt::Vertical);
|
||||
|
||||
void set_pos(qreal x);
|
||||
qreal pos();
|
||||
|
||||
pos_behaviors behavior() const;
|
||||
void set_behavior(pos_behaviors behavior);
|
||||
|
||||
void set_width(qreal value);
|
||||
qreal width() const;
|
||||
|
||||
private:
|
||||
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
|
||||
|
||||
protected:
|
||||
pos_behaviors _behavior;
|
||||
Qt::Orientation _orientation;
|
||||
|
||||
|
||||
signals:
|
||||
void get_nearest_x(qreal& x, pos_behaviors);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_LINE_H
|
|
@ -0,0 +1,115 @@
|
|||
#include "gtl_gui_chart_marker.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_marker::chart_marker(::chart::series::series* parent, bool is_dark_theme)
|
||||
: ::chart::instrument::instrument(parent)
|
||||
, _idx(-1)
|
||||
{
|
||||
if(is_dark_theme)
|
||||
_color = Qt::white;
|
||||
else
|
||||
_color = Qt::black;
|
||||
|
||||
_line = new chart_marker_line(parent, _idx);
|
||||
::chart::instrument::instrument::add(_line);
|
||||
connect(_line, &chart_marker_line::get_nearest_x, this, &chart_marker::get_nearest_x);
|
||||
connect(_line, &chart_marker_line::get_series_data, this, &chart_marker::get_series_data);
|
||||
connect(_line, &chart_marker_line::signal_moved, this, &chart_marker::line_moved);
|
||||
|
||||
/*
|
||||
_label = new chart_marker_label(parent);
|
||||
_label->set_color(Qt::black);
|
||||
::chart::instrument::instrument::add(_label);
|
||||
*/
|
||||
}
|
||||
|
||||
chart_marker::~chart_marker()
|
||||
{
|
||||
emit deleting();
|
||||
}
|
||||
|
||||
void chart_marker::set_pos(QPoint p)
|
||||
{
|
||||
qreal x = _series->axis_x()->map_from_widget(p.x());
|
||||
|
||||
_line->set_pos(x);
|
||||
}
|
||||
|
||||
void chart_marker::set_pos(qreal x)
|
||||
{
|
||||
_line->set_pos(x);
|
||||
}
|
||||
|
||||
void chart_marker::set_pos()
|
||||
{
|
||||
set_pos(pos());
|
||||
}
|
||||
|
||||
qreal chart_marker::pos() const
|
||||
{
|
||||
return _line->pos();
|
||||
}
|
||||
|
||||
bool chart_marker::contains(const QPointF& point) const
|
||||
{
|
||||
return _line->contains(point);
|
||||
}
|
||||
|
||||
void chart_marker::set_idx(int idx)
|
||||
{
|
||||
if(idx != _idx)
|
||||
{
|
||||
_line->set_idx(idx);
|
||||
_idx = idx;
|
||||
|
||||
emit idx_changed();
|
||||
}
|
||||
}
|
||||
|
||||
int chart_marker::idx() const
|
||||
{
|
||||
return _line->idx();
|
||||
}
|
||||
|
||||
qreal chart_marker::value(int series_idx)
|
||||
{
|
||||
QVariantList values;
|
||||
emit get_series_data(_line->pos(), false, values);
|
||||
|
||||
return values[series_idx*2].toDouble();
|
||||
}
|
||||
|
||||
void chart_marker::set_width(qreal width)
|
||||
{
|
||||
_line->set_width(width);
|
||||
}
|
||||
|
||||
qreal chart_marker::width() const
|
||||
{
|
||||
return _line->width();
|
||||
}
|
||||
|
||||
void chart_marker::add(const QPointF &/*point*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void chart_marker::draw(const QPointF &/*point*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void chart_marker::line_moved()
|
||||
{
|
||||
emit position_changed();
|
||||
}
|
||||
|
||||
void chart_marker::set_color(const QColor &color)
|
||||
{
|
||||
::chart::instrument::instrument::set_color(color);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef CHART_MARKER_H
|
||||
#define CHART_MARKER_H
|
||||
|
||||
#include "chart/instruments/instrument.h"
|
||||
|
||||
#include "gtl_gui_chart_marker_line.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_marker : public ::chart::instrument::instrument
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_marker(::chart::series::series* parent, bool is_dark_theme);
|
||||
virtual ~chart_marker();
|
||||
|
||||
void set_pos(QPoint p);
|
||||
virtual void set_pos(qreal x);
|
||||
void set_pos();
|
||||
qreal pos() const;
|
||||
|
||||
virtual bool contains(const QPointF& point) const;
|
||||
virtual void set_idx(int idx);
|
||||
int idx() const;
|
||||
|
||||
virtual qreal value(int series_idx);
|
||||
virtual void set_width(qreal width);
|
||||
virtual qreal width() const;
|
||||
|
||||
protected:
|
||||
chart_marker_line* _line;
|
||||
int _idx;
|
||||
|
||||
private:
|
||||
virtual void add(const QPointF &point) override;
|
||||
virtual void draw(const QPointF &point) override;
|
||||
|
||||
signals:
|
||||
void get_nearest_x(qreal& x, chart_line::pos_behaviors);
|
||||
void get_series_data(qreal x, bool is_widget_pos, QVariantList &data);
|
||||
void get_series_values(qreal x_min, qreal x_max, int series_idx, QVariantList &data);
|
||||
void position_changed();
|
||||
void idx_changed();
|
||||
void deleting();
|
||||
|
||||
protected slots:
|
||||
virtual void line_moved();
|
||||
|
||||
public slots:
|
||||
virtual void set_color(const QColor &color);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKER_H
|
|
@ -0,0 +1,63 @@
|
|||
#include "gtl_gui_chart_marker_color_delegate.h"
|
||||
|
||||
#include "gui/gtl_gui_color_box.h"
|
||||
#include "gtl_gui_chart_markers_model.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_marker_color_delegate::chart_marker_color_delegate(QObject *parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QWidget *chart_marker_color_delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
|
||||
color_box *editor = new color_box(parent);
|
||||
editor->setMinimumSize(0, 0);
|
||||
// editor->setFrame(false);
|
||||
|
||||
((chart_markers_model*)index.model())->connect_color_changed_signal(editor, index);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
void chart_marker_color_delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return;
|
||||
QColor value = index.model()->data(index, Qt::DisplayRole).value<QColor>();
|
||||
static_cast<color_box*>(editor)->set_color(value);
|
||||
}
|
||||
|
||||
void chart_marker_color_delegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
model->setData(index, static_cast<color_box*>(editor)->color(), Qt::EditRole);
|
||||
}
|
||||
|
||||
void chart_marker_color_delegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
//QRect rect(option.rect.left() + 3, option.rect.top() + 3, option.rect.width() - 6, option.rect.height() - 6);
|
||||
editor->setGeometry(option.rect.marginsRemoved(QMargins(1, 1, 1, 1)));
|
||||
|
||||
// editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
void chart_marker_color_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(painter)
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
QSize chart_marker_color_delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QSize s = index.data(Qt::SizeHintRole).toSize();
|
||||
return s.isValid() ? s: QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef BAND_MARKER_COLOR_DELEGATE_H
|
||||
#define BAND_MARKER_COLOR_DELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_marker_color_delegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit chart_marker_color_delegate(QObject *parent = nullptr);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BAND_MARKER_COLOR_DELEGATE_H
|
|
@ -0,0 +1,65 @@
|
|||
#include "gtl_gui_chart_marker_kill_delegate.h"
|
||||
#include "gtl_gui_chart_markers_model.h"
|
||||
|
||||
#include <QToolButton>
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_marker_kill_delegate::chart_marker_kill_delegate(QObject *parent)
|
||||
: QStyledItemDelegate{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QWidget *chart_marker_kill_delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QToolButton *editor = new QToolButton(parent);
|
||||
editor->setIconSize(QSize(16, 16));
|
||||
editor->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
editor->setFixedSize(20, 20);
|
||||
editor->setIcon(QIcon(":/dock/close"));
|
||||
|
||||
((chart_markers_model*)index.model())->connect_kill_signal(editor, index);
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
void chart_marker_kill_delegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(editor)
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
void chart_marker_kill_delegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(editor)
|
||||
Q_UNUSED(model)
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
void chart_marker_kill_delegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
// QRect rect(option.rect.left() + option.rect.width()/2 - editor->width()/2, option.rect.top(), editor->width(), option.rect.height());
|
||||
// editor->setGeometry(rect);
|
||||
QRect rect(option.rect.left() + 3, option.rect.top() + option.rect.height()/2 - editor->height()/2, option.rect.width(), editor->height());
|
||||
editor->setGeometry(rect);
|
||||
|
||||
}
|
||||
|
||||
void chart_marker_kill_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(painter)
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
}
|
||||
|
||||
QSize chart_marker_kill_delegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QSize s = index.data(Qt::SizeHintRole).toSize();
|
||||
return s.isValid() ? s: QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef CHART_MARKER_KILL_DELEGATE_H
|
||||
#define CHART_MARKER_KILL_DELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_marker_kill_delegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit chart_marker_kill_delegate(QObject *parent = nullptr);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKER_KILL_DELEGATE_H
|
|
@ -0,0 +1,119 @@
|
|||
#include "gtl_gui_chart_marker_line.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_marker_line::chart_marker_line(::chart::series::series *parent, int idx, bool is_label_visible, Qt::Orientation orientation)
|
||||
: chart_line(parent, orientation)
|
||||
, _width(15)
|
||||
, _idx(idx)
|
||||
, _is_label_visible(is_label_visible)
|
||||
{
|
||||
setZValue(1);
|
||||
}
|
||||
|
||||
void chart_marker_line::set_idx(int idx)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
_idx = idx;
|
||||
}
|
||||
|
||||
int chart_marker_line::idx() const
|
||||
{
|
||||
return _idx;
|
||||
}
|
||||
|
||||
void chart_marker_line::set_label_visible(bool value)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
_is_label_visible = value;
|
||||
}
|
||||
|
||||
void chart_marker_line::set_label(QString label)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
_lbl_rect.setWidth(100);
|
||||
_label = label;
|
||||
}
|
||||
|
||||
QRectF chart_marker_line::boundingRect() const
|
||||
{
|
||||
QRectF rect = chart::instrument::primitive::line::boundingRect();
|
||||
|
||||
QRectF lbl_rect = _lbl_rect;
|
||||
|
||||
if(_orientation == Qt::Vertical)
|
||||
{
|
||||
if(rect.center().x() - lbl_rect.width() - 3 > 0)
|
||||
lbl_rect.moveTo(rect.center().x() - lbl_rect.width() - 3, rect.top());
|
||||
else
|
||||
lbl_rect.moveTo(rect.center().x() + 3, rect.top());
|
||||
|
||||
return QRectF(rect.center().x() - _width / 2, rect.top(), _width, rect.height()).united(lbl_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rect.center().y() - lbl_rect.height() - 3 > 0)
|
||||
lbl_rect.moveTo(rect.right() - lbl_rect.width() - 3, rect.center().y() - lbl_rect.height() - 3);
|
||||
else
|
||||
lbl_rect.moveTo(rect.right() - lbl_rect.width() - 3, rect.center().y() + 3);
|
||||
|
||||
return QRectF(rect.left(), rect.center().y() - _width / 2, rect.width(), _width).united(lbl_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void chart_marker_line::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
::chart::instrument::primitive::line::paint(painter, option, widget);
|
||||
|
||||
if(_is_label_visible)
|
||||
{
|
||||
|
||||
QString lbl = _label;
|
||||
if(_label.isEmpty())
|
||||
lbl = QString::number(_idx + 1);
|
||||
|
||||
QRectF rect = /*boundingRect()*/chart::instrument::primitive::line::boundingRect();
|
||||
_lbl_rect = painter->fontMetrics().boundingRect(lbl);
|
||||
|
||||
if(_orientation == Qt::Vertical)
|
||||
{
|
||||
if(rect.center().x() - _lbl_rect.width() - 3 > 0)
|
||||
_lbl_rect.moveTo(rect.center().x() - _lbl_rect.width() - 3, rect.top());
|
||||
else
|
||||
_lbl_rect.moveTo(rect.center().x() + 3, rect.top());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rect.center().y() - _lbl_rect.height() - 3 > 0)
|
||||
_lbl_rect.moveTo(rect.right() - _lbl_rect.width() - 3, rect.center().y() - _lbl_rect.height() - 3);
|
||||
else
|
||||
_lbl_rect.moveTo(rect.right() - _lbl_rect.width() - 3, rect.center().y() + 3);
|
||||
}
|
||||
|
||||
painter->drawText(_lbl_rect, Qt::AlignCenter, lbl);
|
||||
}
|
||||
|
||||
qreal dx = _width / 2.0;
|
||||
qreal dy = _width / 2.0;
|
||||
|
||||
QVariantList data;
|
||||
emit get_series_data(pos(), true, data);
|
||||
|
||||
for(int i = 0;i < data.size(); i += 2)
|
||||
{
|
||||
if(data[i].toDouble() == qQNaN())
|
||||
continue;
|
||||
|
||||
qreal y = /*_series->axis_y()->map_to_widget(*/data[i].toDouble()/*)*/;
|
||||
qreal x = _series->axis_x()->map_to_widget(pos());
|
||||
|
||||
painter->setPen(QPen(data[i + 1].value<QColor>(), 0));
|
||||
painter->drawLine((QPointF(x - dx, y - dy)), (QPointF(x + dx, y + dy)));
|
||||
painter->drawLine((QPointF(x - dx, y + dy)), (QPointF(x + dx, y - dy)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef CHART_MARKER_LINE_H
|
||||
#define CHART_MARKER_LINE_H
|
||||
|
||||
#include "gtl_gui_chart_line.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_marker_line : public chart_line
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_marker_line(::chart::series::series *parent, int idx, bool is_label_visible = true, Qt::Orientation orientation = Qt::Vertical);
|
||||
void set_idx(int idx);
|
||||
int idx() const;
|
||||
void set_label_visible(bool value);
|
||||
void set_label(QString label);
|
||||
|
||||
private:
|
||||
qreal _width;
|
||||
int _idx;
|
||||
bool _is_label_visible;
|
||||
QString _label;
|
||||
QRectF _lbl_rect;
|
||||
|
||||
private:
|
||||
QRectF boundingRect() const;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
|
||||
|
||||
signals:
|
||||
void get_series_data(qreal x, bool is_widget_pos, QVariantList &data);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKER_LINE_H
|
|
@ -0,0 +1,296 @@
|
|||
#include "gtl_gui_chart_markers.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class markers_cmp
|
||||
{
|
||||
public:
|
||||
bool operator()(chart_marker* m0, chart_marker* m1) const
|
||||
{
|
||||
return m0->pos() < m1->pos();
|
||||
}
|
||||
};
|
||||
|
||||
chart_markers::chart_markers(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, _color(Qt::black)
|
||||
, _bgnd_color(Qt::white)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant chart_markers::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(orientation == Qt::Vertical)
|
||||
{
|
||||
if(section == 0)
|
||||
return "";
|
||||
else
|
||||
return _series[section - 1]->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
else if (role == Qt::BackgroundRole)
|
||||
{
|
||||
return QVariant(QBrush(/*Qt::white*/_bgnd_color));
|
||||
}
|
||||
else if (role == Qt::ForegroundRole)
|
||||
{
|
||||
if (section == 0)
|
||||
return QVariant(QBrush(/*Qt::black*/_color));
|
||||
else
|
||||
return QVariant(QBrush(_series[section - 1]->color()));
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int chart_markers::rowCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return _series.size() + 1;
|
||||
}
|
||||
|
||||
int chart_markers::columnCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return _markers.size()*2 + 1;
|
||||
}
|
||||
|
||||
QVariant chart_markers::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
return index.row() == 0 ? "x" : "y";
|
||||
if (index.column() % 2 == 1)
|
||||
{
|
||||
if(index.row() != 0)
|
||||
return QVariant(QString::number(index.column() / 2 + 1));
|
||||
}
|
||||
else if (index.row() == 0)
|
||||
return QVariant(QString::number(_markers[(index.column() - 1) / 2]->pos(), 'f', 3));
|
||||
else
|
||||
{
|
||||
qreal value = _markers[(index.column() - 1) / 2]->value(index.row() - 1);
|
||||
return qIsNaN(value) ? "-" : QString::number(value, 'f', 6);
|
||||
}
|
||||
|
||||
}
|
||||
else if (role == Qt::BackgroundRole)
|
||||
{
|
||||
return QVariant(QBrush(/*Qt::white*/_bgnd_color));
|
||||
}
|
||||
else if (role == Qt::ForegroundRole)
|
||||
{
|
||||
if (index.row() == 0)
|
||||
if (index.column() == 0)
|
||||
return QVariant(QBrush(/*Qt::black*/_color));
|
||||
else
|
||||
return QVariant(QBrush(/*Qt::black*//*_color*/_markers[(index.column() - 1) / 2]->color()));
|
||||
else if(index.column() % 2 == 1)
|
||||
return QVariant(QBrush(/*Qt::black*//*_color*/_markers[(index.column() - 1) / 2]->color()));
|
||||
else
|
||||
return QVariant(QBrush(_series[index.row() - 1]->color()));
|
||||
}
|
||||
else if (role == Qt::TextAlignmentRole)
|
||||
return QVariant(Qt::AlignCenter);
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (index.column() % 2 == 1)
|
||||
{
|
||||
if(index.row() == 0)
|
||||
{
|
||||
if(QString(_markers[(index.column() - 1) / 2]->metaObject()->className()).contains("chart_marker"))
|
||||
return QVariant(QPixmap(":chart/single_marker"));
|
||||
else if(QString(_markers[(index.column() - 1) / 2]->metaObject()->className()).contains("band_marker"))
|
||||
return QVariant(QPixmap(":chart/band_marker"));
|
||||
else if(QString(_markers[(index.column() - 1) / 2]->metaObject()->className()).contains("harm_marker"))
|
||||
return QVariant(QPixmap(":chart/harm_marker"));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (role == Qt::SizeHintRole)
|
||||
{
|
||||
if (index.column() % 2 == 1)
|
||||
{
|
||||
if(index.row() == 0)
|
||||
return QVariant(QSize(10, 10));
|
||||
}
|
||||
}
|
||||
*/
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void chart_markers::add_marker(chart_marker *marker)
|
||||
{
|
||||
|
||||
// marker->set_color(_color);
|
||||
|
||||
beginInsertColumns(QModelIndex(), (int)_markers.size(), (int)_markers.size() + 1);
|
||||
|
||||
_markers.push_back(marker);
|
||||
|
||||
endInsertColumns();
|
||||
|
||||
connect(marker, &chart_marker::position_changed, this, &chart_markers::marker_position_changed);
|
||||
connect(marker, &chart_marker::idx_changed, this, &chart_markers::marker_position_changed);
|
||||
|
||||
sort_markers();
|
||||
}
|
||||
|
||||
void chart_markers::remove_marker(chart_marker *marker)
|
||||
{
|
||||
int idx = index_of(marker);
|
||||
beginRemoveColumns(QModelIndex(), idx*2 + 1, idx*2 + 2);
|
||||
_markers.erase(_markers.begin() + idx);
|
||||
endRemoveColumns();
|
||||
|
||||
sort_markers();
|
||||
}
|
||||
|
||||
void chart_markers::add_series(chart_series *series)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), (int)_series.size() + 1, (int)_series.size() + 1);
|
||||
|
||||
_series.push_back(series);
|
||||
|
||||
endInsertRows();
|
||||
|
||||
connect(series, &chart_series::data_changed, this, &chart_markers::series_data_changed);
|
||||
|
||||
if(_series.size() == 1)
|
||||
{
|
||||
foreach(chart_marker* marker, _markers)
|
||||
marker->set_pos();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void chart_markers::remove_series(chart_series *series)
|
||||
{
|
||||
int idx = index_of(series);
|
||||
beginRemoveRows(QModelIndex(), idx + 1, idx + 1);
|
||||
|
||||
_series.erase(_series.begin() + idx);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
}
|
||||
|
||||
chart_marker *chart_markers::marker_at(const QPointF &point) const
|
||||
{
|
||||
foreach(chart_marker* marker, _markers)
|
||||
{
|
||||
if(marker->contains(point))
|
||||
return marker;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int chart_markers::count_markers() const
|
||||
{
|
||||
return (int)_markers.size();
|
||||
}
|
||||
|
||||
chart_marker *chart_markers::marker(int idx) const
|
||||
{
|
||||
return _markers[idx];
|
||||
}
|
||||
|
||||
void chart_markers::set_color(QColor color)
|
||||
{
|
||||
// for(auto marker: _markers)
|
||||
// marker->set_color(color);
|
||||
|
||||
_color = color;
|
||||
|
||||
emit color_changed();
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), QList<int>() << Qt::ForegroundRole);
|
||||
}
|
||||
|
||||
QColor chart_markers::color() const
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void chart_markers::set_bgnd_color(QColor color)
|
||||
{
|
||||
_bgnd_color = color;
|
||||
|
||||
emit color_changed();
|
||||
|
||||
emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1), QList<int>() << Qt::ForegroundRole);
|
||||
}
|
||||
|
||||
QColor chart_markers::bgnd_color() const
|
||||
{
|
||||
return _bgnd_color;
|
||||
}
|
||||
|
||||
|
||||
QVariant chart_markers::get_marker_value(int idx_marker, int idx_series) const
|
||||
{
|
||||
if(_series[idx_series]->size() < 2)
|
||||
return QVariant("-");
|
||||
|
||||
qreal x = _markers[idx_marker]->pos();
|
||||
|
||||
auto it = std::lower_bound(_series[idx_series]->begin_data(), _series[idx_series]->end_data(), QPointF(x, 0), [](
|
||||
const QPointF &p0, const QPointF &p1)
|
||||
{
|
||||
return p0.x() < p1.x();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
if(it->x() == x)
|
||||
return QString::number(it->y(), 'f', 6);
|
||||
|
||||
return QVariant("-");
|
||||
}
|
||||
|
||||
int chart_markers::index_of(chart_marker *marker) const
|
||||
{
|
||||
return std::find(_markers.begin(), _markers.end(), marker) - _markers.begin();
|
||||
}
|
||||
|
||||
int chart_markers::index_of(chart_series *series) const
|
||||
{
|
||||
return std::find(_series.begin(), _series.end(), series) - _series.begin();
|
||||
}
|
||||
|
||||
void chart_markers::sort_markers()
|
||||
{
|
||||
std::sort(_markers.begin(), _markers.end(), markers_cmp());
|
||||
for(int i = 0; i < _markers.size(); i++)
|
||||
_markers[i]->set_idx(i);
|
||||
}
|
||||
|
||||
void chart_markers::marker_position_changed()
|
||||
{
|
||||
sort_markers();
|
||||
|
||||
int idx = index_of(static_cast<chart_marker*>(sender()));
|
||||
emit dataChanged(index(0, idx*2 + 2), index(rowCount() - 1, idx*2 + 1), QList<int>() << Qt::DisplayRole);
|
||||
}
|
||||
|
||||
void chart_markers::series_data_changed()
|
||||
{
|
||||
int idx = index_of(static_cast<chart_series*>(sender()));
|
||||
emit dataChanged(index(idx + 1, 0), index(idx + 1, columnCount() - 1), QList<int>() << Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef CHART_MARKERS_H
|
||||
#define CHART_MARKERS_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "gtl_gui_chart_marker.h"
|
||||
#include "gtl_gui_chart_series.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_markers : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit chart_markers(QObject *parent = nullptr);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void add_marker(chart_marker *marker);
|
||||
void remove_marker(chart_marker* marker);
|
||||
void add_series(chart_series *series);
|
||||
void remove_series(chart_series *series);
|
||||
|
||||
chart_marker* marker_at(const QPointF &point) const;
|
||||
|
||||
int count_markers() const;
|
||||
|
||||
chart_marker* marker(int idx) const;
|
||||
|
||||
|
||||
void set_color(QColor color);
|
||||
QColor color() const;
|
||||
void set_bgnd_color(QColor color);
|
||||
QColor bgnd_color() const;
|
||||
|
||||
private:
|
||||
std::vector<chart_marker*> _markers;
|
||||
std::vector<chart_series*> _series;
|
||||
QColor _color;
|
||||
QColor _bgnd_color;
|
||||
|
||||
private:
|
||||
QVariant get_marker_value(int idx_marker, int idx_series) const;
|
||||
int index_of(chart_marker* marker) const;
|
||||
int index_of(chart_series* series) const;
|
||||
void sort_markers();
|
||||
|
||||
signals:
|
||||
void color_changed();
|
||||
|
||||
private slots:
|
||||
void marker_position_changed();
|
||||
void series_data_changed();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKERS_H
|
|
@ -0,0 +1,30 @@
|
|||
#include "gtl_gui_chart_markers_item_delegate.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_markers_item_delegate::chart_markers_item_delegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void chart_markers_item_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
painter->fillRect(option.rect, /*Qt::black*/index.data(Qt::BackgroundRole).value<QColor>());
|
||||
|
||||
painter->setPen(index.data(Qt::ForegroundRole).value<QColor>());
|
||||
painter->drawText(option.rect, option.decorationAlignment, index.data().toString());
|
||||
|
||||
painter->drawPixmap(QRect(option.rect.left() + option.rect.width()/2 - 8, option.rect.top() + option.rect.height()/2 - 8, 16, 16), index.data(Qt::DecorationRole).value<QPixmap>(), index.data(Qt::DecorationRole).value<QPixmap>().rect());
|
||||
|
||||
painter->setPen(Qt::darkGray);
|
||||
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
|
||||
if (index.column() == 0 || index.column() % 2 == 0)
|
||||
painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
|
||||
if(index.column() == 0)
|
||||
painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef CHART_MARKERS_ITEM_DELEGATE_H
|
||||
#define CHART_MARKERS_ITEM_DELEGATE_H
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QPainter>
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_markers_item_delegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
chart_markers_item_delegate(QObject *parent);
|
||||
private:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKERS_ITEM_DELEGATE_H
|
|
@ -0,0 +1,95 @@
|
|||
#include "gtl_gui_chart_markers_model.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_markers_model::chart_markers_model(QObject *parent)
|
||||
: QAbstractItemModel{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
chart_marker *chart_markers_model::at(int idx) const
|
||||
{
|
||||
return _markers[idx];
|
||||
}
|
||||
|
||||
void chart_markers_model::add(chart_marker *marker)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), (int)_markers.size(), (int)_markers.size());
|
||||
|
||||
_markers.push_back(marker);
|
||||
|
||||
connect(marker, &chart_marker::position_changed, this, &chart_markers_model::marker_changed);
|
||||
connect(marker, &chart_marker::idx_changed, this, &chart_markers_model::marker_index_changed);
|
||||
connect(marker, &chart_marker::deleting, this, &chart_markers_model::marker_deleting);
|
||||
|
||||
endInsertRows();
|
||||
|
||||
// for openPersistentEditor
|
||||
emit dataChanged(index(-1, -1), index(-1, -1));
|
||||
}
|
||||
|
||||
void chart_markers_model::remove(chart_marker *marker)
|
||||
{
|
||||
auto it = std::find(_markers.begin(), _markers.end(), marker);
|
||||
if(it == _markers.end())
|
||||
return;
|
||||
|
||||
int idx = std::distance(_markers.begin(), it);
|
||||
beginRemoveRows(QModelIndex(), idx, idx);
|
||||
|
||||
_markers.erase(it);
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
}
|
||||
|
||||
int chart_markers_model::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
return 0;
|
||||
|
||||
return _markers.size();
|
||||
}
|
||||
|
||||
QModelIndex chart_markers_model::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QModelIndex chart_markers_model::parent(const QModelIndex &index) const
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void chart_markers_model::connect_color_changed_signal(color_box *sender, const QModelIndex &index)
|
||||
{
|
||||
connect(sender, &color_box::color_changed, _markers[index.row()], &chart_marker::set_color);
|
||||
}
|
||||
|
||||
void chart_markers_model::connect_kill_signal(QAbstractButton *sender, const QModelIndex &index)
|
||||
{
|
||||
connect(sender, &QAbstractButton::clicked, _markers[index.row()], &chart_marker::deleteLater);
|
||||
}
|
||||
|
||||
void chart_markers_model::marker_index_changed()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
std::sort(_markers.begin(), _markers.end(), [](chart_marker* marker0, chart_marker* marker1){return marker0->idx() < marker1->idx();});
|
||||
|
||||
endResetModel();
|
||||
|
||||
emit changed();
|
||||
|
||||
// emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
|
||||
}
|
||||
|
||||
void chart_markers_model::marker_deleting()
|
||||
{
|
||||
remove(static_cast<chart_marker*>(sender()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef CHART_MARKERS_MODEL_H
|
||||
#define CHART_MARKERS_MODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "gui/gtl_gui_chart_marker.h"
|
||||
#include "gui/gtl_gui_color_box.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_markers_model : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit chart_markers_model(QObject *parent = nullptr);
|
||||
chart_marker* at(int idx) const;
|
||||
|
||||
virtual void add(chart_marker* marker);
|
||||
void remove(chart_marker* marker);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
|
||||
virtual QModelIndex parent(const QModelIndex& index) const override;
|
||||
|
||||
virtual void connect_color_changed_signal(color_box* sender, const QModelIndex& index);
|
||||
virtual void connect_kill_signal(QAbstractButton* sender, const QModelIndex& index);
|
||||
|
||||
protected:
|
||||
std::vector<chart_marker*> _markers;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
protected slots:
|
||||
virtual void marker_changed() = 0;
|
||||
virtual void marker_index_changed();
|
||||
virtual void marker_deleting();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MARKERS_H
|
|
@ -0,0 +1,145 @@
|
|||
#include "gtl_gui_chart_markers_view.h"
|
||||
|
||||
#include "gtl_gui_chart_markers_item_delegate.h"
|
||||
#include "gtl_gui_chart_markers.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_markers_view::chart_markers_view(QWidget* parent)
|
||||
: QTableView(parent)
|
||||
{
|
||||
setItemDelegate(new chart_markers_item_delegate(this));
|
||||
|
||||
setCornerButtonEnabled(false);
|
||||
setShowGrid(false);
|
||||
|
||||
QFont font("MS Shell Dlg 2", 8);
|
||||
setFont(font);
|
||||
|
||||
setSelectionMode(QAbstractItemView::SelectionMode::NoSelection);
|
||||
setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
|
||||
verticalHeader()->setDefaultSectionSize(18);
|
||||
verticalHeader()->setFont(font);
|
||||
verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
horizontalHeader()->setVisible(false);
|
||||
horizontalHeader()->setMaximumHeight(16);
|
||||
horizontalHeader()->setMinimumSectionSize(0);
|
||||
horizontalHeader()->setFont(font);
|
||||
|
||||
set_height();
|
||||
}
|
||||
|
||||
void chart_markers_view::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTableView::setModel(model);
|
||||
|
||||
connect(model, &QAbstractItemModel::rowsInserted, this, &chart_markers_view::rows_and_columns_count_changed);
|
||||
connect(model, &QAbstractItemModel::rowsRemoved, this, &chart_markers_view::rows_and_columns_count_changed);
|
||||
connect(model, &QAbstractItemModel::columnsInserted, this, &chart_markers_view::rows_and_columns_count_changed);
|
||||
connect(model, &QAbstractItemModel::columnsRemoved, this, &chart_markers_view::rows_and_columns_count_changed);
|
||||
|
||||
connect(static_cast<chart_markers*>(model), &chart_markers::color_changed, this, &chart_markers_view::markers_color_changed);
|
||||
|
||||
markers_color_changed();
|
||||
|
||||
}
|
||||
|
||||
void chart_markers_view::set_height()
|
||||
{
|
||||
int height = 0;
|
||||
|
||||
if(model() == NULL)
|
||||
{
|
||||
|
||||
}
|
||||
else if(model()->rowCount() > 1 && model()->columnCount() > 2)
|
||||
{
|
||||
height = horizontalHeader()->height();
|
||||
|
||||
if (model()->columnCount() == 0)
|
||||
{
|
||||
// height = 0;
|
||||
// setVisible(false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// setVisible(true);
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < model()->rowCount(); i++)
|
||||
height += rowHeight(i)/* + 1*/;
|
||||
}
|
||||
|
||||
if (horizontalScrollBar()->isVisible())
|
||||
{
|
||||
height += horizontalScrollBar()->height();
|
||||
}
|
||||
}
|
||||
|
||||
height += 2;
|
||||
|
||||
|
||||
|
||||
|
||||
setMinimumSize(0, height);
|
||||
setMaximumSize(1000000, height);
|
||||
|
||||
if(model() == NULL)
|
||||
return;
|
||||
|
||||
QFontMetrics metrics(font());
|
||||
|
||||
for (int i = 0; i < model()->columnCount(); i++)
|
||||
{
|
||||
QString str = model()->data(model()->index(0, i), Qt::DisplayRole).toString();
|
||||
QRect rect = metrics.boundingRect(str);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
setColumnWidth(i, rect.width() + 10);
|
||||
horizontalHeader()->setSectionResizeMode(i, QHeaderView::Fixed);
|
||||
}
|
||||
else if (i % 2 == 1)
|
||||
{
|
||||
if (rowSpan(1, i) != model()->rowCount())
|
||||
setSpan(1, i, model()->rowCount(), 1);
|
||||
|
||||
setColumnWidth(i, rect.width() + 10);
|
||||
horizontalHeader()->setSectionResizeMode(i, QHeaderView::Fixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (columnWidth(i) < rect.width() + 10)
|
||||
setColumnWidth(i, rect.width() + 10);
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chart_markers_view::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QTableView::resizeEvent(event);
|
||||
|
||||
set_height();
|
||||
}
|
||||
|
||||
|
||||
void chart_markers_view::rows_and_columns_count_changed(const QModelIndex &/*parent*/, int/* start*/, int/* end*/)
|
||||
{
|
||||
set_height();
|
||||
}
|
||||
|
||||
void chart_markers_view::markers_color_changed()
|
||||
{
|
||||
setStyleSheet( "QTableView{background-color: " + static_cast<chart_markers*>(model())->bgnd_color().name() + ";}" + "QHeaderView:section{background-color: " + static_cast<chart_markers*>(model())->bgnd_color().name() + "; color: " + static_cast<chart_markers*>(model())->color().name() + "; border-style:none; border-bottom: 1px solid #808080;}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef CHART_MARKERS_VIEW_H
|
||||
#define CHART_MARKERS_VIEW_H
|
||||
|
||||
#include <QTableView>
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_markers_view : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_markers_view(QWidget* parent = NULL);
|
||||
virtual void setModel(QAbstractItemModel *model) override;
|
||||
|
||||
private:
|
||||
void set_height();
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private slots:
|
||||
virtual void rows_and_columns_count_changed(const QModelIndex& parent, int start, int end);
|
||||
void markers_color_changed();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_MARKERS_VIEW_H
|
|
@ -0,0 +1,160 @@
|
|||
#include "gtl_gui_chart_series.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_series::chart_series(gtl::analog_data* ad, chart::axis_horz* axis_x, chart::axis_vert* axis_y)
|
||||
: chart::series::xy::line(axis_x, axis_y)
|
||||
, _ad(ad)
|
||||
, _updater(this)
|
||||
, _is_updating(true)
|
||||
{
|
||||
connect(&_updater, &QThread::finished, this, &chart_series::update_series);
|
||||
connect(&_updater, &QThread::finished, this, &chart_series::data_changed);
|
||||
|
||||
if(_ad)
|
||||
{
|
||||
connect(_ad, >l::analog_data::color_changed, this, &chart_series::set_icolor);
|
||||
set_icolor();
|
||||
}
|
||||
}
|
||||
|
||||
chart_series::~chart_series()
|
||||
{
|
||||
_updater.terminate();
|
||||
}
|
||||
|
||||
void chart_series::set_updating(bool value)
|
||||
{
|
||||
_is_updating = value;
|
||||
}
|
||||
|
||||
analog_data *chart_series::ad()
|
||||
{
|
||||
return _ad;
|
||||
}
|
||||
|
||||
QString chart_series::name() const
|
||||
{
|
||||
if(_ad)
|
||||
return _ad->name();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
qreal chart_series::left() const
|
||||
{
|
||||
if(empty())
|
||||
return 0;
|
||||
|
||||
return front_x();
|
||||
}
|
||||
|
||||
qreal chart_series::right() const
|
||||
{
|
||||
if(empty())
|
||||
return 0;
|
||||
|
||||
return back_x();
|
||||
}
|
||||
|
||||
qreal chart_series::get_y(qreal x)
|
||||
{
|
||||
if(size() < 2)
|
||||
return 0;
|
||||
|
||||
qreal x_[2];
|
||||
qreal y_[2];
|
||||
int idx = 0;
|
||||
|
||||
if(x < front_x())
|
||||
{
|
||||
idx = 0;
|
||||
}
|
||||
else if(x > back_x())
|
||||
{
|
||||
idx = size() - 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
qreal dx = at_x(1) - at_x(0);
|
||||
idx = (x - at_x(0))/dx;
|
||||
}
|
||||
|
||||
x_[0] = at_x(idx);
|
||||
x_[1] = at_x(idx + 1);
|
||||
y_[0] = at_y(idx);
|
||||
y_[1] = at_y(idx + 1);
|
||||
|
||||
qreal a = (y_[0] - y_[1])/(x_[0] - x_[1]);
|
||||
qreal b = y_[0] - a*x_[0];
|
||||
|
||||
return a*x + b;
|
||||
}
|
||||
|
||||
void chart_series::set_tool_tip(QPoint pos)
|
||||
{
|
||||
setToolTip("");
|
||||
}
|
||||
|
||||
update_thread::update_thread(chart::series::xy::line *s)
|
||||
: QThread(NULL)
|
||||
, _series(s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void update_thread::set_data(std::vector<qreal> &data)
|
||||
{
|
||||
_mutex.lock();
|
||||
_data = data;
|
||||
_is_updated = true;
|
||||
_mutex.unlock();
|
||||
|
||||
if(!isRunning())
|
||||
start();
|
||||
}
|
||||
|
||||
void update_thread::get_data(std::back_insert_iterator<std::vector<qreal>> data)
|
||||
{
|
||||
std::copy(_data.begin(), _data.end(), data);
|
||||
}
|
||||
|
||||
void update_thread::stop()
|
||||
{
|
||||
_is_running = false;
|
||||
wait();
|
||||
}
|
||||
|
||||
void update_thread::run()
|
||||
{
|
||||
_is_running = true;
|
||||
while(_is_updated)
|
||||
{
|
||||
_mutex.lock();
|
||||
std::vector<qreal> buffer = _data;
|
||||
_is_updated = false;
|
||||
_mutex.unlock();
|
||||
|
||||
for(int i = 0; i < buffer.size(); i++)
|
||||
{
|
||||
_series->set_y(i, buffer[i], false);
|
||||
if(!_is_running)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chart_series::update_series()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
}
|
||||
|
||||
void chart_series::set_icolor()
|
||||
{
|
||||
set_color(QColor(_ad->color()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#ifndef SERIES_H
|
||||
#define SERIES_H
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "chart/series/xy/series_line.h"
|
||||
|
||||
#include "core/gtl_analog_data.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT update_thread: public QThread
|
||||
{
|
||||
public:
|
||||
update_thread(chart::series::xy::line *s);
|
||||
void set_data(std::vector<qreal> &data);
|
||||
void get_data(std::back_insert_iterator<std::vector<qreal>> data);
|
||||
void stop();
|
||||
|
||||
private:
|
||||
chart::series::xy::line* _series;
|
||||
std::vector<qreal> _data;
|
||||
bool _is_updated;
|
||||
QMutex _mutex;
|
||||
bool _is_running;
|
||||
|
||||
private:
|
||||
void run();
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
class GTL_GUI_EXPORT chart_series : public chart::series::xy::line
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_series(gtl::analog_data* ad, chart::axis_horz* axis_x, chart::axis_vert* axis_y);
|
||||
virtual ~chart_series();
|
||||
|
||||
void set_updating(bool value);
|
||||
|
||||
gtl::analog_data* ad();
|
||||
|
||||
virtual QString name() const;
|
||||
virtual qreal left() const;
|
||||
virtual qreal right() const;
|
||||
|
||||
virtual void set_tool_tip(QPoint pos);
|
||||
|
||||
protected:
|
||||
gtl::analog_data* _ad;
|
||||
update_thread _updater;
|
||||
bool _is_updating;
|
||||
|
||||
protected:
|
||||
qreal get_y(qreal x);
|
||||
|
||||
private slots:
|
||||
void update_series();
|
||||
void set_icolor();
|
||||
|
||||
signals:
|
||||
void data_changed();
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif // SERIES_H
|
|
@ -0,0 +1,104 @@
|
|||
#include "gtl_gui_chart_single_markers.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_single_markers::chart_single_markers(QObject *parent)
|
||||
: chart_markers_model{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant chart_single_markers::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(orientation == Qt::Horizontal)
|
||||
{
|
||||
if(section == 0)
|
||||
return tr("ID");
|
||||
else if(section == 1)
|
||||
return tr("pos");
|
||||
else if(section == 2)
|
||||
return tr("color");
|
||||
else if(section == 3)
|
||||
return tr("kill");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int chart_single_markers::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant chart_single_markers::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(index.column() == 0)
|
||||
return _markers[index.row()]->idx() + 1;
|
||||
else if(index.column() == 1)
|
||||
return _markers[index.row()]->pos();
|
||||
else if(index.column() == 2)
|
||||
return _markers[index.row()]->color();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool chart_single_markers::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if(index.column() == 1)
|
||||
{
|
||||
bool is_ok;
|
||||
qreal double_value = value.toDouble(&is_ok);
|
||||
|
||||
if (is_ok)
|
||||
{
|
||||
|
||||
_markers[index.row()]->set_pos(double_value);
|
||||
|
||||
emit dataChanged(chart_markers_model::index(index.row(), 1), chart_markers_model::index(index.row(), 3), {Qt::DisplayRole});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(index.column() == 2)
|
||||
{
|
||||
_markers[index.row()]->set_color(value.value<QColor>());
|
||||
|
||||
emit dataChanged(chart_markers_model::index(index.row(), 2), chart_markers_model::index(index.row(), 2), {Qt::DisplayRole});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags chart_single_markers::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
|
||||
|
||||
if(index.column() >= 1 && index.column() <= 2)
|
||||
flags |= Qt::ItemIsEditable;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void chart_single_markers::marker_changed()
|
||||
{
|
||||
auto it = std::find(_markers.begin(), _markers.end(), sender());
|
||||
int idx = std::distance(_markers.begin(), it);
|
||||
if(idx < _markers.size())
|
||||
emit dataChanged(index(idx, 1), index(idx, 1));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef SINGLE_MARKERS_H
|
||||
#define SINGLE_MARKERS_H
|
||||
|
||||
#include "gtl_gui_chart_markers_model.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class chart_single_markers : public chart_markers_model
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit chart_single_markers(QObject *parent = nullptr);
|
||||
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Basic functionality:
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Editable:
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
|
||||
private slots:
|
||||
virtual void marker_changed() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SINGLE_MARKERS_H
|
|
@ -0,0 +1,58 @@
|
|||
#include "gtl_gui_chart_single_markers_view.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include "gui/gtl_gui_chart_marker_color_delegate.h"
|
||||
#include "gui/gtl_gui_chart_marker_kill_delegate.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_single_markers_view::chart_single_markers_view(chart_single_markers* markers, QWidget *parent)
|
||||
: QTreeView(parent)
|
||||
, _markers(markers)
|
||||
{
|
||||
// verticalHeader()->setDefaultSectionSize(24);
|
||||
setModel(markers);
|
||||
setItemDelegateForColumn(2, new chart_marker_color_delegate(this));
|
||||
setItemDelegateForColumn(3, new chart_marker_kill_delegate(this));
|
||||
setColumnWidth(3, 30);
|
||||
/*
|
||||
connect(markers,
|
||||
&QAbstractItemModel::dataChanged,
|
||||
[=](const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||
{
|
||||
for(int i = 0; i < markers->rowCount(); i++)
|
||||
{
|
||||
openPersistentEditor(markers->index(i, 2));
|
||||
openPersistentEditor(markers->index(i, 3));
|
||||
}
|
||||
}
|
||||
);
|
||||
*/
|
||||
connect(markers,
|
||||
&QAbstractItemModel::rowsInserted,
|
||||
[=](const QModelIndex &parent, int first, int last)
|
||||
{
|
||||
for(int i = first; i <= last; i++)
|
||||
{
|
||||
openPersistentEditor(markers->index(i, 2, parent));
|
||||
openPersistentEditor(markers->index(i, 3, parent));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
connect(markers, >l::gui::chart_markers_model::changed, this, &chart_single_markers_view::open_persistent_editors);
|
||||
}
|
||||
|
||||
void chart_single_markers_view::open_persistent_editors()
|
||||
{
|
||||
for(int i = 0; i < _markers->rowCount(); i++)
|
||||
{
|
||||
openPersistentEditor(_markers->index(i, 2));
|
||||
openPersistentEditor(_markers->index(i, 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef CHART_SINGLE_MARKERS_VIEW_H
|
||||
#define CHART_SINGLE_MARKERS_VIEW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
#include "gtl_gui_chart_single_markers.h"
|
||||
|
||||
#include "gui/gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_single_markers_view : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
chart_single_markers_view(chart_single_markers* markers, QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
chart_single_markers* _markers;
|
||||
|
||||
private slots:
|
||||
void open_persistent_editors();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_SINGLE_MARKERS_VIEW_H
|
|
@ -0,0 +1,22 @@
|
|||
#include "gtl_gui_chart_widget.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
chart_widget::chart_widget(chart *chart, QWidget *parent)
|
||||
: QWidget{parent}
|
||||
{
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->setContentsMargins(0, 0, 0, 0);
|
||||
layout()->setSpacing(0);
|
||||
|
||||
layout()->addWidget(chart);
|
||||
|
||||
/*chart_markers_view*/QTableView* view = new chart_markers_view(this);
|
||||
layout()->addWidget(view);
|
||||
|
||||
view->setModel(chart->chart_markers_model());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef GTL_GUI_CHART_WIDGET_H
|
||||
#define GTL_GUI_CHART_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "gtl_gui_chart.h"
|
||||
#include "gtl_gui_chart_markers_view.h"
|
||||
|
||||
#include "gui_global.h"
|
||||
|
||||
namespace gtl
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class GTL_GUI_EXPORT chart_widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit chart_widget(chart *chart, QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CHART_WIDGET_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue