tree changes

This commit is contained in:
2020-08-19 16:22:10 +03:00
parent 76d9604282
commit d0148bf460
356 changed files with 5334 additions and 6298 deletions

1
piqt/libs/CMakeLists.txt Normal file
View File

@@ -0,0 +1 @@
add_directories_with_include("piqt_")

View File

@@ -0,0 +1 @@
piqt_library(piqt "Gui;Positioning" "qad_utils;qad_widgets")

141
piqt/libs/core/piqt.cpp Normal file
View File

@@ -0,0 +1,141 @@
#include "piqt.h"
#include "qvariantedit.h"
#if QT_VERSION >= 0x050200
# include <QGeoCoordinate>
#endif
const QAD::Enum PI2QADEnum(const PIVariantTypes::Enum & el) {
QAD::Enum ret;
piForeachC (PIVariantTypes::Enumerator & e, el.enum_list)
ret << QAD::Enumerator(e.value, PI2QString(e.name));
ret.selectValue(el.selectedValue());
return ret;
}
const PIVariantTypes::Enum QAD2PIEnum(const QAD::Enum & el) {
PIVariantTypes::Enum ret;
foreach (const QAD::Enumerator & e, el.enum_list)
ret << PIVariantTypes::Enumerator(e.value, Q2PIString(e.name));
ret.selectValue(el.selectedValue());
return ret;
}
const QVariant PI2QVariant(const PIVariant & v) {
switch (v.type()) {
case PIVariant::pivBool: return QVariant(v.toBool());
case PIVariant::pivChar:
case PIVariant::pivUChar:
case PIVariant::pivShort:
case PIVariant::pivUShort:
case PIVariant::pivInt: return QVariant(v.toInt());
case PIVariant::pivUInt: return QVariant(uint(v.toInt()));
case PIVariant::pivLLong: return QVariant(v.toLLong());
case PIVariant::pivULLong: return QVariant(ullong(v.toLLong()));
case PIVariant::pivFloat: return QVariant(v.toFloat());
case PIVariant::pivDouble: return QVariant(v.toDouble());
case PIVariant::pivLDouble: return QVariant(v.toDouble());
case PIVariant::pivByteArray: return QVariant(PI2QByteArray(v.toByteArray()));
case PIVariant::pivString: return QVariant(PI2QString(v.toString()));
case PIVariant::pivStringList: return QVariant(PI2QStringList(v.toStringList()));
case PIVariant::pivTime: return QVariant(PI2QTime(v.toTime()));
case PIVariant::pivDate: return QVariant(PI2QDate(v.toDate()));
case PIVariant::pivDateTime: return QVariant(PI2QDateTime(v.toDateTime()));
case PIVariant::pivEnum: return QVariant::fromValue(PI2QADEnum(v.toEnum()));
case PIVariant::pivFile: return QVariant::fromValue(PI2QADFile(v.toFile()));
case PIVariant::pivDir: return QVariant::fromValue(PI2QADDir(v.toDir()));
case PIVariant::pivColor: return QVariant::fromValue(PI2QColor(v.toColor()));
case PIVariant::pivPoint: return QVariant(PI2QPoint(v.toPoint()));
case PIVariant::pivRect: return QVariant(PI2QRect(v.toRect()));
case PIVariant::pivIODevice: return QVariant::fromValue(PI2QADIODevice(v.toIODevice()));
case PIVariant::pivMathVector: return QVariant::fromValue(PI2QMathVector(v.toMathVector()));
case PIVariant::pivMathMatrix: return QVariant::fromValue(PI2QMathMatrix(v.toMathMatrix()));
//case PIVariant::pivSystemTime: return QVariant(v.to());
default: return QVariant();
}
return QVariant();
}
const PIVariant Q2PIVariant(const QVariant & v) {
switch (v.type()) {
case QVariant::Bool: return PIVariant(v.toBool());
case QVariant::Int: return PIVariant(v.toInt());
case QVariant::UInt: return PIVariant(v.toUInt());
case QVariant::LongLong: return PIVariant(v.toLongLong());
case QVariant::ULongLong: return PIVariant(v.toULongLong());
case QVariant::Double: return PIVariant(v.toDouble());
case QVariant::ByteArray: return PIVariant(Q2PIByteArray(v.toByteArray()));
case QVariant::String: return PIVariant(Q2PIString(v.toString()));
case QVariant::StringList: return PIVariant(Q2PIStringList(v.toStringList()));
case QVariant::Time: return PIVariant(Q2PITime(v.toTime()));
case QVariant::Date: return PIVariant(Q2PIDate(v.toDate()));
case QVariant::DateTime: return PIVariant(Q2PIDateTime(v.toDateTime()));
case QVariant::Color: return PIVariant(Q2PIColor(v.value<QColor>()));
case QVariant::Point:
case QVariant::PointF: return PIVariant(Q2PIPoint(v.toPointF()));
case QVariant::Rect:
case QVariant::RectF: return PIVariant(Q2PIRect(v.toRectF()));
default: break;
}
if (v.canConvert<QAD::Enum>()) return PIVariant(QAD2PIEnum(v.value<QAD::Enum>()));
if (v.canConvert<QAD::File>()) return PIVariant(QAD2PIFile(v.value<QAD::File>()));
if (v.canConvert<QAD::Dir>()) return PIVariant(QAD2PIDir(v.value<QAD::Dir>()));
if (v.canConvert<QAD::IODevice>()) return PIVariant(QAD2PIIODevice(v.value<QAD::IODevice>()));
if (v.canConvert<QAD::MathVector>()) return PIVariant(Q2PIMathVector(v.value<QAD::MathVector>()));
if (v.canConvert<QAD::MathMatrix>()) return PIVariant(Q2PIMathMatrix(v.value<QAD::MathMatrix>()));
return PIVariant();
}
const PIVariantTypes::IODevice QAD2PIIODevice(const QAD::IODevice & v) {
PIVariantTypes::IODevice d;
d.set(Q2PIPropertyStorage(v.props));
d.prefix = Q2PIString(v.prefix);
d.mode = v.mode;
d.options = v.options;
return d;
}
const QAD::IODevice PI2QADIODevice(const PIVariantTypes::IODevice & v) {
return QAD::IODevice(PI2QString(v.prefix), PI2QPropertyStorage(v.get()), v.mode, v.options);
}
const QAD::File PI2QADFile(const PIVariantTypes::File & v) {
return QAD::File(PI2QString(v.file), PI2QString(v.filter), v.is_abs, v.is_save);
}
const QAD::Dir PI2QADDir(const PIVariantTypes::Dir & v) {
return QAD::Dir(PI2QString(v.dir), v.is_abs);
}
const PIVariantTypes::File QAD2PIFile(const QAD::File & v) {
return PIVariantTypes::File(Q2PIString(v.file), Q2PIString(v.filter), v.is_abs, v.is_save);
}
const PIVariantTypes::Dir QAD2PIDir(const QAD::Dir & v) {
return PIVariantTypes::Dir(Q2PIString(v.dir), v.is_abs);
}
#if QT_VERSION >= 0x050200
const QGeoCoordinate PI2QGeoPosition(const PIGeoPosition & v) {
PIGeoPosition p(v);
p.transformTo(PIGeoPosition::Cartesian);
p.setEllipsoidModel(PIEllipsoidModel::WGS84Ellipsoid());
p.transformTo(PIGeoPosition::Geodetic);
return QGeoCoordinate(p.latitudeGeodetic(), p.longitude(), p.height());
}
const PIGeoPosition Q2PIGeoPosition(const QGeoCoordinate & v) {
return PIGeoPosition(createVectorT3d(v.latitude(), v.longitude(), v.altitude()), PIGeoPosition::Geodetic);
}
#endif

168
piqt/libs/core/piqt.h Normal file
View File

