/
pi_coder
/
ByteMachine
Обзор
Документация
Войти
/
pi_coder
/
ByteMachine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/nodes/merge_node.cpp
369 строк
12 KB
pimenov-and
Перенос функциональности из старого проекта, в основном это описания узлов
19 июл 2026, 20:13
19 июл 2026, 20:13
cb3c51b
Код
Авторство
О чём код?
//////////////////////////////////////////////////////////////// // ByteMachine // Узел для слияния потоков данных //////////////////////////////////////////////////////////////// #include "merge_node.h" #include "node_name_manager.h" #include "colors.h" #include "qt_helper.h" #include "byte_list_helper.h" #include <QDomDocument> #include <QPainter> //============================================================== using std::size_t; using std::min; //============================================================== // Конструктор с параметрами //============================================================== MergeNode::MergeNode(QUndoStack *undoStack, QObject *parent) : BaseNode{undoStack, parent} { name_ = nodeNameManager()->addName("merge"); Q_ASSERT(!name_.isEmpty()); createInputPin1(); createInputPin2(); createOutputPin(); MergeNode::updateStateInfo(); } //============================================================== // Чтение из XML //============================================================== void MergeNode::readFromXml(const QDomElement &elem) { Q_ASSERT(!elem.isNull()); const QString name = readNameFromXml(elem); const qint32 left = readLeftFromXml(elem); const qint32 top = readTopFromXml(elem); const QString comment = readCommentFromXml(elem); setName(name); setLeft(left); setTop(top); setComment(comment); } //============================================================== // Запись в XML //============================================================== void MergeNode::writeToXml(QDomDocument &doc, QDomElement &elem) const { Q_ASSERT(!doc.isNull()); Q_ASSERT(!elem.isNull()); writeIdToXml(doc, elem); writeNameToXml(doc, elem); writeLeftToXml(doc, elem); writeTopToXml(doc, elem); writeCommentToXml(doc, elem); } //============================================================== // Рисование узла //============================================================== void MergeNode::draw(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); drawSimpleBody(painter, theme); drawPins(painter, theme); drawStateArea(painter, theme); drawComments(painter, theme); } //============================================================== // Получение копии узла //============================================================== ShPtrBaseNode MergeNode::clone() const { const ShPtrMergeNode cloneNode = ShPtrMergeNode::create( undoStack(), parent()); cloneNode->setUndo(true); cloneNode->setLeft(left()); cloneNode->setTop(top()); cloneNode->setComment(comment()); cloneNode->setUndo(false); return cloneNode; } //============================================================== // Получение текста подсказки //============================================================== QString MergeNode::tooltipText() const { QString text{}; text += QString{"%1: \"%2\"\n"}.arg(tr("Name"), name()); text += QString{"%1: \"%2\""}.arg(tr("Comment"), comment()); return text; } //============================================================== // Получение размера данных //============================================================== size_t MergeNode::dataSize() const { if (stateInfo_.isError()) { return 0; } return inputDataSize1() + inputDataSize2(); } //============================================================== // Получение байта данных //============================================================== quint8 MergeNode::dataByte(size_t index) const { Q_ASSERT(index < dataSize()); if (index < inputDataSize1()) { return inputPin1_->dataByte(index); } else { return inputPin2_->dataByte(index - inputDataSize1()); } } //============================================================== // Получение блока данных //============================================================== ByteList MergeNode::dataBlock(size_t index, size_t count) const { Q_ASSERT(index + count <= dataSize()); ByteList byteList{}; if (index < inputDataSize1()) { // Получение блока данных из первого подключения const size_t c1 = min(inputDataSize1(), count) - index; byteList << inputPin1_->dataBlock(index, c1); // Получение блока данных из второго подключения (если есть) if (index + count > inputDataSize1()) { const size_t c2 = min(inputDataSize1(), count) - index; byteList << inputPin2_->dataBlock(0, c2); } } else { const size_t i = index - inputDataSize1(); byteList << inputPin2_->dataBlock(i, count); } return byteList; } //============================================================== // Функция вызывается при изменении данных //============================================================== void MergeNode::dataChanged() { startHighlightTimer(); updateStateInfo(); outputPin_->dataChanged(); } //============================================================== // Получение входных пинов //============================================================== QVector<ShPtrInputPin> MergeNode::inputPins() { return QVector<ShPtrInputPin>{inputPin1_, inputPin2_}; } //============================================================== // Получение входных пинов (константный вариант) //============================================================== QVector<ShPtrConstInputPin> MergeNode::inputPins() const { return QVector<ShPtrConstInputPin>{inputPin1_, inputPin2_}; } //============================================================== // Получение выходных пинов //============================================================== QVector<ShPtrOutputPin> MergeNode::outputPins() { return QVector<ShPtrOutputPin>{outputPin_}; } //============================================================== // Получение выходных пинов (константный вариант) //============================================================== QVector<ShPtrConstOutputPin> MergeNode::outputPins() const { return QVector<ShPtrConstOutputPin>{outputPin_}; } //============================================================== // Функция получения имени свойства для графического // интерфейса по его системному имени //============================================================== QString MergeNode::getUiPropertyName(const QString &systemName) { const QMap<QString, QString> map { {"name", tr("Name")}, {"left", tr("Left")}, {"top", tr("Top")}, {"width", tr("Width")}, {"height", tr("Height")}, {"topLeft", tr("Top and left")}, {"size", tr("Size")}, {"comment", tr("Comment")} }; return map.value(systemName, tr("Unknown")); } //============================================================== // Функция перевода //============================================================== void MergeNode::retranslate() { updateStateInfo(); } //============================================================== // Функция вызывается при подключении выходного пина //============================================================== void MergeNode::slotOutputPinConnectChanged(ConnectStates state, InputPin *pin) { Q_UNUSED(state) Q_UNUSED(pin) } //============================================================== // Создание входного пина 1 //============================================================== void MergeNode::createInputPin1() { inputPin1_ = ShPtrInputPin::create(this, 0); } //============================================================== // Создание входного пина 2 //============================================================== void MergeNode::createInputPin2() { inputPin2_ = ShPtrInputPin::create(this, 1); } //============================================================== // Создание выходного пина //============================================================== void MergeNode::createOutputPin() { outputPin_ = ShPtrOutputPin::create(this, 0); connect(outputPin_.get(), &OutputPin::sigConnectChanged, this, &MergeNode::slotOutputPinConnectChanged); } //============================================================== // Получение признака подключения входного пина 1 //============================================================== bool MergeNode::isConnectedInputPin1() const { return inputPin1_->isConnected(); } //============================================================== // Получение признака подключения входного пина 2 //============================================================== bool MergeNode::isConnectedInputPin2() const { return inputPin2_->isConnected(); } //============================================================== // Получение размера входные данных для пина 1 //============================================================== size_t MergeNode::inputDataSize1() const { return isConnectedInputPin1() ? inputPin1_->dataSize() : 0; } //============================================================== // Получение размера входные данных для пина 2 //============================================================== size_t MergeNode::inputDataSize2() const { return isConnectedInputPin2() ? inputPin2_->dataSize() : 0; } //============================================================== // Обновление состояния узла //============================================================== void MergeNode::updateStateInfo() { const NodeStateInfo oldStateInfo = stateInfo_; if (!isConnectedInputPin1() && !isConnectedInputPin2()) { const QString msg = tr("Input pins is not connected"); stateInfo_ = NodeStateInfo{NodeStates::Error, msg}; } else if (!isConnectedInputPin1() || !isConnectedInputPin2()) { const QString msg = tr("Input pin is not connected"); stateInfo_ = NodeStateInfo{NodeStates::Warning, msg}; } else if (inputDataSize1() + inputDataSize2() == 0) { const QString msg = "No data"; stateInfo_ = NodeStateInfo{NodeStates::Warning, msg}; } else { stateInfo_ = NodeStateInfo{NodeStates::Success, QString{}}; } if (stateInfo_ != oldStateInfo) { emit sigChangedState(stateInfo_); } } //============================================================== // Вывод комментариев //============================================================== void MergeNode::drawComments(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); if (isCommentsVisible()) { QString comments{}; comments += QString{" <<< %1: \"%2\"\n"}.arg(tr("Name"), name()); comments += QString{" %1: \"%2\"\n"}.arg(tr("Comment"), comment()); #ifdef QT_DEBUG comments += " -\n"; comments += QString{" %1: %2\n"}.arg("Id").arg(id()); #endif // QT_DEBUG const int commentsLeft = right(); const int commentsTop = top() + (headerHeight() - charHeight()) / 2; const int commentsFlags = Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip; const QRect commentsRect{commentsLeft, commentsTop, 0, 0}; painter->setPen(Colors::nodeText(theme)); painter->drawText(commentsRect, commentsFlags, comments); } }