/
pi_coder
/
ByteMachine
Обзор
Документация
Войти
/
pi_coder
/
ByteMachine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/nodes/graph_node.cpp
424 строки
14 KB
pimenov-and
Перенос функциональности из старого проекта, в основном это описания узлов
19 июл 2026, 20:13
19 июл 2026, 20:13
cb3c51b
Код
Авторство
О чём код?
//////////////////////////////////////////////////////////////// // ByteMachine // Узел для показа графиков //////////////////////////////////////////////////////////////// #include "graph_node.h" #include "node_name_manager.h" #include "undo/undo_change_object_prop_value.h" #include "colors.h" #include <QDomDocument> #include <QPainter> #include <QUndoStack> //============================================================== using std::size_t; //============================================================== // Конструктор с параметрами //============================================================== GraphNode::GraphNode(QUndoStack *undoStack, QObject *parent) : BaseNode{undoStack, parent} { Q_ASSERT(undoStack != nullptr); name_ = nodeNameManager()->addName("graph"); Q_ASSERT(!name_.isEmpty()); createInputPin(); createOutputPin(); // Задание начальных размером const int width = GraphNode::minWidth(); const int height = GraphNode::minHeight(); setUndo(true); BaseNode::setWidth(width); BaseNode::setHeight(height); setUndo(false); GraphNode::updateStateInfo(); } //============================================================== // Чтение из XML //============================================================== void GraphNode::readFromXml(const QDomElement &elem) { Q_ASSERT(!elem.isNull()); const QString name = readNameFromXml(elem); const qint32 left = readLeftFromXml(elem); const qint32 top = readTopFromXml(elem); const qint32 width = readWidthFromXml(elem); const bool isBypass = readBypassFromXml(elem); const QString comment = readCommentFromXml(elem); setName(name); setLeft(left); setTop(top); setWidth(width); setBypass(isBypass); setComment(comment); } //============================================================== // Запись в XML //============================================================== void GraphNode::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); writeWidthToXml(doc, elem); writeHeightToXml(doc, elem); writeBypassToXml(doc, elem); writeCommentToXml(doc, elem); } //============================================================== // Функция перерисовки //============================================================== void GraphNode::draw(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); drawHighlight(painter); drawBody(painter, theme); drawPins(painter, theme); drawStateArea(painter, theme); drawResizebleMarker(painter, theme); drawComments(painter, theme); } //============================================================== // Получение копии узла //============================================================== ShPtrBaseNode GraphNode::clone() const { const auto cloneNode = ShPtrGraphNode::create( undoStack(), parent()); cloneNode->setUndo(true); cloneNode->setName(name()); cloneNode->setLeft(left()); cloneNode->setTop(top()); cloneNode->setWidth(width()); cloneNode->setHeight(height()); cloneNode->setByteOrder(byteOrder()); cloneNode->setBypass(isBypass()); cloneNode->setUndo(false); return cloneNode; } //============================================================== // Получение текста подсказки //============================================================== QString GraphNode::tooltipText() const { return QString{}; } //============================================================== // Получение размера данных //============================================================== size_t GraphNode::dataSize() const { return 0; } //============================================================== // Получение байта данных //============================================================== quint8 GraphNode::dataByte(size_t index) const { Q_UNUSED(index) return 0; } //============================================================== // Получение блока данных //============================================================== ByteList GraphNode::dataBlock(size_t index, size_t count) const { Q_UNUSED(index) Q_UNUSED(count) return ByteList{}; } //============================================================== // Функция вызывается при изменении данных //============================================================== void GraphNode::dataChanged() { } //============================================================== // Получение входных пинов //============================================================== QVector<ShPtrInputPin> GraphNode::inputPins() { return QVector<ShPtrInputPin>{inputPin_}; } //============================================================== // Получение входных пинов (константный вариант) //============================================================== QVector<ShPtrConstInputPin> GraphNode::inputPins() const { return QVector<ShPtrConstInputPin>{inputPin_}; } //============================================================== // Получение выходных пинов //============================================================== QVector<ShPtrOutputPin> GraphNode::outputPins() { return QVector<ShPtrOutputPin>{outputPin_}; } //============================================================== // Получение выходных пинов (константный вариант) //============================================================== QVector<ShPtrConstOutputPin> GraphNode::outputPins() const { return QVector<ShPtrConstOutputPin>{outputPin_}; } //============================================================== // Задание порядка байтов //============================================================== void GraphNode::setByteOrder(ByteOrders order) { if (byteOrder_ != order) { const ByteOrders oldByteOrder = byteOrder_; byteOrder_ = order; const PropValue value{"byteOrder", QVariant::fromValue(byteOrder_)}; emit sigChangedProp(value); if (!isUndo_) { Q_ASSERT(undoStack_ != nullptr); const auto undoCmd = new UndoChangeObjectPropValue{this, "byteOrder", QVariant::fromValue(byteOrder_), QVariant::fromValue(oldByteOrder)}; undoStack_->push(undoCmd); } startHighlightTimer(); } } //============================================================== // Сброс порядка байтов //============================================================== void GraphNode::resetByteOrder() { setByteOrder(ByteOrders::LittleEndian); } //============================================================== // Задание признака пропуска //============================================================== void GraphNode::setBypass(bool bypass) { if (isBypass_ != bypass) { const bool oldBypass = isBypass_; isBypass_ = bypass; const PropValue value{"bypass", isBypass_}; emit sigChangedProp(value); if (!isUndo_) { Q_ASSERT(undoStack_ != nullptr); const auto undoCmd = new UndoChangeObjectPropValue{this, "bypass", isBypass_, oldBypass}; undoStack_->push(undoCmd); } startHighlightTimer(); } } //============================================================== // Сброс признака пропуска //============================================================== void GraphNode::resetBypass() { setBypass(false); } //============================================================== // Функция получения имени свойства для графического // интерфейса по его системному имени //============================================================== QString GraphNode::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")}, {"byteOrder", tr("Byte order")}, {"bypass", tr("Bypass")} }; return map.value(systemName, tr("Unknown")); } //============================================================== // Функция перевода //============================================================== void GraphNode::retranslate() { updateStateInfo(); } //============================================================== // Функция вызывается при подключении выходного пина //============================================================== void GraphNode::slotOutputPinConnectChanged(ConnectStates state, InputPin *pin) { Q_ASSERT(!isUnknown(state)); Q_ASSERT(pin != nullptr); dataChanged(); const int conNodeId = pin->parentNode()->id(); const int conPinIndex = pin->parentNode()->indexOfInputPin(pin); const bool isCon = ::isConnect(state); emit sigChangedConnect(0, conNodeId, conPinIndex, isCon); } //============================================================== // Создание входного пина //============================================================== void GraphNode::createInputPin() { inputPin_ = ShPtrInputPin::create(this, 0); } //============================================================== // Создание выходного пина //============================================================== void GraphNode::createOutputPin() { outputPin_ = ShPtrOutputPin::create(this, 0); connect(outputPin_.get(), &OutputPin::sigConnectChanged, this, &GraphNode::slotOutputPinConnectChanged); } //============================================================== // Получение признака подключения входного пина //============================================================== bool GraphNode::isConnectedInputPin() const { return inputPin_->isConnected(); } //============================================================== // Получение размера входные данных //============================================================== size_t GraphNode::inputDataSize() const { return isConnectedInputPin() ? inputPin_->dataSize() : 0; } //============================================================== // Вывод тела //============================================================== void GraphNode::drawBody(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); // Вывод основы painter->setPen(Qt::transparent); painter->setBrush(Colors::nodeBack(theme)); painter->drawRect(rect().adjusted(-2, -2, 2, 2)); // больший размер для обводки контура // Вывод типа узла (в режиме пропуска выводится перечёркнутым) painter->setPen(Colors::nodeText(theme)); if (!isBypass()) { painter->drawText(left(), top(), width(), headerHeight(), Qt::AlignCenter, strType()); } else { QFont font = painter->font(); font.setStrikeOut(true); painter->setFont(font); painter->drawText(left(), top(), width(), headerHeight(), Qt::AlignCenter, strType()); font.setStrikeOut(false); painter->setFont(font); } // Вывод разделительной линии painter->setPen(Colors::nodeBorder(theme)); painter->drawLine(left() + 1, top() + headerHeight(), right() - 2, top() + headerHeight()); // Обводка контура QPen borderPen{currentBorderColor(theme), 2}; borderPen.setJoinStyle(Qt::MiterJoin); painter->setPen(borderPen); painter->setBrush(Qt::transparent); painter->drawRect(rect()); } //============================================================== // Вывод комментариев //============================================================== void GraphNode::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); } } //============================================================== // Обновление состояния узла //============================================================== void GraphNode::updateStateInfo() { const NodeStateInfo oldStateInfo = stateInfo_; if (stateInfo_ != oldStateInfo) { emit sigChangedState(stateInfo_); } }