@@ -0,0 +1,168 @@
/*
PIQt - PIP <-> Qt convertions
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIQT_H
#define PIQT_H
#include "pimathmatrix.h"
#include "pipropertystorage.h"
#include "qad_types.h"
#include <QVector3D>
#include <QDateTime>
#include <QColor>
#if QT_VERSION >= 0x050200
# include "pigeoposition.h"
#endif
class QGeoCoordinate;
const QVariant PI2QVariant(const PIVariant & v);
const PIVariant Q2PIVariant(const QVariant & v);
//inline const QString PI2QString(const PIString & v) {return QString::fromLocal8Bit(v.data());}
inline const QString PI2QString(const PIString & v) {return QString::fromUtf8(v.dataUTF8());}
//inline const PIString Q2PIString(const QString & v) {return PIString(v.toLocal8Bit().data());}
inline const PIString Q2PIString(const QString & v) {return PIString::fromUTF8(v.toUtf8().data());}
inline const QStringList PI2QStringList(const PIStringList & v) {QStringList ret; piForeachC (PIString & s, v) ret << PI2QString(s); return ret;}
inline const PIStringList Q2PIStringList(const QStringList & v) {PIStringList ret; foreach (const QString & s, v) ret << Q2PIString(s); return ret;}
inline const QByteArray PI2QByteArray(const PIByteArray & v) {return QByteArray((const char *)(v.data()), v.size_s());}
inline const PIByteArray Q2PIByteArray(const QByteArray & v) {return PIByteArray(v.constData(), v.size());}
inline const QPointF PI2QVector2(const PIMathVectorT2d & v) {return QPointF(v[0], v[1]);}
inline const QVector3D PI2QVector3(const PIMathVectorT3d & v) {return QVector3D(v[0], v[1], v[2]);}
inline const PIMathVectorT2d Q2PIVector2(const QPointF & v) {return createVectorT2d(double(v.x()), double(v.y()));}
inline const PIMathVectorT3d Q2PIVector3(const QVector3D & v) {return createVectorT3d(double(v.x()), double(v.y()), double(v.z()));}
inline const QPointF PI2QPoint(const PIPointd & v) {return QPointF(v.x, v.y);}
inline const PIPointd Q2PIPoint(const QPointF & v) {return PIPointd(v.x(), v.y());}
inline const QRectF PI2QRect(const PIRectd & v) {return QRectF(v.x0, v.y0, v.width(), v.height());}
inline const PIRectd Q2PIRect(const QRectF & v) {return PIRectd(v.x(), v.y(), v.width(), v.height());}
inline const QAD::MathVector PI2QMathVector(const PIMathVectord & v) {
QVector<double> q = QVector<double>(v.size());
memcpy(q.data(), v.data(), q.size()*sizeof(double));
return QAD::MathVector(q);
}
inline const PIMathVectord Q2PIMathVector(const QAD::MathVector & v) {
PIMathVectord p = PIMathVectord(v.v.size());
memcpy(p.data(), v.v.data(), p.size()*sizeof(double));
return p;
}
inline const QAD::MathMatrix PI2QMathMatrix(const PIMathMatrixd & v) {
PIVector<PIVector<double> > p = v.toVectors();
QVector<QVector<double> > q = QVector<QVector<double> >(p.size());
for (int i = 0; i < q.size(); ++i) {
q[i].resize(p[i].size());
memcpy(q[i].data(), p[i].data(), q[i].size()*sizeof(double));
}
return QAD::MathMatrix(q);
}
inline const PIMathMatrixd Q2PIMathMatrix(const QAD::MathMatrix & v) {
PIVector<PIVector<double> > p = PIVector<PIVector<double> >(v.m.size());
for (int i = 0; i < v.m.size(); ++i) {
p[i].resize(v.m[i].size());
memcpy(p[i].data(), v.m[i].data(), p[i].size()*sizeof(double));
}
return PIMathMatrixd(p);
}
inline const QDate PI2QDate(const PIDate & v) {return QDate(v.year, v.month, v.day);}
inline const QTime PI2QTime(const PITime & v) {return QTime(v.hours, v.minutes, v.seconds, v.milliseconds);}
inline const QDateTime PI2QDateTime(const PIDateTime & v) {return QDateTime(PI2QDate(v.date()), PI2QTime(v.time()));}
inline const PIDate Q2PIDate(const QDate & v) {return PIDate(v.year(), v.month(), v.day());}
inline const PITime Q2PITime(const QTime & v) {return PITime(v.hour(), v.minute(), v.second(), v.msec());}
inline const PIDateTime Q2PIDateTime(const QDateTime & v) {return PIDateTime(Q2PIDate(v.date()), Q2PITime(v.time()));}
inline const QColor PI2QColor(const PIVariantTypes::Color & v) {return QColor::fromRgba(v.rgba);}
inline const PIVariantTypes::Color Q2PIColor(const QColor & v) {return PIVariantTypes::Color(v.rgba());}
inline PIPropertyStorage Q2PIPropertyStorage(const PropertyStorage & props) {
PIPropertyStorage ret;
foreach (const PropertyStorage::Property & p, props)
ret.addProperty(Q2PIString(p.name), Q2PIVariant(p.value), Q2PIString(p.comment), p.flags);
return ret;
}
inline PropertyStorage PI2QPropertyStorage(const PIPropertyStorage & props) {
PropertyStorage ret;
piForeachC (PIPropertyStorage::Property & p, props)
ret.addProperty(PI2QString(p.name), PI2QVariant(p.value), PI2QString(p.comment), p.flags);
return ret;
}
const QAD::Enum PI2QADEnum(const PIVariantTypes::Enum & el);
const QAD::File PI2QADFile(const PIVariantTypes::File & v);
const QAD::Dir PI2QADDir(const PIVariantTypes::Dir & v);
const QAD::IODevice PI2QADIODevice(const PIVariantTypes::IODevice & v);
const PIVariantTypes::Enum QAD2PIEnum(const QAD::Enum & el);
const PIVariantTypes::File QAD2PIFile(const QAD::File & v);
const PIVariantTypes::Dir QAD2PIDir(const QAD::Dir & v);
const PIVariantTypes::IODevice QAD2PIIODevice(const QAD::IODevice & v);
//inline const PIVariant QString2PIVariant(const QString & v) {return PIVariant::readFromString(QString2PIString(v));}
#if QT_VERSION >= 0x050200
const QGeoCoordinate PI2QGeoPosition(const PIGeoPosition & v);
const PIGeoPosition Q2PIGeoPosition(const QGeoCoordinate & v);
#endif
template <typename From>
class __PIQtConverter {
public:
__PIQtConverter(const From & v): val(v) {}
template <typename To> operator To() {return To();}
From val;
};
template<typename From> inline __PIQtConverter<From> __PIQtConvert(const From & f) {return __PIQtConverter<From>(f);}
#define _PIQt_CONVERT(ft, tt, ftc, tfc) \
template<> template<> inline __PIQtConverter<ft>::operator tt() {return ftc(val);} \
template<> template<> inline __PIQtConverter<tt>::operator ft() {return tfc(val);}
#define _PIQt_CONVERT_S(t) _PIQt_CONVERT(PI##t, Q##t, PI2Q##t, Q2PI##t)
_PIQt_CONVERT_S(String)
_PIQt_CONVERT_S(ByteArray)
_PIQt_CONVERT_S(Time)
_PIQt_CONVERT_S(Date)
_PIQt_CONVERT_S(DateTime)
_PIQt_CONVERT(PIMathVectorT2d, QPointF, PI2QVector2, Q2PIVector2)
_PIQt_CONVERT(PIMathVectorT3d, QVector3D, PI2QVector3, Q2PIVector3)
#define piqt __PIQtConvert
#define qtpi __PIQtConvert
#endif // PIQT_H

View File

@@ -0,0 +1 @@
piqt_library(qcd_utils "Gui" "pip;qad_utils;qad_widgets;qad_graphic;cd_utils;piqt")

297
piqt/libs/qcd/qcd_core.cpp Normal file
View File

@@ -0,0 +1,297 @@
#include "qcd_core.h"
#include "cdutils_k.h"
#include "cdutils_core.h"
#include "piqt.h"
#include <QWidget>
#include <QCheckBox>
#include <QGroupBox>
#include <QSpinBox>
#include <QSlider>
#include <QScrollBar>
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <spinslider.h>
#include <clineedit.h>
#include <evalspinbox.h>
#include <qvariantedit.h>
#include <qcd_view.h>
using namespace CDUtils;
int __QCore_Initializer__::count_(0);
QCDCore * __QCore_Initializer__::__instance__(0);
__QCore_Initializer__::__QCore_Initializer__() {
count_++;
if (count_ > 1) return;
__instance__ = new QCDCore();
}
__QCore_Initializer__::~__QCore_Initializer__() {
count_--;
if (count_ > 0) return;
if (__instance__ != 0) {
delete __instance__;
__instance__ = 0;
}
}
QCDCore::QCDCore() {
setObjectName("QCDCore");
setName("QCDCore");
CONNECTU(&K, changedGlobal, this, K_ChangedGlobal);
updating = direct_on = false;
}
QCDCore::~QCDCore() {
}
void QCDCore::K_ChangedGlobal() {
QMetaObject::invokeMethod(this, "updateBindedWidgets", Qt::QueuedConnection);
}
void QCDCore::slotBool(bool v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(PIString::fromBool(v));
K.calculate();
emit updateViewRequest();
}
void QCDCore::slotInt(int v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(PIString::fromNumber(v));
finishEdit(pathes);
}
void QCDCore::slotDouble(double v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(PIString::fromNumber(v));
finishEdit(pathes);
}
void QCDCore::slotText(QString v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(Q2PIString(v));
finishEdit(pathes);
}
void QCDCore::slotVariant(QVariant v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setVariantValue(Q2PIVariant(v));
finishEdit(pathes);
}
void QCDCore::slotDestroyed(QObject * o) {
if (!o) return;
if (!binded_widgets.contains((QWidget*)o)) return;
binded_widgets.remove((QWidget*)o);
}
int QCDCore::bindWindow(QWidget * wnd) {
if (!wnd) return 0;
//K.root().makePath();
return bindWidgets(wnd->findChildren<QWidget * >());
}
int QCDCore::bindWidgets(QList<QWidget * > wl) {
int ret = 0;
foreach (QWidget * w, wl)
if (bindWidget(w)) ++ret;
return ret;
}
bool QCDCore::bindWidget(QWidget * w) {
if (!w) return false;
QString on = w->objectName();
QString cn = w->metaObject()->className();
if (cn == "CDView") {
bindView(w);
return false;
}
PIVector<CDType * > ak = K.root().children();
piForeachC (CDType * k, ak) {
if (!on.endsWith(PI2QString(k->pathString().join("_")))) continue;
if (bindWidget(w, *k)) return true;
}
return false;
}
bool QCDCore::bindWidget(QWidget * w, const CDType & k) {
if (!w) return false;
//piCout << "bind..." << k.name() << k.path();
QString cn = w->metaObject()->className();
bool ok = false;
if (cn == "QCheckBox" || cn == "QGroupBox") {
connect(w, SIGNAL(toggled(bool)), this, SLOT(slotBool(bool)), Qt::UniqueConnection);
ok = true;
}
if (cn == "QSpinBox" || cn == "QSlider" || cn == "QScrollBar") {
connect(w, SIGNAL(valueChanged(int)), this, SLOT(slotInt(int)), Qt::UniqueConnection);
ok = true;
}
if (cn == "QDoubleSpinBox" || cn == "SpinSlider" || cn == "EvalSpinBox") {
connect(w, SIGNAL(valueChanged(double)), this, SLOT(slotDouble(double)), Qt::UniqueConnection);
ok = true;
}
if (cn == "QLineEdit" || cn == "CLineEdit") {
connect(w, SIGNAL(textChanged(QString)), this, SLOT(slotText(QString)), Qt::UniqueConnection);
ok = true;
}
if (cn == "QVariantEdit") {
connect(w, SIGNAL(valueChanged(QVariant)), this, SLOT(slotVariant(QVariant)), Qt::UniqueConnection);
ok = true;
}
if (cn == "CDView") {
bindView(w);
}
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(slotDestroyed(QObject*)), Qt::UniqueConnection);
setWidgetValue(w, k);
if (!ok) return false;
//piCout << k.name() << k.path() << "ok";
binded_widgets.insert(w, k.path());
return true;
}
void QCDCore::updateBindedWidgets() {
QMapIterator<QWidget * , PIDeque<int> > it(binded_widgets);
QWidgetList to_remove;
updating = true;
while (it.hasNext()) {
QWidget * w = it.next().key();
if (!K.exists(it.value()))
to_remove << w;
else
setWidgetValue(w, K[it.value()]);
}
foreach (QWidget * w, to_remove)
unbindWidget(w);
updating = false;
}
void QCDCore::bindView(QWidget * v) {
CDView * w = qobject_cast<CDView * >(v);
if (!w) return;
connect(this, SIGNAL(updateViewRequest()), w, SLOT(refreshValues()), Qt::UniqueConnection);
}
void QCDCore::setWidgetValue(QWidget * w, const CDType & k) {
if (!w) return;
QString cn = w->metaObject()->className();
if (cn == "QCheckBox") qobject_cast<QCheckBox*>(w)->setChecked(k.toBool());
if (cn == "QGroupBox") qobject_cast<QGroupBox*>(w)->setChecked(k.toBool());
if (cn == "QSpinBox") qobject_cast<QSpinBox*>(w)->setValue(k.toInt());
if (cn == "QSlider") qobject_cast<QSlider*>(w)->setValue(k.toInt());
if (cn == "QScrollBar") qobject_cast<QScrollBar*>(w)->setValue(k.toInt());
if (cn == "QDoubleSpinBox") qobject_cast<QDoubleSpinBox*>(w)->setValue(k.toDouble());
if (cn == "SpinSlider") qobject_cast<SpinSlider*>(w)->setValue(k.toDouble());
if (cn == "QLineEdit") qobject_cast<QLineEdit*>(w)->setText(PI2QString(k.value()));
if (cn == "CLineEdit") qobject_cast<CLineEdit*>(w)->setText(PI2QString(k.value()));
if (cn == "EvalSpinBox") qobject_cast<EvalSpinBox*>(w)->setValue(k.toDouble());
if (cn == "QVariantEdit") qobject_cast<QVariantEdit*>(w)->setValue(PI2QVariant(k.variantValue()));
}
void QCDCore::finishEdit(const QList<PIDeque<int> > & pathes) {
K.calculate();
if (direct_on) {
foreach (const PIDeque<int> & path, pathes)
K.directChange(K[path]);
}
emit updateViewRequest();
}
int QCDCore::unbindWindow(QWidget * wnd) {
if (!wnd) return 0;
return unbindWidgets(wnd->findChildren<QWidget * >());
}
int QCDCore::unbindWidgets(QList<QWidget * > wl) {
int ret = 0;
foreach (QWidget * w, wl)
if (unbindWidget(w)) ++ret;
return ret;
}
bool QCDCore::unbindWidget(QWidget * w) {
if (!w) return false;
//qDebug() << "unbind" << w;
if (!binded_widgets.contains(w)) return false;
QString cn = w->metaObject()->className();
if (cn == "QCheckBox" || cn == "QGroupBox")
disconnect(w, SIGNAL(toggled(bool)), this, SLOT(slotBool(bool)));
if (cn == "QSpinBox" || cn == "QSlider" || cn == "QScrollBar")
disconnect(w, SIGNAL(valueChanged(int)), this, SLOT(slotInt(int)));
if (cn == "QDoubleSpinBox" || cn == "SpinSlider" || cn == "EvalSpinBox")
disconnect(w, SIGNAL(valueChanged(double)), this, SLOT(slotDouble(double)));
if (cn == "QLineEdit" || cn == "CLineEdit")
disconnect(w, SIGNAL(textChanged(QString)), this, SLOT(slotText(QString)));
if (cn == "QVariantEdit")
disconnect(w, SIGNAL(valueChanged(QVariant)), this, SLOT(slotVariant(QVariant)));
//qDebug() << "remove b" << binded_widgets.size();
binded_widgets.remove(w);
//qDebug() << "remove a" << binded_widgets.size();
return true;
}
void QCDCore::unbindAllWidgets() {
QMap<QWidget * , PIDeque<int> > bwm = binded_widgets;
QMapIterator<QWidget * , PIDeque<int> > it(bwm);
while (it.hasNext()) {
QWidget * w = it.next().key();
unbindWidget(w);
}
binded_widgets.clear();
}
void QCDCore::updateBindedWidget(const CDType & k_) {
QMapIterator<QWidget * , PIDeque<int> > it(binded_widgets);
updating = true;
while (it.hasNext()) {
QWidget * w = it.next().key();
const CDType & k(K[it.value()]);
if (k.path() != k_.path()) continue;
setWidgetValue(w, k);
}
updating = false;
}

96
piqt/libs/qcd/qcd_core.h Normal file
View File

@@ -0,0 +1,96 @@
/*
QCD Utils - Qt bindings/utilites for CD Utils
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_CORE_H
#define QCD_CORE_H
#include <QObject>
#include <QMultiMap>
#include <QVariant>
#include "piobject.h"
#include "cdutils_types.h"
class QCDCore;
class __QCore_Initializer__ {
public:
__QCore_Initializer__();
~__QCore_Initializer__();
static int count_;
static QCDCore * __instance__;
};
class QCDCore: public QObject, public PIObject
{
Q_OBJECT
PIOBJECT(QCDCore)
friend class __QCore_Initializer__;
public:
static QCDCore * instance() {return __QCore_Initializer__::__instance__;}
int bindWindow(QWidget * wnd);
int bindWidgets(QList<QWidget * > wl);
bool bindWidget(QWidget * w);
bool bindWidget(QWidget * w, const CDUtils::CDType & k);
int unbindWindow(QWidget * wnd);
int unbindWidgets(QList<QWidget * > wl);
bool unbindWidget(QWidget * w);
void unbindAllWidgets();
void updateBindedWidget(const CDUtils::CDType & k_);
void setDirectKEnabled(bool yes) {direct_on = yes;}
bool isDirectKEnabled() const {return direct_on;}
private:
QCDCore();
~QCDCore();
void bindView(QWidget * v);
void setWidgetValue(QWidget * w, const CDUtils::CDType & k);
void finishEdit(const QList<PIDeque<int> > & pathes);
EVENT_HANDLER(void, K_ChangedGlobal);
QMultiMap<QWidget * , PIDeque<int> > binded_widgets;
bool updating, direct_on;
private slots:
void slotBool(bool v);
void slotInt(int v);
void slotDouble(double v);
void slotText(QString v);
void slotVariant(QVariant v);
void slotDestroyed(QObject * );
public slots:
void updateBindedWidgets();
signals:
void updateViewRequest();
};
static __QCore_Initializer__ __QCore_initializer__;
#endif // QCD_CORE_H

View File

@@ -0,0 +1,40 @@
#include "qcd_graphic.h"
#include "ui_qcd_graphic.h"
#include "cdutils_core.h"
#include "cdutils_x.h"
#include "graphic.h"
#include "piqt.h"
using namespace CDUtils;
CDGraphicWidget::CDGraphicWidget(QWidget * p): QWidget(p) {
ui = new Ui::CDGraphicWidget();
ui->setupUi(this);
ui->graphic->setGraphicsCount(0);
}
Graphic * CDGraphicWidget::graphic() const {
return ui->graphic;
}
void CDGraphicWidget::setConfigVisible(bool on) {
ui->widgetConfig->setVisible(on);
}
bool CDGraphicWidget::isConfigVisible() const {
return ui->widgetConfig->isVisible();
}
EvalSpinBox * CDGraphicWidget::evalSpinBoxHistory() {
return ui->evalHistory;
}
EvalSpinBox * CDGraphicWidget::evalSpinBoxVisible() {
return ui->evalVisible;
}

View File

@@ -0,0 +1,66 @@
/*
QCD Utils - Qt bindings/utilites for CD Utils
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_GRAPHIC_H
#define QCD_GRAPHIC_H
#include <QWidget>
#include <evalspinbox.h>
#include <pistring.h>
namespace CDUtils {
class CDType;
class CDSection;
}
namespace Ui {
class CDGraphicWidget;
}
class Graphic;
class Graphic;
class CDGraphicWidget: public QWidget {
Q_OBJECT
friend class CDGraphics;
friend class GDockWidget;
public:
CDGraphicWidget(QWidget * p = 0);
Graphic * graphic() const;
bool isConfigVisible() const;
EvalSpinBox * evalSpinBoxHistory();
EvalSpinBox * evalSpinBoxVisible();
public slots:
void setConfigVisible(bool on);
private:
Ui::CDGraphicWidget * ui;
private slots:
signals:
};
#endif // QCD_GRAPHIC_H

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDGraphicWidget</class>
<widget class="QWidget" name="CDGraphicWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<height>380</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="layoutMain">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="Graphic" name="graphic">
<property name="buttons">
<set>Graphic::Autofit|Graphic::BorderInputs|Graphic::Clear|Graphic::Configure|Graphic::CursorAxis|Graphic::Fullscreen|Graphic::Legend|Graphic::OnlyExpandY|Graphic::Pause|Graphic::Save</set>
</property>
<property name="borderInputsVisible">
<bool>false</bool>
</property>
<property name="statusVisible">
<bool>false</bool>
</property>
<property name="historySize">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetConfig" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>History:</string>
</property>
</widget>
</item>
<item>
<widget class="EvalSpinBox" name="evalHistory">
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Visible:</string>
</property>
</widget>
</item>
<item>
<widget class="EvalSpinBox" name="evalVisible">
<property name="value">
<double>-1.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Graphic</class>
<extends>QFrame</extends>
<header>graphic.h</header>
</customwidget>
<customwidget>
<class>EvalSpinBox</class>
<extends>QWidget</extends>
<header>evalspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>evalHistory</sender>
<signal>valueChanged(double)</signal>
<receiver>graphic</receiver>
<slot>setHistorySize(double)</slot>
<hints>
<hint type="sourcelabel">
<x>148</x>
<y>363</y>
</hint>
<hint type="destinationlabel">
<x>156</x>
<y>297</y>
</hint>
</hints>
</connection>
<connection>
<sender>evalVisible</sender>
<signal>valueChanged(double)</signal>
<receiver>graphic</receiver>
<slot>setMaxVisibleTime(double)</slot>
<hints>
<hint type="sourcelabel">
<x>345</x>
<y>361</y>
</hint>
<hint type="destinationlabel">
<x>342</x>
<y>337</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,46 @@
#include "qcd_modedialog.h"
#include "ui_qcd_modedialog.h"
QCDModeDialog::QCDModeDialog(QWidget * parent): QDialog(parent) {
ui = new Ui::QCDModeDialog();
ui->setupUi(this);
}
QCDModeDialog::~QCDModeDialog() {
delete ui;
}
CDUtils::UpdateModeFlags QCDModeDialog::mode() const {
CDUtils::UpdateModeFlags ret = 0;
if (ui->checkSaveIndex->isChecked()) ret |= CDUtils::SaveByIndex;
if (ui->checkSaveName->isChecked()) ret |= CDUtils::SaveByName;
if (ui->checkMerge->isChecked()) ret |= CDUtils::Merge;
return ret;
}
void QCDModeDialog::changeEvent(QEvent *e) {
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void QCDModeDialog::on_checkSaveIndex_clicked(bool checked) {
if (!checked) return;
ui->checkSaveName->setChecked(false);
}
void QCDModeDialog::on_checkSaveName_clicked(bool checked) {
if (!checked) return;
ui->checkSaveIndex->setChecked(false);
}

View File

@@ -0,0 +1,50 @@
/*
QCD Utils - Qt bindings/utilites for CD Utils
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_MODEDIALOG_H
#define QCD_MODEDIALOG_H
#include <QDialog>
#include <cdutils_types.h>
namespace Ui {
class QCDModeDialog;
}
class QCDModeDialog: public QDialog
{
Q_OBJECT
public:
explicit QCDModeDialog(QWidget * parent = 0);
~QCDModeDialog();
CDUtils::UpdateModeFlags mode() const;
protected:
void changeEvent(QEvent *e);
Ui::QCDModeDialog * ui;
private slots:
void on_checkSaveIndex_clicked(bool checked);
void on_checkSaveName_clicked(bool checked);
};
#endif // QCD_MODEDIALOG_H

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QCDModeDialog</class>
<widget class="QDialog" name="QCDModeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>251</width>
<height>152</height>
</rect>
</property>
<property name="windowTitle">
<string>Update description mode</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="checkSaveIndex">
<property name="text">
<string>Save by index</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkSaveName">
<property name="text">
<string>Save by name</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkMerge">
<property name="text">
<string>Merge</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QCDModeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>106</x>
<y>131</y>
</hint>
<hint type="destinationlabel">
<x>101</x>
<y>146</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QCDModeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>182</x>
<y>127</y>
</hint>
<hint type="destinationlabel">
<x>169</x>
<y>146</y>
</hint>
</hints>
</connection>
</connections>
</ui>

460
piqt/libs/qcd/qcd_model.cpp Normal file
View File

@@ -0,0 +1,460 @@
#include "qcd_model.h"
#include "cdutils_interface.h"
#include "cdutils_core.h"
#include "cdutils_x.h"
#include "piqt.h"
#include <QDebug>
#include <QBrush>
#include <QColor>
#include <QMimeData>
#include "qvariantedit.h"
#include "qad_types.h"
using namespace CDUtils;
// CDKItem
CDItem::CDItem(CDUtils::Interface * i, int _index, CDItem::CDItemType type, CDItem *parent) {
interface = i;
index_ = _index;
parent_ = parent;
type_ = type;
item_count = 0;
expanded = true;
}
CDItem::~CDItem() {
qDeleteAll(childs);
}
QVariant CDItem::data(int column, int role) const {
if (role == Qt::BackgroundRole) {
switch (type_) {
case ItemCDType: {
CDType & t(interface->section(buildPath())[index_]);
if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230));
else return QBrush(QColor(255, 128, 128));
}
case ItemCDSection: return QBrush(QColor(230, 250, 230));
}
}
if (role == Qt::CheckStateRole && type_ == ItemCDType) {
CDType & t(interface->section(buildPath())[index_]);
if (column == cValue && t.cd_type() == CDType::cdK) {
if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked;
else QVariant();
}
if (column == cName_Cmd && t.cd_type() == CDType::cdX) {
return t.isSelectedX() ? Qt::Checked : Qt::Unchecked;
}
}
if (role == Qt::ToolTipRole && type_ == ItemCDType) {
CDType & t(interface->section(buildPath())[index_]);
return PI2QString(t.errorString());
}
if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant();
PIDeque<int> path = buildPath();
CDSection & rs = interface->section(path);
CDSection s;
switch (type_) {
case ItemCDType:
switch (column) {
case cID: return QString::number(index_);
case cName_Cmd: return PI2QString(rs[index_].name());
case cType: return stringType(rs[index_].type());
case cXMode: return QVariant::fromValue(xModeEnum(rs[index_].xmode()));
case cXAvg: return rs[index_].avg();
case cExpression: return PI2QString(rs[index_].formula());
case cValue: return value(rs[index_], role);
case cComment: return PI2QString(rs[index_].comment());
default: break;
}
break;
case ItemCDSection:
s = rs.section(index_);
// piCout << rs.name << rs.alias << s.name << s.alias;
switch (column) {
case cID: return QString("[") + QString::number(index_) + QString("]");
case cName_Cmd: return PI2QString(s.alias);
case cType: return PI2QString(s.name);
default: break;
}
break;
}
return QVariant();
}
QVariant CDItem::value(CDType & t, int role) const {
if (t.type() == "f") return t.toDouble();
if (t.type() == "n") return t.toInt();
if (t.type() == "b") return t.toBool();
if (t.type() == "e") {
QAD::Enum et = PI2QADEnum(t.enumValues());
et.selectValue(t.toInt());
if (role == Qt::EditRole) return QVariant::fromValue<QAD::Enum>(et);
else return et.selectedName();
}
return PI2QString(t.value());
}
bool CDItem::setData(int column, const QVariant & value) {
if (type_ == ItemCDType) {
CDType & t(interface->section(buildPath())[index_]);
if ((column == cExpression || column == cValue) && (t.cd_type() == CDType::cdK)) {
interface->section(buildPath())[index_].setValue(Q2PIString(value.toString()));
interface->calculate();
return true;
}
if (t.cd_type() == CDType::cdX) {
switch (column) {
case cName_Cmd:
X.setEnabled(t, value.toBool());
return true;
case cXMode:
t.setXMode((CDType::XMode)value.toInt());
return true;
case cXAvg:
t.setAvg(piMax(value.toInt(), 1));
return true;
default: break;
}
}
}
return false;
}
PIDeque<int> CDItem::buildPath() const {
PIDeque<int> path;
CDItem * p = parent_;
while (p) {
path.push_front(p->index_);
p = p->parent_;
}
path.take_front();
return path;
}
QString CDItem::stringType(const PIString & t) const {
QString n = PI2QString(t);
if (n.isEmpty()) return QString("");
switch (n[0].toLatin1()) {
case 'l': return QString("list"); break;
case 'b': return QString("bool"); break;
case 'n': return QString("int"); break;
case 'f': return QString("double"); break;
case 'c': return QString("color"); break;
case 'r': return QString("rect"); break;
case 'a': return QString("rect"); break;
case 'p': return QString("point"); break;
case 'v': return QString("vector"); break;
case 'i': return QString("IP"); break;
case 'e': return QString("enum"); break;
case 'F': return QString("file"); break;
case 'D': return QString("dir"); break;
}
return QString("string");
}
QAD::Enum CDItem::xModeEnum(int v) const {
QAD::Enum ret;
ret << QAD::Enumerator(CDType::X_Current, "Current")
<< QAD::Enumerator(CDType::X_All_Avg, "All, Averaging");
ret.selectValue(v);
return ret;
}
// CDKDelegate
CDDelegate::CDDelegate(QObject *parent) : QStyledItemDelegate(parent) {
}
void CDDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
CDItem * item = ((CDItemModel*)index.model())->getItem(index);
if (item) {
if (item->itemType() == CDItem::ItemCDType && item->interface->cdType() == CDType::cdC) {
QStyleOptionButton bo;
bo.direction = option.direction;
bo.fontMetrics = option.fontMetrics;
bo.palette = option.palette;
bo.rect = option.rect;
bo.state = option.state;// & ~(QStyle::State_HasFocus | QStyle::State_MouseOver);
bo.text = item->data(1, Qt::DisplayRole).toString();
QWidget * v = (QWidget*)(painter->device());
if (v) {
QPoint cp = v->mapFromGlobal(QCursor::pos());
if (bo.rect.contains(cp, true)) {
//bo.state |= QStyle::State_MouseOver;
if (qApp->mouseButtons().testFlag(Qt::LeftButton))
bo.state |= QStyle::State_On;
}
}
qApp->style()->drawControl(QStyle::CE_PushButton, &bo, painter);
return;
}
}
QStyledItemDelegate::paint(painter, option, index);
}
QWidget * CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
return new QVariantEdit(parent);
}
void CDDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
QVariantEdit *edit = static_cast<QVariantEdit*>(editor);
edit->setValue(index.model()->data(index, Qt::EditRole));
}
void CDDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QVariantEdit *edit = static_cast<QVariantEdit*>(editor);
QVariant v = edit->value();
if (v.canConvert<QAD::Enum>()) {
QAD::Enum et = v.value<QAD::Enum>();
model->setData(index, et.selectedValue(), Qt::EditRole);
} else model->setData(index, v, Qt::EditRole);
}
void CDDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
editor->setGeometry(option.rect);
}
QSize CDDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
QSize s = QStyledItemDelegate::sizeHint(option, index);
s.setWidth(s.width() + 20);
return s;
}
// CDItemModel
CDItemModel::CDItemModel(int type_, QObject *parent) : QAbstractItemModel(parent) {
interface = new Interface((CDType::cdT)type_);
root = 0;
internalRebuild();
}
CDItemModel::~CDItemModel() {
delete root;
delete interface;
}
QVariant CDItemModel::data(const QModelIndex &index, int role) const {
if (!index.isValid()) return QVariant();
CDItem * item = getItem(index);
return item->data(index.column(), role);
}
QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case cID: return tr("Index");
case cName_Cmd: return interface->cdType() == CDType::cdC ? tr("Command") : tr("Name");
case cType: return tr("Type");
case cXMode: return tr("Mode");
case cXAvg: return tr("Averaging");
case cExpression: return tr("Expression");
case cValue: return tr("Value");
case cComment: return tr("Comment");
}
}
return QVariant();
}
QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const {
if (parent.isValid() && parent.column() != cID) return QModelIndex();
CDItem * p = getItem(parent);
CDItem * c = p->childs.value(row, 0);
if (c) return createIndex(row, column, c);
else return QModelIndex();
}
QModelIndex CDItemModel::parent(const QModelIndex &index) const {
if (!index.isValid()) return QModelIndex();
CDItem * c = getItem(index);
CDItem * p = c->parent_;
if (p == root) return QModelIndex();
return createIndex(p->parent_->childs.indexOf(p), cID, p);
}
int CDItemModel::rowCount(const QModelIndex &parent) const {
CDItem * p = getItem(parent);
return p->childs.count();
}
int CDItemModel::columnCount(const QModelIndex &parent) const {
return cLastColumn;
}
Qt::ItemFlags CDItemModel::flags(const QModelIndex & index) const {
if (!index.isValid()) return 0;
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
CDItem * item = getItem(index);
if (!item) return 0;
if (item->type_ == CDItem::ItemCDType) {
CDType & t(interface->section(item->buildPath())[item->index_]);
if (t.cd_type() == CDType::cdK) {
if (index.column() == cExpression || index.column() == cValue)
f |= Qt::ItemIsEditable;
if (index.column() == cValue && t.type() == "b")
f |= Qt::ItemIsUserCheckable;
if (index.column() == cName_Cmd)
f |= Qt::ItemIsDragEnabled;
}
if (t.cd_type() == CDType::cdX) {
if (index.column() == cXMode || index.column() == cXAvg)
f |= Qt::ItemIsEditable;
if (index.column() == cName_Cmd)
f |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled;
}
}
return f;
}
bool CDItemModel::setData(const QModelIndex & index, const QVariant & value, int role) {
if (role == Qt::CheckStateRole && (index.column() == cName_Cmd || index.column() == cValue)) {
CDItem * item = getItem(index);
if (item->type_ == CDItem::ItemCDType) {
CDType & t(interface->section(item->buildPath())[item->index_]);
if (index.column() == cValue && (t.cd_type() == CDType::cdK)) {
if (t.type() == "b") {
bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool())));
QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent()));
emit dataChanged(rin, rin);
return result;
}
}
if (index.column() == cName_Cmd && (t.cd_type() == CDType::cdX)) {
bool result = item->setData(index.column(), value);
//QModelIndex rin(CDItemModel::index(index.row(), 1, index.parent()));
//emit dataChanged(rin, rin);
return result;
}
}
}
if (role != Qt::EditRole) return false;
CDItem * item = getItem(index);
bool result = item->setData(index.column(), value);
if (result) {
QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent()));
emit dataChanged(rin, rin);
emit dataChanged(index, index);
}
return result;
}
QMimeData * CDItemModel::mimeData(const QModelIndexList & indexes) const {
if (indexes.size() == 1) {
QModelIndex index = indexes[0];
if (index.isValid()/* && interface->cdType() == CDType::cdX*/) {
CDItem * item = getItem(index);
if (item) {
CDType & t(interface->section(item->buildPath())[item->index_]);
QMimeData * mime = new QMimeData();
mime->setText(PI2QString(CDCore::instance()->typeLetter(interface->cdType()) +
CDCore::pathToString(t.path())));
return mime;
}
}
}
return QAbstractItemModel::mimeData(indexes);
}
void CDItemModel::rebuildModel() {
beginResetModel();
internalRebuild();
endResetModel();
}
void CDItemModel::buildItem(CDItem * it, CDSection & r) {
//piCout << "build item" << r.name << r.alias;
auto i = r.cd.makeIterator();
while (i.next()) {
it->childs << new CDItem(interface, i.key(), CDItem::ItemCDType, it);
}
it->item_count = it->childs.size();
auto j = r.s.makeIterator();
while (j.next()) {
it->childs << new CDItem(interface, j.key(), CDItem::ItemCDSection, it);
buildItem(it->childs.back(), j.valueRef());
}
}
void CDItemModel::updateModel() {
beginResetModel();
endResetModel();
}
void CDItemModel::internalRebuild() {
//qDebug() << "[CDKItemModel]" << "internalRebuild()";
if (root) delete root;
root = new CDItem(interface, 0, CDItem::ItemCDSection, 0);
CDSection & r = interface->root();
buildItem(root, r);
}
CDItem * CDItemModel::getItem(const QModelIndex &index) const {
if (index.isValid()) {
CDItem * item = static_cast<CDItem*>(index.internalPointer());
if (item) return item;
}
return root;
}
QModelIndex CDItemModel::indexByPath(const PIDeque<int> & path, int column) const {
if (path.isEmpty()) return QModelIndex();
CDItem * item = root;
//piCout << path << "...";
bool ok = false;
for (int i = 0; i < path.size_s() - 1; ++i) {
ok = false;
foreach (CDItem * j, item->childs)
if (j->type_ == CDItem::ItemCDSection && j->index_ == path[i]) {
item = j;
ok = true;
break;
}
if (!ok) return QModelIndex();
}
ok = false;
foreach (CDItem * j, item->childs)
if (j->type_ == CDItem::ItemCDType && j->index_ == path.back()) {
item = j;
ok = true;
break;
}
if (!ok || !item->parent_) return QModelIndex();
QModelIndex ret = createIndex(item->parent_->childs.indexOf(item), column, item);
//piCout << path << Q2PIString(item->data(cName_Cmd, Qt::DisplayRole).toString()) << getItem(ret)->buildPath();
return ret;
}

