#include "piqt_connection_edit.h" #include "picodeinfo.h" #include "piqt.h" #include "piqt_connection_view.h" #include "piqt_highlighter.h" #include "ui_piqt_connection_edit.h" #include #include 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)), this, SLOT(recreateRequest())); connect(ui->blockView->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); conn = 0; PICodeInfo::EnumInfo * ei = PICODEINFO->enums().value("PIIODevice::DeviceMode"); if (ei) { piForeachC(PICodeInfo::EnumeratorInfo & e, ei->members) #if PIP_VERSION >= PIP_MAKE_VERSION(2, 39, 0) ui->comboMode->addItem(PI2QString(e.name.toString() + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue(e.value)); #else ui->comboMode->addItem(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue(e.value)); #endif } ui->comboMode->setCurrentIndex(ui->comboMode->count() - 1); ei = PICODEINFO->enums().value("PIIODevice::DeviceOption"); if (ei) { piForeachC(PICodeInfo::EnumeratorInfo & e, ei->members) { QCheckBox * cb = new QCheckBox(); #if PIP_VERSION >= PIP_MAKE_VERSION(2, 39, 0) cb->setText(PI2QString(e.name.toString() + " (" + PIString::fromNumber(e.value) + ")")); #else cb->setText(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")")); #endif cb->setProperty("__value", e.value); ui->layoutOptions->addWidget(cb); } } ei = PICODEINFO->enums().value("PIPacketExtractor::SplitMode"); if (ei) { piForeachC(PICodeInfo::EnumeratorInfo & e, ei->members) #if PIP_VERSION >= PIP_MAKE_VERSION(2, 39, 0) ui->comboSplit->addItem(PI2QString(e.name.toString() + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue(e.value)); #else ui->comboSplit->addItem(PI2QString(e.name + " (" + PIString::fromNumber(e.value) + ")"), QVariant::fromValue(e.value)); #endif } udevicenum = 0; } ConnectionEdit::~ConnectionEdit() { if (conn) { conn->stop(); delete conn; } } void ConnectionEdit::accept() { // bool ok = false; QList 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 busl = ui->blockView->buses(); s << busl.size(); foreach(BlockBusItem * b, busl) s << b->save(); QList 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 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(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(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(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 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 buses = p->connectedBuses(), nbuses; QSet pbuses; while (!buses.isEmpty()) { nbuses.clear(); foreach(BlockBusItem * bus, buses) { QList 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->setHeader(PIByteArray::fromUserInput(Q2PIString(fi_t->header()))); pe->setFooter(PIByteArray::fromUserInput(Q2PIString(fi_t->footer()))); pe->setTimeout(fi_t->timeout()); pe->setPayloadSize(fi_t->packetSize()); pe->setThreadedReadBufferSize(fi_t->bufferSize()); PIDiagnostics * diag = conn->diagnostic(pe); if (diag) diag->setDisconnectTimeout(fi_t->disconnectTimeout()); QList 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 buses = p->connectedBuses(); foreach(BlockBusItem * bus, buses) { QList 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 si = ui->blockView->scene()->selectedItems(); if (si.isEmpty()) return; if (!qgraphicsitem_cast(si[0])) return; if (qgraphicsitem_cast(si[0])->propertyByName("__type").value.toInt() != __CV_Filter) return; applyFilter(qgraphicsitem_cast(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 si = ui->blockView->scene()->selectedItems(); if (si.isEmpty()) return; if (!qgraphicsitem_cast(si[0])) return; if (qgraphicsitem_cast(si[0])->propertyByName("__type").value.toInt() != __CV_Device) return; applyDevice(qgraphicsitem_cast(si[0])); } void ConnectionEdit::on_buttonSenderAdd_clicked() { if (!conn) return; applySender(ui->blockView->addSender(ui->lineSender->text())); } void ConnectionEdit::on_buttonSenderModify_clicked() { QList si = ui->blockView->scene()->selectedItems(); if (si.isEmpty()) return; if (!qgraphicsitem_cast(si[0])) return; if (qgraphicsitem_cast(si[0])->propertyByName("__type").value.toInt() != __CV_Sender) return; applySender(qgraphicsitem_cast(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; } }