132
piqt/libs/qcd/qcd_model.h Normal file
View File

@@ -0,0 +1,132 @@
/*
QCD Utils - Qt bindings/utilites for CD Utils
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_MODEL_H
#define QCD_MODEL_H
#include <QAbstractItemModel>
#include <QItemDelegate>
#include <QStyledItemDelegate>
#include "pistring.h"
namespace CDUtils {
class CDType;
class CDSection;
class Interface;
enum Column {
cID ,
cName_Cmd ,
cType ,
cXMode ,
cXAvg ,
cExpression,
cValue ,
cComment ,
cLastColumn,
};
}
namespace QAD {
struct Enum;
}
class CDItemModel;
class CDItem {
friend class CDItemModel;
friend class CDView;
public:
enum CDItemType{ItemCDType, ItemCDSection};
CDItem(CDUtils::Interface * interface, int _index, CDItemType type, CDItem * parent);
~CDItem();
QVariant data(int column, int role) const;
QVariant value(CDUtils::CDType & t, int role) const;
bool setData(int column, const QVariant & value);
CDItemType itemType() const {return type_;}
PIDeque<int> buildPath() const;
int index() const {return index_;}
CDUtils::Interface * interface;
bool expanded;
private:
QString stringType(const PIString & t) const;
QAD::Enum xModeEnum(int v) const;
CDItem * parent_;
int index_, item_count;
CDItemType type_;
QList<CDItem *> childs;
};
class CDDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
CDDelegate(QObject *parent = 0);
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
class CDItemModel : public QAbstractItemModel {
Q_OBJECT
friend class CDView;
public:
explicit CDItemModel(int type_, QObject *parent = 0);
~CDItemModel();
QVariant data(const QModelIndex & index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QMimeData * mimeData(const QModelIndexList & indexes) const;
CDItem * getItem(const QModelIndex & index) const;
QModelIndex indexByPath(const PIDeque<int> & path, int column = CDUtils::cID) const;
void buildItem(CDItem * it, CDUtils::CDSection &r);
public slots:
void rebuildModel();
void updateModel();
private:
void internalRebuild();
CDUtils::Interface * interface;
CDItem * root;
signals:
};
#endif // QCD_MODEL_H

371
piqt/libs/qcd/qcd_view.cpp Normal file
View File

@@ -0,0 +1,371 @@
#include <QDir>
#include <QMouseEvent>
#include <QSortFilterProxyModel>
#include "cdutils_k.h"
#include "cdutils_x.h"
#include "cdutils_c.h"
#include "cdutils_m.h"
#include "cdutils_core.h"
#include "qcd_view.h"
#include "qcd_model.h"
#include "piqt.h"
#include "pifile.h"
using namespace CDUtils;
CDView::CDView(QWidget * parent) : QTreeView(parent) {
type_ = -1;
model_ = 0;
proxy_ = 0;
connect(this, SIGNAL(clicked(QModelIndex)), this, SLOT(indexClicked(QModelIndex)));
connect(this, SIGNAL(_qcd_sendFailed()), this, SLOT(cd_sendFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(_qcd_sendSucceed()), this, SLOT(cd_sendSucceed()), Qt::QueuedConnection);
connect(this, SIGNAL(_qcd_receiveFailed()), this, SLOT(cd_receiveFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(_qcd_receiveSucceed()), this, SLOT(cd_receiveSucceed()), Qt::QueuedConnection);
connect(this, SIGNAL(_qcd_receivedX()), this, SLOT(cd_receivedX()), Qt::QueuedConnection);
connect(this, SIGNAL(_qcd_changedGlobal()), this, SLOT(cd_changedGlobal()), Qt::QueuedConnection);
}
CDView::~CDView() {
if (model_) {
delete model_;
delete proxy_;
}
model_ = 0;
proxy_ = 0;
}
void CDView::setType(int cdt) {
if (cdt < 0) return;
if (type_ >= 0) return;
type_ = cdt;
switch ((CDType::cdT)type_) {
case CDType::cdK:
CONNECTU(&K, sended, this, pi_cd_sendSucceed);
CONNECTU(&K, sendFailed, this, pi_cd_sendFailed);
CONNECTU(&K, received, this, pi_cd_receiveSucceed);
CONNECTU(&K, receiveFailed, this, pi_cd_receiveFailed);
CONNECTU(&K, changedGlobal, this, pi_cd_changedGlobal);
break;
case CDType::cdX:
CONNECTU(&X, sended, this, pi_cd_sendSucceed);
CONNECTU(&X, sendFailed, this, pi_cd_sendFailed);
CONNECTU(&X, received, this, pi_cd_receiveSucceed);
CONNECTU(&X, receiveFailed, this, pi_cd_receiveFailed);
CONNECTU(&X, receivedX, this, pi_cd_receivedX);
CONNECTU(&X, changedGlobal, this, pi_cd_changedGlobal);
break;
case CDType::cdC:
CONNECTU(&C, sended, this, pi_cd_sendSucceed);
CONNECTU(&C, sendFailed, this, pi_cd_sendFailed);
CONNECTU(&C, received, this, pi_cd_receiveSucceed);
CONNECTU(&C, receiveFailed, this, pi_cd_receiveFailed);
CONNECTU(&C, changedGlobal, this, pi_cd_changedGlobal);
break;
case CDType::cdM:
CONNECTU(&M, sended, this, pi_cd_sendSucceed);
CONNECTU(&M, sendFailed, this, pi_cd_sendFailed);
CONNECTU(&M, received, this, pi_cd_receiveSucceed);
CONNECTU(&M, receiveFailed, this, pi_cd_receiveFailed);
CONNECTU(&M, changedGlobal, this, pi_cd_changedGlobal);
CONNECTU(&M, messageReceived, this, pi_cd_messageReceived);
break;
default: break;
}
}
void CDView::mousePressEvent(QMouseEvent * e) {
if (type_ == CDType::cdC) {
QModelIndex i = indexAt(e->pos());
if (i.isValid() && i.column() == cName_Cmd)
update(i);
}
QTreeView::mousePressEvent(e);
}
void CDView::mouseReleaseEvent(QMouseEvent * e) {
if (type_ == CDType::cdC) {
QModelIndex i = indexAt(e->pos());
if (i.isValid() && i.column() == cName_Cmd)
update(i);
}
QTreeView::mouseReleaseEvent(e);
}
void CDView::currentChanged(const QModelIndex & cur, const QModelIndex & prev) {
if (type_ == CDType::cdC) {
if (prev.isValid() && prev.column() == cName_Cmd)
update(prev);
}
QTreeView::currentChanged(cur, prev);
}
void CDView::refresh() {
if (type_ < 0) return;
if (!model_) {
model_ = new CDItemModel(type_);
proxy_ = new QSortFilterProxyModel();
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
proxy_->setRecursiveFilteringEnabled(true);
#endif
proxy_->setFilterKeyColumn(-1);
proxy_->setFilterCaseSensitivity(Qt::CaseInsensitive);
proxy_->setSourceModel(model_);
setModel(proxy_);
setItemDelegateForColumn(type_ == CDType::cdC ? cName_Cmd : cValue, new CDDelegate());
if (type_ == CDType::cdX)
setItemDelegateForColumn(cXMode, new CDDelegate());
}
model_->rebuildModel();
switch ((CDType::cdT)type_) {
case CDType::cdK:
setColumnHidden(cXMode, true);
setColumnHidden(cXAvg, true);
break;
case CDType::cdX:
setColumnHidden(cExpression, true);
break;
case CDType::cdC:
case CDType::cdM:
setColumnHidden(cType, true);
setColumnHidden(cXMode, true);
setColumnHidden(cXAvg, true);
setColumnHidden(cExpression, true);
setColumnHidden(cValue, true);
break;
default: break;
}
expandAll();
for (int i = 0; i < model_->columnCount(); i++) resizeColumnToContents(i);
}
void CDView::refreshValues() {
if (!model_) return;
model_->dataChanged(model_->index(0, 0), model_->index(model_->columnCount() - 1, model_->rowCount() - 1));
}
void CDView::setFile(const QString & filename) {
switch ((CDType::cdT)type_) {
case CDType::cdK: K.setFileName(Q2PIString(filename)); break;
case CDType::cdX: X.setFileName(Q2PIString(filename)); break;
case CDType::cdC: C.setFileName(Q2PIString(filename)); break;
case CDType::cdM: M.setFileName(Q2PIString(filename)); break;
default: break;
}
}
bool CDView::inProgress() const {
switch ((CDType::cdT)type_) {
case CDType::cdK: return K.inProgress(); break;
case CDType::cdX: return X.inProgress(); break;
case CDType::cdC: return C.inProgress(); break;
case CDType::cdM: return M.inProgress(); break;
default: break;
}
return false;
}
void CDView::startX(double freq) {
switch ((CDType::cdT)type_) {
case CDType::cdX: X.start(freq); break;
default: break;
}
}
CDSection * CDView::root() {
return CDCore::instance()->root((CDType::cdT)type_);
}
QString CDView::typeLetter() const {
return PI2QString(CDCore::instance()->typeLetter((CDType::cdT)type_));
}
void CDView::send() {
busyStatusChanged(true);
switch ((CDType::cdT)type_) {
case CDType::cdK: K.send(); break;
case CDType::cdX: X.send(); break;
case CDType::cdC: C.send(); break;
case CDType::cdM: M.send(); break;
default: break;
}
}
void CDView::receive() {
busyStatusChanged(true);
switch ((CDType::cdT)type_) {
case CDType::cdK: K.request(); break;
case CDType::cdX: X.request(); break;
case CDType::cdC: C.request(); break;
case CDType::cdM: M.request(); break;
default: break;
}
}
void CDView::save() {
switch ((CDType::cdT)type_) {
case CDType::cdK: K.writeFile(); break;
case CDType::cdX: X.writeFile(); break;
case CDType::cdC: C.writeFile(); break;
case CDType::cdM: M.writeFile(); break;
default: break;
}
}
void CDView::load() {
switch ((CDType::cdT)type_) {
case CDType::cdK:
K.readFile();
K.calculate();
break;
case CDType::cdX:
X.readFile();
X.calculate();
break;
case CDType::cdC:
C.readFile();
C.calculate();
break;
case CDType::cdM:
M.readFile();
M.calculate();
break;
default: break;
}
refresh();
}
void CDView::clear() {
//piCout << "clearK";
switch ((CDType::cdT)type_) {
case CDType::cdK: K.root() = CDSection(); break;
case CDType::cdX: X.root() = CDSection(); break;
case CDType::cdC: C.root() = CDSection(); break;
case CDType::cdM: M.root() = CDSection(); break;
default: break;
}
refresh();
}
void CDView::buildFromHeader(const QString & description, int mode) {
if (description.isEmpty()) return;
PIString desc_file = Q2PIString(QDir::current().relativeFilePath(description));
PIFile f(desc_file, PIIODevice::ReadOnly);
switch ((CDType::cdT)type_) {
case CDType::cdK: K.update(&f, mode); break;
case CDType::cdX: X.update(&f, mode); break;
case CDType::cdC: C.update(&f, mode); break;
case CDType::cdM: M.update(&f, mode); break;
default: break;
}
refresh();
}
void CDView::calculate() {
switch ((CDType::cdT)type_) {
case CDType::cdK: K.calculate(); break;
case CDType::cdX: X.calculate(); break;
case CDType::cdC: C.calculate(); break;
case CDType::cdM: M.calculate(); break;
default: break;
}
}
void CDView::filter(const QString & f) {
proxy_->setFilterRegExp(QRegExp(f, Qt::CaseInsensitive));
}
void CDView::indexClicked(const QModelIndex & i) {
if (!model_ || !i.isValid() || type_ != CDType::cdC || i.column() != cName_Cmd) return;
CDItem * item = model_->getItem(i);
if (!item) return;
if (item->itemType() != CDItem::ItemCDType) return;
CDType & t(model_->interface->section(item->buildPath())[item->index()]);
C.sendCommand(t);
emit commandSended(PI2QString(t.pathString().join(".")));
//piCout << t;
qDebug() << PI2QString(t.pathString().join("."));
}
void CDView::cd_sendFailed() {
busyStatusChanged(false);
emit messageStatus("send failed");
emit sendFailed();
}
void CDView::cd_sendSucceed() {
busyStatusChanged(false);
emit messageStatus("send success");
emit sendSucceed();
}
void CDView::cd_receiveFailed() {
busyStatusChanged(false);
emit messageStatus("receive failed");
emit receiveFailed();
}
void CDView::cd_receiveSucceed() {
refresh();
busyStatusChanged(false);
emit messageStatus("receive success");
emit receiveSucceed();
}
void CDView::cd_receivedX() {
X.lock();
PIVector<PIDeque<int> > xl = X.enabledList();
//piCout << "X" << xl.size();
piForeachC (PIDeque<int> & x, xl) {
CDType & t(X[x]);
//piCout << t;
//piCout << t.path();
if (t.cd_type() != CDType::cdX) continue;
update(model_->indexByPath(t.path(), cValue));
//piCout << CDCore::pathToString(t.path()) << t.toDouble() << "model";
//qDebug() << "val" << model_->data(model_->indexByPath(t.path(), cValue), Qt::DisplayRole).toDouble();
}
X.unlock();
emit receivedX();
}
void CDView::cd_changedGlobal() {
emit changedGlobal();
}
void CDView::pi_cd_messageReceived(PIDeque<int> path, int type, PIString msg) {
QMetaObject::invokeMethod(this, "messageReceived", Qt::QueuedConnection,
Q_ARG(QString, PI2QString(CDCore::pathToString(path))),
Q_ARG(int, type),
Q_ARG(QString, PI2QString(msg)));
}

112
piqt/libs/qcd/qcd_view.h Normal file
View File

@@ -0,0 +1,112 @@
/*
QCD Utils - Qt bindings/utilites for CD Utils
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_VIEW_H
#define QCD_VIEW_H
#include "piobject.h"
#include <QTreeView>
namespace CDUtils {
class CDType;
class CDSection;
}
class CDItemModel;
class QSortFilterProxyModel;
class CDView: public QTreeView, public PIObject
{
Q_OBJECT
PIOBJECT(CDView)
public:
explicit CDView(QWidget *parent = 0);
~CDView();
void setType(int cdt);
void setFile(const QString & filename);
bool inProgress() const;
void startX(double freq = 20.);
CDUtils::CDSection * root();
QString typeLetter() const;
CDItemModel * CDModel() {return model_;}
protected:
void mousePressEvent(QMouseEvent * );
void mouseReleaseEvent(QMouseEvent * );
void currentChanged(const QModelIndex & cur, const QModelIndex & prev);
public slots:
void refresh();
void refreshValues();
void send();
void receive();
void save();
void load();
void clear();
void buildFromHeader(const QString & description, int mode = 2);
void calculate();
void filter(const QString & f);
private slots:
void indexClicked(const QModelIndex & i);
void cd_sendFailed();
void cd_sendSucceed();
void cd_receiveFailed();
void cd_receiveSucceed();
void cd_receivedX();
void cd_changedGlobal();
private:
bool filterTree(const QModelIndex & ti, const QString & filter);
EVENT_HANDLER(void, pi_cd_sendFailed) {emit _qcd_sendFailed();}
EVENT_HANDLER(void, pi_cd_sendSucceed) {emit _qcd_sendSucceed();}
EVENT_HANDLER(void, pi_cd_receiveFailed) {emit _qcd_receiveFailed();}
EVENT_HANDLER(void, pi_cd_receiveSucceed) {emit _qcd_receiveSucceed();}
EVENT_HANDLER(void, pi_cd_receivedX) {emit _qcd_receivedX();}
EVENT_HANDLER(void, pi_cd_changedGlobal) {emit _qcd_changedGlobal();}
EVENT_HANDLER3(void, pi_cd_messageReceived, PIDeque<int>, path, int, type, PIString, msg);
CDItemModel * model_;
QSortFilterProxyModel * proxy_;
int type_;
signals:
void sendFailed();
void sendSucceed();
void receiveFailed();
void receiveSucceed();
void receivedX();
void changedGlobal();
void messageStatus(QString msg);
void commandSended(QString msg);
void messageReceived(QString path, int type, QString msg);
void busyStatusChanged(bool busy);
void _qcd_sendFailed(); // PRIVATE
void _qcd_sendSucceed(); // PRIVATE
void _qcd_receiveFailed(); // PRIVATE
void _qcd_receiveSucceed(); // PRIVATE
void _qcd_receivedX(); // PRIVATE
void _qcd_changedGlobal(); // PRIVATE
};
#endif // QCD_VIEW_H

View File

@@ -0,0 +1,9 @@
include(PIPMacros)
pip_code_model(CCM "${ROOT_DIR}/pip/libs/main/io_devices/piiodevice.h" "${ROOT_DIR}/pip/libs/main/io_utils/pipacketextractor.h" OPTIONS "-DPIP_EXPORT" "-Es")
piqt_library(piqt_utils "Gui" "qad_utils;qad_widgets;qad_blockview;piqt" ${CCM})
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
add_dependencies(piqt_utils${_v} pip_cmg)
endif()
endforeach()

View File

@@ -0,0 +1,493 @@
#include "ui_piqt_connection_edit.h"
#include "piqt_connection_edit.h"
#include "piqt_connection_view.h"
#include "piqt_highlighter.h"
#include "piqt.h"
#include "picodeinfo.h"
#include <QCheckBox>
#include <QMessageBox>
ConnectionEdit::ConnectionEdit(QWidget * parent): QDialog(parent) {
ui = new Ui::ConnectionEdit();
ui->setupUi(this);
new ConfigHighlighter(ui->codeEdit->document());
loading = false;
connect(ui->blockView, SIGNAL(schemeAction(BlockItemBase::Action,QList<QGraphicsItem*>)), this, SLOT(recreateRequest()));
connect(ui->blockView->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
conn = 0;
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("PIIODevice::DeviceMode");
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members)
ui->comboMode->addItem(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue<int>(e.value));
}
ui->comboMode->setCurrentIndex(ui->comboMode->count() - 1);
ei = PICodeInfo::enumsInfo->value("PIIODevice::DeviceOption");
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members) {
QCheckBox * cb = new QCheckBox();
cb->setText(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"));
cb->setProperty("__value", e.value);
ui->layoutOptions->addWidget(cb);
}
}
ei = PICodeInfo::enumsInfo->value("PIPacketExtractor::SplitMode");
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members)
ui->comboSplit->addItem(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue<int>(e.value));
}
udevicenum = 0;
}
ConnectionEdit::~ConnectionEdit() {
if (conn) {
conn->stop();
delete conn;
}
}
void ConnectionEdit::accept() {
//bool ok = false;
QList<BlockItem * > bl = ui->blockView->allDevices();
foreach (BlockItem * i, bl)
foreach (BlockItem * j, bl)
if (i != j)
if (((DeviceItem*)i)->name() == ((DeviceItem*)j)->name()) {
QMessageBox::critical(this, windowTitle() + " - " + tr("error") + "!", tr("Equal devices names: \"%1\"!").arg(((DeviceItem*)i)->name()));
return;
}
QDialog::accept();
}
QString ConnectionEdit::configuration() const {
if (!conn) return QString();
return PI2QString(conn->makeConfig());
}
QByteArray ConnectionEdit::model() const {
QByteArray ret;
QDataStream s(&ret, QIODevice::ReadWrite);
QString cn = PI2QString(conn ? conn->name() : PIString());
s << cn;
QList<BlockBusItem*> busl = ui->blockView->buses();
s << busl.size();
foreach (BlockBusItem * b, busl)
s << b->save();
QList<BlockItem*> blockl = ui->blockView->blocks();
s << blockl.size();
foreach (BlockItem * b, blockl) {
int type = b->propertyByName("__type").value.toInt();
s << type;
switch (type) {
case __CV_Device:
case __CV_Filter:
case __CV_Sender:
s << b->save();
break;
}
}
return ret;
}
QString ConnectionEdit::name() const {
if (!conn) return QString();
return PI2QString(conn->name());
}
void ConnectionEdit::setName(const QString & name) {
ui->lineName->setText(name);
recreateConnection();
}
void ConnectionEdit::addDevice(const QString & name, const QString & path) {
ui->blockView->addDevice(name, path);
}
void ConnectionEdit::setModel(const QByteArray & m) {
loading = true;
ui->blockView->removeAll();
QDataStream s(m);
QString cn;
s >> cn;
if (conn) delete conn;
conn = new PIConnection(Q2PIString(cn));
ui->lineName->setText(cn);
int sz;
s >> sz;
for (int i = 0; i < sz; ++i) {
BlockBusItem * b = new BlockBusItem();
QByteArray ba; s >> ba; b->load(ba);
ui->blockView->addItem(b);
}
s >> sz;
for (int i = 0; i < sz; ++i) {
int type(0);
BlockItem * b(0);
QByteArray ba;
s >> type;
switch (type) {
case __CV_Device:
b = new DeviceItem();
s >> ba; b->load(ba);
if (!b->isPropertyExists("bufferSize"))
((DeviceItem*)b)->setBufferSize(4096);
((DeviceItem*)b)->rename();
break;
case __CV_Filter:
b = new FilterItem();
s >> ba; b->load(ba);
if (!b->isPropertyExists("bufferSize"))
((FilterItem*)b)->setBufferSize(65536);
((FilterItem*)b)->rename();
break;
case __CV_Sender:
b = new SenderItem();
s >> ba; b->load(ba);
((SenderItem*)b)->rename();
break;
}
if (b)
ui->blockView->addItem(b);
}
ui->blockView->reconnectAll();
loading = false;
recreateConnection();
}
void ConnectionEdit::selectionChanged() {
QList<QGraphicsItem*> si = ui->blockView->scene()->selectedItems();
ui->buttonRemove->setEnabled(!si.isEmpty());
ui->buttonDeviceModify->setEnabled(false);
ui->buttonFilterModify->setEnabled(false);
ui->buttonSenderModify->setEnabled(false);
if (si.size() != 1) return;
BlockItem * b = qgraphicsitem_cast<BlockItem*>(si[0]);
if (!b) return;
int type = b->propertyByName("__type").value.toInt();
if (type == __CV_Device) {
ui->tabWidget->setCurrentIndex(0);
DeviceItem * di = (DeviceItem*)b;
ui->buttonDeviceModify->setEnabled(true);
for (int i = 0; i < ui->comboMode->count(); ++i)
if (ui->comboMode->itemData(i).toInt() == di->mode()) {
ui->comboMode->setCurrentIndex(i);
break;
}
ui->lineDevice->setText(di->name());
ui->linePath->setEditText(di->path());
ui->spinDeviceDT->setValue(di->disconnectTimeout());
ui->spinDeviceBS->setValue(di->bufferSize());
setOptions(di->options());
}
if (type == __CV_Filter) {
ui->tabWidget->setCurrentIndex(1);
FilterItem * fi = (FilterItem*)b;
ui->buttonFilterModify->setEnabled(true);
for (int i = 0; i < ui->comboSplit->count(); ++i)
if (ui->comboSplit->itemData(i).toInt() == fi->mode()) {
ui->comboSplit->setCurrentIndex(i);
break;
}
ui->lineFilter->setText(fi->name());
ui->lineHeader->setText(fi->header());
ui->lineFooter->setText(fi->footer());
ui->spinTimeout->setValue(fi->timeout());
ui->spinSize->setValue(fi->packetSize());
ui->spinFilterDT->setValue(fi->disconnectTimeout());
ui->spinFilterBS->setValue(fi->bufferSize());
}
if (type == __CV_Sender) {
ui->tabWidget->setCurrentIndex(2);
SenderItem * si = (SenderItem*)b;
ui->buttonSenderModify->setEnabled(true);
ui->lineSender->setText(si->name());
ui->lineData->setText(si->data());
ui->spinFrequency->setValue(si->frequency());
}
}
void ConnectionEdit::applyFilter(FilterItem * b) {
b->setName(ui->lineFilter->text());
b->setMode(PIPacketExtractor::SplitMode(ui->comboSplit->itemData(ui->comboSplit->currentIndex()).toInt()));
b->setHeader(ui->lineHeader->text());
b->setFooter(ui->lineFooter->text());
b->setTimeout(ui->spinTimeout->value());
b->setPacketSize(ui->spinSize->value());
b->setDisconnectTimeout(ui->spinFilterDT->value());
b->setBufferSize(ui->spinFilterBS->value());
recreateConnection();
}
void ConnectionEdit::applyDevice(DeviceItem * b) {
QString n = ui->lineDevice->text();
if (n.isEmpty()) {
n = "device" + QString::number(udevicenum);
}
b->setName(n);
b->setMode(PIIODevice::DeviceMode(ui->comboMode->itemData(ui->comboMode->currentIndex()).toInt()));
b->setOptions(PIIODevice::DeviceOptions(getOptions()));
b->setPath(ui->linePath->currentText());
b->setDisconnectTimeout(ui->spinDeviceDT->value());
b->setBufferSize(ui->spinDeviceBS->value());
recreateConnection();
}
void ConnectionEdit::applySender(SenderItem * b) {
b->setName(ui->lineSender->text());
b->setData(ui->lineData->text());
b->setFrequency(ui->spinFrequency->value());
recreateConnection();
}
int ConnectionEdit::getOptions() const {
int ret(0);
for (int i = 0; i < ui->layoutOptions->count(); ++i) {
QCheckBox * cb = qobject_cast<QCheckBox*>(ui->layoutOptions->itemAt(i)->widget());
if (!cb) continue;
if (cb->isChecked())
ret |= cb->property("__value").toInt();
}
return ret;
}
void ConnectionEdit::setOptions(int o) {
for (int i = 0; i < ui->layoutOptions->count(); ++i) {
QCheckBox * cb = qobject_cast<QCheckBox*>(ui->layoutOptions->itemAt(i)->widget());
if (!cb) continue;
int cbf = cb->property("__value").toInt();
//qDebug() << cbf;
cb->setChecked((o & cbf) == cbf);
}
}
void ConnectionEdit::recreateConnection() {
//qDebug() << "recreate";
if (loading) return;
ui->blockView->reconnectAll();
if (conn) delete conn;
PIString cn = Q2PIString(ui->lineName->text());
if (cn.isEmpty()) conn = new PIConnection();
else conn = new PIConnection(cn);
QList<BlockItem*> devs = ui->blockView->allDevices();
foreach (BlockItem * b, devs) {
DeviceItem * di = (DeviceItem*)b;
//qDebug() << di->path();
PIIODevice * dev = conn->addDevice(Q2PIString(di->path()), di->mode());
if (!dev) continue;
dev->setOptions(di->options());
dev->setThreadedReadBufferSize(di->bufferSize());
conn->setDeviceName(dev, Q2PIString(di->name()));
PIDiagnostics * diag = conn->diagnostic(dev);
if (diag) diag->setDisconnectTimeout(di->disconnectTimeout());
}
foreach (BlockItem * b, devs) {
DeviceItem * di = (DeviceItem*)b;
PIIODevice * dev = conn->deviceByName(Q2PIString(di->name()));
if (!dev) continue;
BlockItemPin * p = b->pinByText("read");
if (!p) continue;
QList<BlockBusItem*> buses = p->connectedBuses(), nbuses;
QSet<BlockBusItem*> pbuses;
while (!buses.isEmpty()) {
nbuses.clear();
foreach (BlockBusItem * bus, buses) {
QList<BlockItem*> cb = bus->connectedBlocks();
if (cb.size() != 2) continue;
FilterItem * fi_t(0);
BlockItem * bi_f(0);
if (cb[0]->pinAtBus(bus)->text() == "in") {
fi_t = (FilterItem*)(cb[0]);
bi_f = (cb[1]);
} else if (cb[1]->pinAtBus(bus)->text() == "in") {
fi_t = (FilterItem*)(cb[1]);
bi_f = (cb[0]);
}
if (!fi_t || !bi_f) continue;
PIString name_from;
int type = bi_f->propertyByName("__type").value.toInt();
if (type == __CV_Device) name_from = Q2PIString(((DeviceItem*)bi_f)->name());
if (type == __CV_Filter) name_from = Q2PIString(((FilterItem*)bi_f)->name());
if (name_from.isEmpty()) continue;
PIPacketExtractor * pe = conn->addFilter(Q2PIString(fi_t->name()),conn->deviceByName(name_from), fi_t->mode());
if (!pe) continue;
pe->setBufferSize(fi_t->bufferSize());
pe->setHeader(PIByteArray::fromUserInput(Q2PIString(fi_t->header())));
pe->setFooter(PIByteArray::fromUserInput(Q2PIString(fi_t->footer())));
pe->setTimeout(fi_t->timeout());
pe->setPacketSize(fi_t->packetSize());
pe->setPayloadSize(fi_t->packetSize());
PIDiagnostics * diag = conn->diagnostic(pe);
if (diag) diag->setDisconnectTimeout(fi_t->disconnectTimeout());
QList<BlockBusItem*> nb = fi_t->pinByText("out")->connectedBuses();
foreach (BlockBusItem * b_, nb)
if (!pbuses.contains(b_)) {
pbuses << b_;
nbuses << b_;
}
}
buses = nbuses;
}
}
foreach (BlockItem * b, devs) {
BlockItemPin * p = b->pinByText("write");
if (!p) continue;
QList<BlockBusItem*> buses = p->connectedBuses();
foreach (BlockBusItem * bus, buses) {
QList<BlockItem*> cb = bus->connectedBlocks();
if (cb.size() != 2) continue;
BlockItem * bi_f(0);
DeviceItem * di_t(0);
if (cb[0]->pinAtBus(bus)->text() == "write") {
di_t = (DeviceItem*)(cb[0]);
bi_f = (cb[1]);
} else if (cb[1]->pinAtBus(bus)->text() == "write") {
di_t = (DeviceItem*)(cb[1]);
bi_f = (cb[0]);
}
if (!bi_f || !di_t) continue;
QString name_from;
int type = bi_f->propertyByName("__type").value.toInt();
if (type == __CV_Sender) {
SenderItem * si = ((SenderItem*)bi_f);
si->name();
conn->addSender(Q2PIString(si->name()), Q2PIString(di_t->path()), si->frequency());
if (!si->data().isEmpty())
conn->setSenderFixedData(Q2PIString(si->name()), PIByteArray::fromUserInput(Q2PIString(si->data())));
} else {
if (type == __CV_Device) name_from = ((DeviceItem*)bi_f)->name();
if (type == __CV_Filter) name_from = ((FilterItem*)bi_f)->name();
if (name_from.isEmpty()) continue;
conn->addChannel(Q2PIString(name_from), Q2PIString(di_t->name()));
}
}
}
ui->codeEdit->setText(PI2QString(conn->makeConfig()));
}
void ConnectionEdit::on_buttonRemove_clicked() {
ui->blockView->removeSelected();
recreateConnection();
}
void ConnectionEdit::on_buttonClear_clicked() {
ui->blockView->removeAll();
recreateConnection();
}
void ConnectionEdit::on_buttonFilterAdd_clicked() {
if (!conn) return;
applyFilter(ui->blockView->addFilter(ui->lineFilter->text()));
}
void ConnectionEdit::on_buttonFilterModify_clicked() {
QList<QGraphicsItem*> si = ui->blockView->scene()->selectedItems();
if (si.isEmpty()) return;
if (!qgraphicsitem_cast<BlockItem*>(si[0])) return;
if (qgraphicsitem_cast<BlockItem*>(si[0])->propertyByName("__type").value.toInt() != __CV_Filter)
return;
applyFilter(qgraphicsitem_cast<FilterItem*>(si[0]));
}
void ConnectionEdit::on_buttonDeviceAdd_clicked() {
if (!conn) return;
QString n = ui->lineDevice->text();
if (n.isEmpty()) {
udevicenum++;
n = "device" + QString::number(udevicenum);
}
QString p = ui->linePath->currentText();
if (ui->linePath->findText(p) < 0) ui->linePath->addItem(p);
qDebug() << "add:" << n;
applyDevice(ui->blockView->addDevice(n, ui->linePath->currentText()));
}
void ConnectionEdit::on_buttonDeviceModify_clicked() {
QList<QGraphicsItem*> si = ui->blockView->scene()->selectedItems();
if (si.isEmpty()) return;
if (!qgraphicsitem_cast<BlockItem*>(si[0])) return;
if (qgraphicsitem_cast<BlockItem*>(si[0])->propertyByName("__type").value.toInt() != __CV_Device)
return;
applyDevice(qgraphicsitem_cast<DeviceItem*>(si[0]));
}
void ConnectionEdit::on_buttonSenderAdd_clicked() {
if (!conn) return;
applySender(ui->blockView->addSender(ui->lineSender->text()));
}
void ConnectionEdit::on_buttonSenderModify_clicked() {
QList<QGraphicsItem*> si = ui->blockView->scene()->selectedItems();
if (si.isEmpty()) return;
if (!qgraphicsitem_cast<BlockItem*>(si[0])) return;
if (qgraphicsitem_cast<BlockItem*>(si[0])->propertyByName("__type").value.toInt() != __CV_Sender)
return;
applySender(qgraphicsitem_cast<SenderItem*>(si[0]));
}
void ConnectionEdit::on_comboSplit_currentIndexChanged(int index) {
int mode = ui->comboSplit->itemData(index).toInt();
switch (mode) {
case PIPacketExtractor::None:
ui->widgetHeader->setEnabled(false);
ui->widgetFooter->setEnabled(false);
ui->widgetTimeout->setEnabled(false);
ui->widgetSize->setEnabled(false);
break;
case PIPacketExtractor::Header:
ui->widgetHeader->setEnabled(true);
ui->widgetFooter->setEnabled(false);
ui->widgetTimeout->setEnabled(false);
ui->widgetSize->setEnabled(true);
break;
case PIPacketExtractor::Footer:
ui->widgetHeader->setEnabled(false);
ui->widgetFooter->setEnabled(true);
ui->widgetTimeout->setEnabled(false);
ui->widgetSize->setEnabled(true);
break;
case PIPacketExtractor::HeaderAndFooter:
ui->widgetHeader->setEnabled(true);
ui->widgetFooter->setEnabled(true);
ui->widgetTimeout->setEnabled(false);
ui->widgetSize->setEnabled(false);
break;
case PIPacketExtractor::Timeout:
ui->widgetHeader->setEnabled(false);
ui->widgetFooter->setEnabled(false);
ui->widgetTimeout->setEnabled(true);
ui->widgetSize->setEnabled(false);
break;
case PIPacketExtractor::Size:
ui->widgetHeader->setEnabled(false);
ui->widgetFooter->setEnabled(false);
ui->widgetTimeout->setEnabled(false);
ui->widgetSize->setEnabled(true);
break;
default: break;
}
}

View File

@@ -0,0 +1,80 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONNECTION_EDIT_H
#define CONNECTION_EDIT_H
#include <QDialog>
#include "piconnection.h"
namespace Ui {
class ConnectionEdit;
}
class FilterItem;
class DeviceItem;
class SenderItem;
class ConnectionEdit: public QDialog {
Q_OBJECT
public:
explicit ConnectionEdit(QWidget * parent = 0);
~ConnectionEdit();
QString configuration() const;
QByteArray model() const;
QString name() const;
void setName(const QString & name);
void addDevice(const QString & name, const QString & path);
void setModel(const QByteArray & m);
private:
void accept();
void keyPressEvent(QKeyEvent *) {}
void applyFilter(FilterItem * b);
void applyDevice(DeviceItem * b);
void applySender(SenderItem * b);
int getOptions() const;
void setOptions(int o);
Ui::ConnectionEdit * ui;
PIConnection * conn;
bool loading;
int udevicenum;
private slots:
void recreateRequest() {if (!loading) QMetaObject::invokeMethod(this, "recreateConnection", Qt::QueuedConnection);}
void on_buttonRemove_clicked();
void on_buttonClear_clicked();
void on_buttonFilterAdd_clicked();
void on_buttonFilterModify_clicked();
void on_buttonDeviceAdd_clicked();
void on_buttonDeviceModify_clicked();
void on_buttonSenderAdd_clicked();
void on_buttonSenderModify_clicked();
void on_comboSplit_currentIndexChanged(int index);
void selectionChanged();
public slots:
void recreateConnection();
};
#endif // CONNECTION_EDIT_H

View File

@@ -0,0 +1,898 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConnectionEdit</class>
<widget class="QDialog" name="ConnectionEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>794</width>
<height>799</height>
</rect>
</property>
<property name="windowTitle">
<string>Connection editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<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_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineName"/>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Device</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelFilter_4">
<property name="text">
<string>Name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="CLineEdit" name="lineDevice"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelFilter_11">
<property name="text">
<string>Path:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="EComboBox" name="linePath">
<property name="editable">
<bool>true</bool>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<item>
<property name="text">
<string>eth://UDP:127.0.0.1:12345:127.0.0.1:12346</string>
</property>
</item>
<item>
<property name="text">
<string>eth://TCP:127.0.0.1:16666</string>
</property>
</item>
<item>
<property name="text">
<string>eth://UDP:192.168.0.5:16666:192.168.0.6:16667:mcast:234.0.2.1:mcast:234.0.2.2</string>
</property>
</item>
<item>
<property name="text">
<string>file://./text.txt</string>
</property>
</item>
<item>
<property name="text">
<string>binlog://./logs/:mylog_:1</string>
</property>
</item>
<item>
<property name="text">
<string>ser:///dev/ttyUSB0:9600:8:N:1</string>
</property>
</item>
<item>
<property name="text">
<string>ser://COM32:115200:8:N:1</string>
</property>
</item>
<item>
<property name="text">
<string>usb://0bb4:0c86:1:1:2</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelFilter_12">
<property name="text">
<string>Mode:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboMode"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelFilter_14">
<property name="text">
<string>Options:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QVBoxLayout" name="layoutOptions">
<property name="spacing">
<number>2</number>
</property>
</layout>
</item>
<item row="4" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="labelFilter_13">
<property name="text">
<string>Disconnect timeout:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDeviceDT">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="value">
<double>3.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelFilter_15">
<property name="text">
<string>Buffer size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinDeviceBS">
<property name="suffix">
<string> b</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</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>1</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item>
<widget class="QPushButton" name="buttonDeviceAdd">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonDeviceModify">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Modify</string>
</property>
<property name="icon">
<iconset resource="piconnedit/piconnedit.qrc">
<normaloff>:/icons/document-save-.png</normaloff>:/icons/document-save-.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Filter</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelFilter">
<property name="text">
<string>Name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="CLineEdit" name="lineFilter"/>
</item>
<item>
<widget class="QComboBox" name="comboSplit"/>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Parameters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QWidget" name="widgetHeader" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelFilter_2">
<property name="text">
<string>Header:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="CLineEdit" name="lineHeader"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widgetFooter" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelFilter_3">
<property name="text">
<string>Footer:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="CLineEdit" name="lineFooter"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QWidget" name="widgetTimeout" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelFilter_7">
<property name="text">
<string>Timeout:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinTimeout">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widgetSize" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelFilter_8">
<property name="text">
<string>Size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSize">
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QWidget" name="widgetDT" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelFilter_9">
<property name="text">
<string>Disconnect timeout:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinFilterDT">
<property name="suffix">
<string> ms</string>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="value">
<double>3.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSize_2" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="margin">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelFilter_17">
<property name="text">
<string>Buffer size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinFilterBS">
<property name="suffix">
<string> b</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>65536</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="buttonFilterAdd">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonFilterModify">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Modify</string>
</property>
<property name="icon">
<iconset resource="piconnedit/piconnedit.qrc">
<normaloff>:/icons/document-save-.png</normaloff>:/icons/document-save-.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Sender</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="labelFilter_5">
<property name="text">
<string>Name:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="CLineEdit" name="lineSender"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelFilter_16">
<property name="text">
<string>Frequency:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinFrequency">
<property name="suffix">
<string> Hz</string>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelFilter_6">
<property name="text">
<string>Data:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="CLineEdit" name="lineData"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>77</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<widget class="QPushButton" name="buttonSenderAdd">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSenderModify">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Modify</string>
</property>
<property name="icon">
<iconset resource="piconnedit/piconnedit.qrc">
<normaloff>:/icons/document-save-.png</normaloff>:/icons/document-save-.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonRemove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonClear">
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="piconnedit/piconnedit.qrc">
<normaloff>:/icons/edit-clear-.png</normaloff>:/icons/edit-clear-.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="ConnectionView" name="blockView">
<property name="traceConsiderBuses">
<bool>false</bool>
</property>
<property name="pinMulticonnect" stdset="0">
<bool>true</bool>
</property>
<property name="miniMap" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QCodeEdit" name="codeEdit"/>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>BlockView</class>
<extends>QGraphicsView</extends>
<header>blockview.h</header>
</customwidget>
<customwidget>
<class>CLineEdit</class>
<extends>QLineEdit</extends>
<header>clineedit.h</header>
</customwidget>
<customwidget>
<class>EComboBox</class>
<extends>QComboBox</extends>
<header>ecombobox.h</header>
</customwidget>
<customwidget>
<class>QCodeEdit</class>
<extends>QWidget</extends>
<header>qcodeedit.h</header>
</customwidget>
<customwidget>
<class>ConnectionView</class>
<extends>BlockView</extends>
<header>piqt_connection_view.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="piconnedit/piconnedit.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ConnectionEdit</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>442</x>
<y>738</y>
</hint>
<hint type="destinationlabel">
<x>413</x>
<y>426</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConnectionEdit</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>669</x>
<y>738</y>
</hint>
<hint type="destinationlabel">
<x>643</x>
<y>428</y>
</hint>
</hints>
</connection>
<connection>
<sender>lineName</sender>
<signal>editingFinished()</signal>
<receiver>ConnectionEdit</receiver>
<slot>recreateConnection()</slot>
<hints>
<hint type="sourcelabel">
<x>644</x>
<y>29</y>
</hint>
<hint type="destinationlabel">
<x>662</x>
<y>-5</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>recreateConnection()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,204 @@
#include "piqt_connection_view.h"
#include "picodeinfo.h"
#include "piqt.h"
#include <alignedtextitem.h>
DeviceItem::DeviceItem(): BlockItem() {
addProperty(BlockItem::Property("__type", "", __CV_Device));
addProperty(BlockItem::Property("bufferSize", "", 4096));
setSize(200, 80);
setColor(QColor(192, 192, 255));
text_name = new AlignedTextItem();
text_path = new AlignedTextItem();
QFont fnt(text_name->font()); fnt.setBold(true);
text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_name->setFont(fnt);
text_name->setPos(0., -size().height() / 2.);
addDecor(text_name);
fnt.setBold(false);
fnt.setPointSizeF(fnt.pointSizeF() - 2.);
text_path->setFont(fnt);
text_path->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_path->setPos(0., -size().height() / 2. + 20);
addDecor(text_path);
addPin(Qt::AlignLeft, 0, "write", "");
addPin(Qt::AlignRight, 0, "read", "");
}
void DeviceItem::rename() {
QString ms;
BlockItemPin * pr = pinByText("read"), * pw = pinByText("write");
switch (mode()) {
case PIIODevice::ReadOnly: ms = "ro"; pr->show(); pw->hide(); break;
case PIIODevice::WriteOnly: ms = "wo"; pr->hide(); pw->show(); break;
case PIIODevice::ReadWrite: ms = "rw"; pr->show(); pw->show(); break;
}
text_name->setText(name() + " (" + ms + ")");
text_path->setText(path());
}
FilterItem::FilterItem(): BlockItem() {
addProperty(BlockItem::Property("__type", "", __CV_Filter));
addProperty(BlockItem::Property("bufferSize", "", 65536));
setSize(140, 80);
setPos(200, 0);
setColor(QColor(192, 255, 192));
text_name = new AlignedTextItem();
text_mode = new AlignedTextItem();
QFont fnt(text_name->font()); fnt.setBold(true);
text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_name->setFont(fnt);
text_name->setPos(0., -size().height() / 2.);
addDecor(text_name);
fnt.setBold(false);
fnt.setPointSizeF(fnt.pointSizeF() - 2.);
text_mode->setFont(fnt);
text_mode->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_mode->setPos(0., -size().height() / 2. + 20);
addDecor(text_mode);
addPin(Qt::AlignLeft, 0, "in", "");
addPin(Qt::AlignRight, 0, "out", "");
}
void FilterItem::rename() {
text_name->setText(name());
QString ms;
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("PIPacketExtractor::SplitMode", 0);
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & i, ei->members)
if (i.value == mode()) {
ms = PI2QString(i.name);
break;
}
}
text_mode->setText(ms);
}
SenderItem::SenderItem(): BlockItem() {
addProperty(BlockItem::Property("__type", "", __CV_Sender));
setSize(140, 80);
setPos(-200, 0);
setColor(QColor(255, 192, 192));
text_name = new AlignedTextItem();
text_frequency = new AlignedTextItem();
QFont fnt(text_name->font()); fnt.setBold(true);
text_name->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_name->setFont(fnt);
text_name->setPos(0., -size().height() / 2.);
addDecor(text_name);
fnt.setBold(false);
fnt.setPointSizeF(fnt.pointSizeF() - 2.);
text_frequency->setFont(fnt);
text_frequency->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
text_frequency->setPos(0., -size().height() / 2. + 20);
addDecor(text_frequency);
addPin(Qt::AlignRight, 0, "out", "");
}
void SenderItem::rename() {
text_name->setText(name());
text_frequency->setText(QString::number(frequency()) + " Hz");
}
ConnectionView::ConnectionView(QWidget * parent): BlockView(parent) {
}
ConnectionView::~ConnectionView() {
}
DeviceItem * ConnectionView::addDevice(const QString & name, const QString & path) {
DeviceItem * ret = findDevice(name);
if (ret) return ret;
ret = new DeviceItem();
PIString dp;
PIIODevice::DeviceMode dm;
PIIODevice::splitFullPath(Q2PIString(path), &dp, &dm);
ret->setPos(0, 0);
ret->setName(name);
ret->setPath(PI2QString(dp));
ret->setMode(dm);
ret->setDisconnectTimeout(3.);
ret->setBufferSize(4096);
placeBlock(ret, allDevices());
addItem(ret);
return ret;
}
FilterItem * ConnectionView::addFilter(const QString & name) {
FilterItem * ret = new FilterItem();
ret->setDisconnectTimeout(3.);
ret->setBufferSize(65536);
ret->setName(name);
placeBlock(ret, allFilters());
addItem(ret);
return ret;
}
SenderItem * ConnectionView::addSender(const QString & name) {
SenderItem * ret = new SenderItem();
ret->setName(name);
placeBlock(ret, allSenders());
addItem(ret);
return ret;
}
DeviceItem * ConnectionView::findDevice(const QString & name) const {
QList<BlockItem*> blockl = blocks();
foreach (BlockItem * b, blockl)
if ((b->propertyByName("name").value == name) && (b->propertyByName("__type").value.toInt() == __CV_Device))
return (DeviceItem*)b;
return 0;
}
void ConnectionView::loadBus(BlockBusItem * bus) {
bus->setEndpointsNumber(2);
}
void ConnectionView::placeBlock(BlockItem * b, QList<BlockItem * > coll) {
if (coll.isEmpty()) return;
QList<QRectF> collr;
foreach (BlockItem * i, coll)
collr << i->sceneBoundingRect();
while (true) {
QRectF br = b->sceneBoundingRect();
bool ok = true;
for (int i = 0; i < collr.size(); ++i)
if (br.intersects(collr[i])) {
ok = false;
break;
}
if (ok) break;
b->moveBy(0., grid_step);
}
b->moveBy(0., grid_step * 2.);
}
QList<BlockItem * > ConnectionView::allByType(int type_) const {
QList<BlockItem*> blockl = blocks(), ret;
foreach (BlockItem * b, blockl)
if (b->propertyByName("__type").value.toInt() == type_)
ret << b;
return ret;
}

View File

@@ -0,0 +1,132 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONNECTION_VIEW_H
#define CONNECTION_VIEW_H
#include "blockview.h"
#include "piconnection.h"
const int __CV_Device = 1;
const int __CV_Filter = 2;
const int __CV_Sender = 3;
class DeviceItem: public BlockItem {
public:
DeviceItem();
void setName(const QString & n) {addProperty(BlockItem::Property("name", "", n)); rename();}
void setPath(const QString & p) {addProperty(BlockItem::Property("device", "", p)); rename();}
void setMode(PIIODevice::DeviceMode m) {addProperty(BlockItem::Property("mode", "", int(m))); rename();}
void setOptions(PIIODevice::DeviceOptions o) {addProperty(BlockItem::Property("options", "", int(o))); rename();}
void setDisconnectTimeout(double v) {addProperty(BlockItem::Property("disconnectTimeout", "", v)); rename();}
void setBufferSize(int v) {addProperty(BlockItem::Property("bufferSize", "", v)); rename();}
QString name() const {return propertyByName("name").value.toString();}
QString path() const {return propertyByName("device").value.toString();}
PIIODevice::DeviceMode mode() const {return PIIODevice::DeviceMode(propertyByName("mode").value.toInt());}
PIIODevice::DeviceOptions options() const {return PIIODevice::DeviceOptions(propertyByName("options").value.toInt());}
double disconnectTimeout() const {return propertyByName("disconnectTimeout").value.toDouble();}
int bufferSize() const {return propertyByName("bufferSize").value.toInt();}
void rename();
protected:
AlignedTextItem * text_name, * text_path;
};
class FilterItem: public BlockItem {
public:
FilterItem();
void setName(const QString & n) {addProperty(BlockItem::Property("name", "", n)); rename();}
void setMode(PIPacketExtractor::SplitMode m) {addProperty(BlockItem::Property("mode", "", int(m))); rename();}
void setHeader(const QString & v) {addProperty(BlockItem::Property("header", "", v)); rename();}
void setFooter(const QString & v) {addProperty(BlockItem::Property("footer", "", v)); rename();}
void setTimeout(double v) {addProperty(BlockItem::Property("timeout", "", v)); rename();}
void setPacketSize(int v) {addProperty(BlockItem::Property("size", "", v)); rename();}
void setDisconnectTimeout(double v) {addProperty(BlockItem::Property("disconnectTimeout", "", v)); rename();}
void setBufferSize(int v) {addProperty(BlockItem::Property("bufferSize", "", v)); rename();}
QString name() const {return propertyByName("name").value.toString();}
PIPacketExtractor::SplitMode mode() const {return PIPacketExtractor::SplitMode(propertyByName("mode").value.toInt());}
QString header() const {return propertyByName("header").value.toString();}
QString footer() const {return propertyByName("footer").value.toString();}
double timeout() const {return propertyByName("timeout").value.toDouble();}
int packetSize() const {return propertyByName("size").value.toInt();}
double disconnectTimeout() const {return propertyByName("disconnectTimeout").value.toDouble();}
int bufferSize() const {return propertyByName("bufferSize").value.toInt();}
void rename();
protected:
AlignedTextItem * text_name, * text_mode;
};
class SenderItem: public BlockItem {
public:
SenderItem();
void setName(const QString & n) {addProperty(BlockItem::Property("name", "", n)); rename();}
void setData(const QString & p) {addProperty(BlockItem::Property("data", "", p)); rename();}
void setFrequency(double m) {addProperty(BlockItem::Property("frequency", "", m)); rename();}
QString name() const {return propertyByName("name").value.toString();}
QString data() const {return propertyByName("data").value.toString();}
double frequency() const {return propertyByName("frequency").value.toDouble();}
void rename();
protected:
AlignedTextItem * text_name, * text_frequency;
};
class ConnectionView: public BlockView {
Q_OBJECT
public:
explicit ConnectionView(QWidget * parent = 0);
~ConnectionView();
DeviceItem * addDevice(const QString & name, const QString & path);
FilterItem * addFilter(const QString & name);
SenderItem * addSender(const QString & name);
DeviceItem * findDevice(const QString & name) const;
QList<BlockItem * > allDevices() const {return allByType(__CV_Device);}
QList<BlockItem * > allFilters() const {return allByType(__CV_Filter);}
QList<BlockItem * > allSenders() const {return allByType(__CV_Sender);}
private:
QSize sizeHint() const {return QSize(800, 600);}
void loadBus(BlockBusItem * bus);
void placeBlock(BlockItem * b, QList<BlockItem*> coll);
QList<BlockItem * > allByType(int type_) const;
private slots:
};
#endif // CONNECTION_VIEW_H

View File

@@ -0,0 +1,70 @@
#include "piqt_highlighter.h"
ConfigHighlighter::ConfigHighlighter(QTextDocument * parent): QSyntaxHighlighter(parent) {
HighlightingRule rule;
valueNameFormat.setForeground(QColor(0, 64, 154));
rule.pattern = QRegExp("[^=]"); //"\\b[A-Za-z0-9_]+(?=\\()");
rule.format = valueNameFormat;
highlightingRules.append(rule);
valueFormat.setForeground(QColor(192, 0, 0));
rule.pattern = QRegExp("=[^\n]*");
rule.format = valueFormat;
highlightingRules.append(rule);
equalFormat.setFontWeight(QFont::Bold);
equalFormat.setForeground(QColor(96, 126, 0));
rule.pattern = QRegExp("=");
rule.format = equalFormat;
highlightingRules.append(rule);
sectionFormat.setFontWeight(QFont::Bold);
sectionFormat.setForeground(QColor(0, 32, 64));
rule.pattern = QRegExp("\\[.*\\]");
rule.format = sectionFormat;
highlightingRules.append(rule);
//substFormat.setFontWeight(QFont::Bold);
substFormat.setForeground(QColor(192, 0, 192));
rule.pattern = QRegExp("\\$\\{.*\\}+");
rule.pattern.setMinimal(true);
rule.format = substFormat;
highlightingRules.append(rule);
rule.pattern = QRegExp("\\$\\{[^\\{]*\\}+");
highlightingRules.append(rule);
singleLineCommentFormat.setFontItalic(true);
singleLineCommentFormat.setForeground(QColor(128, 128, 128));
rule.pattern = QRegExp("#[^\n]*");
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
spaceFormat.setForeground(QColor(210, 210, 210));
//commentStartExpression = QRegExp("/\\*");
//commentEndExpression = QRegExp("\\*/");
}
void ConfigHighlighter::highlightBlock(const QString & text) {
foreach (const HighlightingRule &rule, highlightingRules) {
QRegExp expression(rule.pattern);
int index = expression.indexIn(text);
while (index >= 0) {
int length = expression.matchedLength();
setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length);
}
}
setCurrentBlockState(0);
QRegExp expression = QRegExp("[ |\t]");
int index = expression.indexIn(text);
while (index >= 0) {
int length = expression.matchedLength();
setFormat(index, length, spaceFormat);
index = expression.indexIn(text, index + length);
}
}

View File

@@ -0,0 +1,50 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONF_HIGHLIGHTER_H
#define CONF_HIGHLIGHTER_H
#include <QSyntaxHighlighter>
#include <QTextCursor>
#include <QTextCharFormat>
class QTextDocument;
class ConfigHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
ConfigHighlighter(QTextDocument *parent = 0);
QTextCursor cursor;
private:
void highlightBlock(const QString &text);
struct HighlightingRule {
QRegExp pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QRegExp commentStartExpression, commentEndExpression;
QTextCharFormat singleLineCommentFormat, valueNameFormat, valueFormat, equalFormat, sectionFormat, spaceFormat, substFormat;
};
#endif // CONF_HIGHTLIGHTER_H

View File

@@ -0,0 +1,92 @@
#include "piqt_iodevice_edit.h"
#include "piqt_iodevice_edit_dialog.h"
#include "qvariantedit_custom.h"
#include <QLineEdit>
#include <QToolButton>
#include <QBoxLayout>
#include <piqt.h>
#include <piiodevice.h>
IODeviceEdit::IODeviceEdit(QWidget * parent): QWidget(parent) {
dlg = new IODeviceEditDialog();
line = new QLineEdit();
btn = new QToolButton();
setLayout(new QBoxLayout(QBoxLayout::LeftToRight));
layout()->setContentsMargins(0, 0, 0, 0);
layout()->addWidget(line);
layout()->addWidget(btn);
connect(btn, SIGNAL(clicked(bool)), this, SLOT(buttonDlg_clicked()));
line->setReadOnly(true);
btn->setText(QString());
btn->setIcon(QIcon(":/icons/configure.png"));
btn->setToolTip(tr("Edit ..."));
}
IODeviceEdit::~IODeviceEdit() {
delete dlg;
}
QVariant IODeviceEdit::value() const {
return QVariant::fromValue(dev);
}
bool IODeviceEdit::isReadOnly() const {
return btn->isHidden();
}
void IODeviceEdit::setDevice(const QAD::IODevice & d) {
if (dev.toString() == d.toString()) return;
dev = d;
line->setText(dev.toString());
line->setCursorPosition(0);
emit valueChanged();
}
void IODeviceEdit::setValue(const QVariant & v) {
setDevice(v.value<QAD::IODevice>());
}
void IODeviceEdit::setReadOnly(bool yes) {
btn->setHidden(yes);
}
void IODeviceEdit::buttonDlg_clicked() {
QAD::IODevice d = dlg->getIODevice(dev);
if (!d.isValid()) return;
setDevice(d);
}
class Factory: public QVariantEditorFactoryBase {
public:
Factory() {}
virtual QWidget * createEditor() {return new IODeviceEdit();}
};
__IODeviceEditRegistrator__::__IODeviceEditRegistrator__() {
QVariantEditorFactories::registerEditorFactory(qMetaTypeId<QAD::IODevice>(), new Factory());
__QADTypesRegistrator__::instance()->toString_funcs.insert(qMetaTypeId<QAD::IODevice>(), &QAD_IODevice_toString);
}
void QAD_IODevice_toString(const QVariant & v, QString & r) {
PIVariantTypes::IODevice sd = Q2PIVariant(v).toIODevice();
// piCout << sd;
PIIODevice * rd = PIIODevice::createFromVariant(sd);
if (rd) {
PIString ps = rd->constructFullPath();
r = PI2QString(ps);
} else {
piCout << "error in " << sd;
}
}

View File

@@ -0,0 +1,71 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIQT_IODEVICE_EDIT_H
#define PIQT_IODEVICE_EDIT_H
#include <QWidget>
#include "qad_types.h"
class QLineEdit;
class QToolButton;
class IODeviceEditDialog;
class IODeviceEdit: public QWidget {
Q_OBJECT
Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
public:
explicit IODeviceEdit(QWidget * parent = 0);
~IODeviceEdit();
QVariant value() const;
bool isReadOnly() const;
private:
void setDevice(const QAD::IODevice & d);
QLineEdit * line;
QToolButton * btn;
IODeviceEditDialog * dlg;
QAD::IODevice dev;
public slots:
void setValue(const QVariant & v);
void setReadOnly(bool yes);
private slots:
void buttonDlg_clicked();
signals:
void valueChanged();
};
class __IODeviceEditRegistrator__ {
public:
__IODeviceEditRegistrator__();
};
static __IODeviceEditRegistrator__ __iodeviceeditregistrator__;
void QAD_IODevice_toString(const QVariant & v, QString & r);
#endif // PIQT_IODEVICE_EDIT_H

View File

@@ -0,0 +1,112 @@
#include "ui_piqt_iodevice_edit_dialog.h"
#include "piqt_iodevice_edit_dialog.h"
#include "piqt.h"
#include "picodeinfo.h"
#include "piiodevice.h"
#include <QCheckBox>
IODeviceEditDialog::IODeviceEditDialog(QWidget * parent): QDialog(parent) {
ui = new Ui::IODeviceEditDialog();
ui->setupUi(this);
PICodeInfo::EnumInfo * ei = PICodeInfo::enumsInfo->value("PIIODevice::DeviceMode");
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members)
ui->comboMode->addItem(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue<int>(e.value));
}
ui->comboMode->setCurrentIndex(ui->comboMode->count() - 1);
ei = PICodeInfo::enumsInfo->value("PIIODevice::DeviceOption");
if (ei) {
piForeachC (PICodeInfo::EnumeratorInfo & e, ei->members) {
QCheckBox * cb = new QCheckBox();
cb->setText(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"));
cb->setProperty("__value", e.value);
ui->layoutOptions->addWidget(cb);
}
}
PIStringList pl = PIIODevice::availablePrefixes();
piForeachC (PIString & p, pl) {
ui->comboType->addItem(PI2QString(p));
}
}
IODeviceEditDialog::~IODeviceEditDialog() {
}
int IODeviceEditDialog::getOptions() const {
int ret = 0;
for (int i = 0; i < ui->layoutOptions->count(); ++i) {
QCheckBox * cb = qobject_cast<QCheckBox*>(ui->layoutOptions->itemAt(i)->widget());
if (!cb) continue;
if (cb->isChecked())
ret |= cb->property("__value").toInt();
}
return ret;
}
void IODeviceEditDialog::setOptions(int o) {
for (int i = 0; i < ui->layoutOptions->count(); ++i) {
QCheckBox * cb = qobject_cast<QCheckBox*>(ui->layoutOptions->itemAt(i)->widget());
if (!cb) continue;
int cbf = cb->property("__value").toInt();
cb->setChecked((o & cbf) == cbf);
}
}
void IODeviceEditDialog::on_comboType_currentIndexChanged(int index) {
PIString prefix = Q2PIString(ui->comboType->currentText());
PIVector<const PIObject * > rd(PICollection::groupElements("__PIIODevices__"));
piForeachC (PIObject * d, rd) {
const PIIODevice * dev = ((const PIIODevice * )d);
if (prefix != dev->fullPathPrefix())
continue;
ps = PI2QPropertyStorage(dev->constructVariant().get());
ui->widgetProperties->setStorage(&ps);
return;
}
}
QAD::IODevice IODeviceEditDialog::getIODevice(const QAD::IODevice & d) {
setValue(d);
if (QDialog::exec() != QDialog::Accepted)
return QAD::IODevice();
return value();
}
QAD::IODevice IODeviceEditDialog::value() const {
QAD::IODevice d;
ui->widgetProperties->applyProperties();
d.prefix = ui->comboType->currentText();
d.mode = ui->comboMode->itemData(ui->comboMode->currentIndex()).toInt();
d.options = getOptions();
d.props = ps;
return d;
}
void IODeviceEditDialog::setValue(const QAD::IODevice & d) {
#if QT_VERSION >= 0x050000
ui->comboType->setCurrentText(d.prefix);
#else
for (int i = 0; i < ui->comboType->count(); ++i) {
if (ui->comboType->itemText(i) == d.prefix) {
ui->comboType->setCurrentIndex(i);
break;
}
}
#endif
for (int i = 0; i < ui->comboMode->count(); ++i)
if (ui->comboMode->itemData(i).toInt() == d.mode) {
ui->comboMode->setCurrentIndex(i);
break;
}
setOptions(d.options);
ps = d.props;
ui->widgetProperties->setStorage(&ps);
}

View File

@@ -0,0 +1,53 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIQT_IODEVICE_EDIT_DIALOG_H
#define PIQT_IODEVICE_EDIT_DIALOG_H
#include <QDialog>
#include "qad_types.h"
#include "propertystorage.h"
namespace Ui {
class IODeviceEditDialog;
}
class IODeviceEditDialog: public QDialog {
Q_OBJECT
public:
explicit IODeviceEditDialog(QWidget * parent = 0);
~IODeviceEditDialog();
QAD::IODevice getIODevice(const QAD::IODevice & d);
private:
QAD::IODevice value() const;
void setValue(const QAD::IODevice & d);
int getOptions() const;
void setOptions(int o);
PropertyStorage ps;
Ui::IODeviceEditDialog * ui;
private slots:
void on_comboType_currentIndexChanged(int index);
};
#endif // PIQT_IODEVICE_EDIT_DIALOG_H

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>IODeviceEditDialog</class>
<widget class="QDialog" name="IODeviceEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>387</width>
<height>345</height>
</rect>
</property>
<property name="windowTitle">
<string>IODevice</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboType"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelFilter_12">
<property name="text">
<string>Mode:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboMode"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelFilter_14">
<property name="text">
<string>Options:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="layoutOptions">
<property name="spacing">
<number>2</number>
</property>
</layout>
</item>
</layout>
</item>
<item>
<widget class="PropertyStorageEditor" name="widgetProperties" native="true"/>
</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>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>PropertyStorageEditor</class>
<extends>QWidget</extends>
<header>propertystorage_editor.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>IODeviceEditDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>227</x>
<y>326</y>
</hint>
<hint type="destinationlabel">
<x>144</x>
<y>302</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>IODeviceEditDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>315</y>
</hint>
<hint type="destinationlabel">
<x>304</x>
<y>306</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>recreateConnection()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,30 @@
#include "qpiconnection.h"
QPIConnection::QPIConnection(const QString & name): QObject(), PIConnection(Q2PIString(name)) {
setObjectName(name);
CONNECTU(this, dataReceivedEvent, this, piDataRec);
CONNECTU(this, packetReceivedEvent, this, piPacketRec);
}
bool QPIConnection::loadFromCMFile(const QString & file) {
QPIConfig f(file, QIODevice::ReadOnly);
if (!f.isOpen()) return false;
PIString cs = Q2PIString(QString::fromLatin1(f.getValue("config").toByteArray()));
configureFromString(&cs, Q2PIString(f.getValue("name").toString()));
return true;
}
void QPIConnection::piDataRec(const PIString & from, const PIByteArray & data) {
//piCout << from << PICoutManipulators::Hex << data;
QMetaObject::invokeMethod(this, "qDataReceivedEvent", Qt::QueuedConnection,
Q_ARG(QString, PI2QString(from)), Q_ARG(QByteArray, PI2QByteArray(data)));
}
void QPIConnection::piPacketRec(const PIString & from, const PIByteArray & data) {
QMetaObject::invokeMethod(this, "qPacketReceivedEvent", Qt::QueuedConnection,
Q_ARG(QString, PI2QString(from)), Q_ARG(QByteArray, PI2QByteArray(data)));
}

View File

@@ -0,0 +1,50 @@
/*
PIQt Utils - Qt utilites for PIP
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QPICONNECTION_H
#define QPICONNECTION_H
#include <QObject>
#include <QMetaObject>
#include "piconnection.h"
#include "qpiconfig.h"
#include "piqt.h"
class QPIConnection: public QObject, public PIConnection {
Q_OBJECT
PIOBJECT_SUBCLASS(QPIConnection, PIConnection)
public:
QPIConnection(const QString & name = QString());
bool loadFromCMFile(const QString & file);
protected:
void propertyChanged(const PIString & ) {setObjectName(PI2QString(name()));}
EVENT_HANDLER2(void, piDataRec, const PIString &, from, const PIByteArray &, data);
EVENT_HANDLER2(void, piPacketRec, const PIString &, from, const PIByteArray &, data);
public slots:
signals:
void qDataReceivedEvent(QString from, QByteArray data);
void qPacketReceivedEvent(QString from, QByteArray data);
};
#endif // QPICONNECTION_H