/
pi_coder
/
ByteMachine
Обзор
Документация
Войти
/
pi_coder
/
ByteMachine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/forms/form_designer.cpp
1 936 строк
73 KB
pimenov-and
Восстановление функционала старой версии
28 июл 2026, 20:04
28 июл 2026, 20:04
98412d0
Код
Авторство
О чём код?
//////////////////////////////////////////////////////////////// // ByteMachine // Виджет дизайнера //////////////////////////////////////////////////////////////// #include "form_designer.h" #include "project.h" #include "nodes/node_helper.h" #include "qt_helper.h" #include "nodes/com_port_manager.h" #include "global_settings.h" #include "math_helper.h" #include "colors.h" #include "icons.h" #include <QPainter> #include <QMouseEvent> #include <QPaintEvent> #include <QDragEnterEvent> #include <QDropEvent> //============================================================== // Конструктор с параметром //============================================================== FormDesigner::FormDesigner(QWidget *parent) : QWidget{parent} { ui_.setupUi(this); setConnections(); setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_NoSystemBackground); #ifdef Q_OS_WASM QFont font{"Segoe UI", 10}; setFont(font); #endif // Q_OS_WASM } //============================================================== // Задание видимости сетки //============================================================== void FormDesigner::setGridVisible(bool visible) { if (isGridVisible_ != visible) { isGridVisible_ = visible; update(); } } //============================================================== // Перетаскивание узла //============================================================== void FormDesigner::dragNode(const QPoint &pos) { isDragNode_ = true; dragNodePos_ = pos; update(); } //============================================================== // Скрытие перетаскиваемого узла //============================================================== void FormDesigner::hideDragNode() { isDragNode_ = false; dragNodePos_ = QPoint{}; update(); } //============================================================== // Отпускание узла //============================================================== void FormDesigner::dropNode(NodeTypes nodeType, const QPoint &pos) { Q_ASSERT(!isUnknown(nodeType)); isDragNode_ = false; dragNodePos_ = QPoint{}; const ShPtrBaseNode node = createNode(nodeType, project()->undoStack()); Q_ASSERT(node != nullptr); node->setTopLeft(pos); project()->addNode(node); update(); } //============================================================== // Добавление узла через контекстное меню //============================================================== void FormDesigner::slotAddNodeFromContextMenu() { const auto action = qobject_cast<QAction*>(sender()); Q_ASSERT(action != nullptr); QUndoStack *const undoStack = project()->undoStack(); const QString strNodeType = action->text(); const ShPtrBaseNode node = createNode(strNodeType, undoStack); Q_ASSERT(node != nullptr); node->setUndo(true); node->setTopLeft(menuPos_); node->setUndo(false); project()->addNode(node); } //============================================================== // Удаление узла через контекстное меню //============================================================== void FormDesigner::slotRemoveNodeFromContextMenu() { const ShPtrBaseNode node = project()->findSelectedNode(); if (node != nullptr) { project()->removeNode(node); } // qDebug() << "slotRemoveNodeFromContextMenu"; } //============================================================== // Функция вызывается при возникновении события //============================================================== void FormDesigner::changeEvent(QEvent *event) { Q_UNUSED(event) } #ifndef Q_OS_WASM //============================================================== // Функция вызывается при приёме перетаскиваемого узла //============================================================== void FormDesigner::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *const mimeData = event->mimeData(); if (mimeData->hasFormat("text/plain")) { const QString strNodeType = mimeData->text(); const NodeTypes nodeType = strToNodeType(strNodeType); if (!isUnknown(nodeType)) { event->acceptProposedAction(); } } } //============================================================== // Функция вызывается при отпускании перетаскиваемого узла //============================================================== void FormDesigner::dropEvent(QDropEvent *event) { const QString strNodeType = event->mimeData()->text(); const auto undoStack = project()->undoStack(); const ShPtrBaseNode node = createNode(strNodeType, undoStack); Q_ASSERT(node != nullptr); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) const QPoint nodePos = event->pos(); #else const QPoint nodePos = event->position().toPoint(); #endif node->setUndo(true); node->setTopLeft(nodePos); node->setUndo(false); project()->addNode(node); update(); } #endif // Q_OS_WASM //============================================================== // Функция вызывается при перерисовке //============================================================== void FormDesigner::paintEvent(QPaintEvent *event) { QPainter painter{this}; painter.setFont({"Courier New", 10}); const QRect &clipRect = event->rect(); setCharSize(&painter); const ColorThemes theme = globalSettings()->colorTheme(); fillBackgound(&painter, clipRect, theme); drawGrid(&painter, theme); drawPinConnectedLines(&painter, theme); drawNodes(&painter, theme); drawMoveConnection(&painter, theme); drawDragNode(&painter); } //============================================================== // Функция вызывается при нажатии мыши //============================================================== void FormDesigner::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { const QPoint pos = event->pos(); //------------------------------------------------------ // Попытка проведения связи из выходного пина //------------------------------------------------------ if (ShPtrOutputPin pin = project()->findNodeOutputPinByPt(pos, 5); pin != nullptr) { // Выделение узла BaseNode *const node = pin->parentNode(); Q_ASSERT(node != nullptr); const ShPtrBaseNode shPtrNode = project()->findNodeByPtr(node); Q_ASSERT(shPtrNode != nullptr); project()->setSelectedNode(shPtrNode); // Задание параметров подключения movingConnection_.outputPin = pin; movingConnection_.beginPt = movingConnection_.endPt = pin->rect().center(); } //------------------------------------------------------ // Попытка изменения связи из подключенного входного пина //------------------------------------------------------ else if (ShPtrInputPin pin = project()->findNodeInputPinByPt(pos, 5); (pin != nullptr) && pin->isConnected()) { const ShPtrOutputPin connectOutputPin = pin->outputPin(); // Задание параметров подключения movingConnection_.inputPin = pin; movingConnection_.beginPt = connectOutputPin->rect().center(); movingConnection_.endPt = pin->rect().center(); } //------------------------------------------------------ // При нажатии на область состояния //------------------------------------------------------ else if (ShPtrBaseNode node = project()->findStateAreaNodeByPt(pos); node != nullptr) { project()->setSelectedNode(node); } //------------------------------------------------------ // Проверка изменения размера узла //------------------------------------------------------ else if (ShPtrBaseNode node = project()->findResizebleAreaNodeFromCurrentByPt(pos)) { project()->setSelectedNode(node); resizebleNode_ = node; resizebleNode_->beginResize(); } //------------------------------------------------------ // Попытка захвата узла //------------------------------------------------------ else if (ShPtrBaseNode node = project()->findNodeByPt(pos); node != nullptr) { // Если нажата клавиша Ctrl, то создаётся копия узла if (isCtrlKey(event->modifiers())) { const auto cloneNode = node->clone(); project()->addNode(cloneNode); movingNode_ = cloneNode; const QPoint movingBeginPos = cloneNode->topLeft(); project()->setSelectedNode(movingNode_); movingDragOffsetNode_ = pos - movingBeginPos; } // Если нажата клавиша Alt и есть выходные пины, то задаётся связь else if (isAltKey(event->modifiers()) && node->isOutputPins()) { // Выделение узла project()->setSelectedNode(node); // Задание параметром связи const ShPtrOutputPin pin = node->outputPin(0); movingConnection_.outputPin = pin; movingConnection_.beginPt = movingConnection_.endPt = pin->rect().center(); } // Иначе узел перетаскивается else { movingNode_ = node; project()->setSelectedNode(movingNode_); const QPoint movingBeginPos = node->topLeft(); movingDragOffsetNode_ = pos - movingBeginPos; project()->bringNodeToFront(movingNode_); } } //------------------------------------------------------ // Иначе //------------------------------------------------------ else { project()->setSelectedNode(nullptr); } update(); } } //============================================================== // Функция вызвается при перемещении мыши //============================================================== void FormDesigner::mouseMoveEvent(QMouseEvent *event) { const QPoint pos = event->pos(); //---------------------------------------------------------- // Перемещении захваченного узла //---------------------------------------------------------- if (movingNode_ != nullptr) { // Узел начинает перетаскиваться только при некотором смещении от начального if (!movingNode_->isMoving()) { const QPoint topLeft = movingNode_->topLeft(); const QPoint newTopLeft = pos - movingDragOffsetNode_; if ((newTopLeft - topLeft).manhattanLength() >= QApplication::startDragDistance()) { movingNode_->beginMove(newTopLeft); } } // Перетаскивание узла собственно else { const QPoint topLeft = pos - movingDragOffsetNode_; movingNode_->move(topLeft); update(); } } //---------------------------------------------------------- // Перетаскивание связи узла //---------------------------------------------------------- else if (movingConnection_.isMove()) { if (movingConnection_.outputPin != nullptr) { // Если это попадание во входной пин элемента const BaseNode *const sourceNode = movingConnection_.outputPin->parentNode(); const ShPtrInputPin targetPin = project()->findNodeInputPinByPt(pos, 5); const ShPtrBaseNode targetNode = project()->findNodeByPt(pos); if ((targetPin != nullptr) && (sourceNode != targetPin->parentNode())) { const QPoint inputPinCenter = targetPin->rect().center(); movingConnection_.endPt = inputPinCenter; } else if ((targetNode != nullptr) && targetNode->isInputPins() && (sourceNode != targetNode) && isAltKey(event->modifiers())) { const QPoint inputPinCenter = targetNode->inputPin(0)->rect().center(); movingConnection_.endPt = inputPinCenter; } else { movingConnection_.endPt = pos; } } else { // Если это попадание во входной пин элемента const ShPtrInputPin targetInputPin = project()->findNodeInputPinByPt(pos, 5); const BaseNode *const sourceNode = movingConnection_.inputPin->outputPin()->parentNode(); if ((targetInputPin != nullptr) && (sourceNode != targetInputPin->parentNode())) { const QPoint targetInputPinCenter = targetInputPin->rect().center(); movingConnection_.endPt = targetInputPinCenter; } else { movingConnection_.endPt = pos; } } update(); } //---------------------------------------------------------- // Если курсов находится на области состояния узла, показать подсказку // состояния //---------------------------------------------------------- else if (ShPtrBaseNode node = project()->findStateAreaNodeByPt(pos); node != nullptr) { setToolTip(node->stateInfo().toStr()); setCursor(Qt::ArrowCursor); } //---------------------------------------------------------- // Изменение вида курсора при наведении на маркер изменения размера узла //---------------------------------------------------------- else if (resizebleNode_ != nullptr) { setCursor(Qt::SizeFDiagCursor); const QPoint topLeft = resizebleNode_->topLeft(); const int width = pos.x() - topLeft.x(); const int height = pos.y() - topLeft.y(); resizebleNode_->resizing(QSize{width, height}); update(); } //--------------------------------------------------------------- // Изменение вида курсора при наведении на маркер изменения размера узла //--------------------------------------------------------------- else if (project()->findResizebleAreaNodeFromCurrentByPt(pos) != nullptr) { setCursor(Qt::SizeFDiagCursor); } //---------------------------------------------------------- // Если курсор находится на узле, показать подсказку //---------------------------------------------------------- else if (ShPtrBaseNode node = project()->findNodeByPt(pos); node != nullptr) { setToolTip(node->tooltipText()); setCursor(Qt::ArrowCursor); } //---------------------------------------------------------- // Иначе //---------------------------------------------------------- else { setToolTip(QString{}); QToolTip::hideText(); setCursor(Qt::ArrowCursor); } } //============================================================== // Функция вызывается при отпускании мыши //============================================================== void FormDesigner::mouseReleaseEvent(QMouseEvent *event) { const QPoint pos = event->pos(); //---------------------------------------------------------- // Отпускание проведение связи из выходного пина //---------------------------------------------------------- if (movingConnection_.isMove()) { if (movingConnection_.outputPin != nullptr) { const ShPtrInputPin inputPin = project()->findNodeInputPinByPt(movingConnection_.endPt); if (inputPin != nullptr) { project()->setNodeConnection(movingConnection_.outputPin, nullptr, inputPin); } } else { const ShPtrInputPin inputPin = project()->findNodeInputPinByPt(pos); if (inputPin != movingConnection_.inputPin) { const ShPtrInputPin connectInputPin = movingConnection_.inputPin; const ShPtrOutputPin sourceOutputPin = connectInputPin->outputPin(); project()->setNodeConnection(sourceOutputPin, connectInputPin, inputPin); } } movingConnection_.reset(); update(); } //---------------------------------------------------------- // Отпускание захваченного узла //---------------------------------------------------------- else if (movingNode_ != nullptr) { const QPoint topLeft = pos - movingDragOffsetNode_; movingNode_->endMove(topLeft); movingNode_ = nullptr; movingDragOffsetNode_ = QPoint{}; } //---------------------------------------------------------- // Изменение размеров узла //---------------------------------------------------------- else if (resizebleNode_ != nullptr) { const QPoint topLeft = resizebleNode_->topLeft(); const int width = pos.x() - topLeft.x(); const int height = pos.y() - topLeft.y(); resizebleNode_->endResize(QSize{width, height}); resizebleNode_ = nullptr; } } //============================================================== // Функция вызывается при показе контекстного меню //============================================================== void FormDesigner::contextMenuEvent(QContextMenuEvent *event) { const QPoint globalPos = event->globalPos(); const QPoint pos = event->pos(); menuPos_ = pos; if (ShPtrBaseNode node = project()->findNodeByPt(menuPos_); node != nullptr) { project()->setSelectedNode(node); const QPointer<QMenu> menu = createNodeContextMenu(node); menu->popup(globalPos); } else { project()->setSelectedNode(nullptr); const QPointer<QMenu> menu = createContextMenu(); menu->popup(globalPos); } } //============================================================== // Задание соединений //============================================================== void FormDesigner::setConnections() { connect(project(), &Project::sigAddNode, this, [this]() { this->update(); }); connect(project(), &Project::sigRemoveNode, this, [this]() { this->update(); }); connect(project(), &Project::sigChangedNodeProp, this, [this]() { this->update(); }); connect(project(), &Project::sigChangeSelectedNode, this, [this]() { this->update(); }); connect(project(), &Project::sigChangedNodeState, this, [this]() { this->update(); }); connect(project(), &Project::sigChangeNodeConnection, this, [this]() { this->update(); }); connect(project(), &Project::sigNodeUpdate, this, [this]() { this->update(); }); } //============================================================== // Заливка фона //============================================================== void FormDesigner::fillBackgound(QPainter *painter, const QRect &clipRect, ColorThemes theme) const { Q_ASSERT(!isUnknown(theme)); painter->fillRect(clipRect, Colors::designerBack(theme)); } //============================================================== // Вывод сетки //============================================================== void FormDesigner::drawGrid(QPainter *painter, ColorThemes theme) const { Q_ASSERT(!isUnknown(theme)); if (isGridVisible_) { const QColor color = Colors::designerGrid(theme); painter->setPen(color); constexpr int gridSize = 20; for (int i = gridSize; i < width(); i += gridSize) { painter->drawLine(i, 0, i, height()); } for (int i = gridSize; i < height(); i += gridSize) { painter->drawLine(0, i, width(), i); } } } //============================================================== // Вывод узлов //============================================================== void FormDesigner::drawNodes(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); const QVector<ShPtrBaseNode> &nodes = project()->nodes(); for (const ShPtrBaseNode &node: nodes) { node->draw(painter, theme); } } //============================================================== // Вывод перемещаемого соединения //============================================================== void FormDesigner::drawMoveConnection(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); Q_ASSERT(!isUnknown(theme)); if (movingConnection_.isMove()) { painter->save(); painter->setRenderHint(QPainter::Antialiasing); QPen pen{Colors::nodeSelectBorder(theme), 2.0, Qt::CustomDashLine, Qt::RoundCap}; pen.setDashPattern({1, 3}); painter->setPen(pen); const QPoint &pt1 = movingConnection_.beginPt; const QPoint &pt2 = movingConnection_.endPt; painter->drawLine(pt1, pt2); painter->restore(); } } //============================================================== // Рисование соединений пинов //============================================================== void FormDesigner::drawPinConnectedLines(QPainter *painter, ColorThemes theme) const { Q_ASSERT(painter != nullptr); const QVector<ShPtrBaseNode> &nodes = project()->nodes(); for (const ShPtrBaseNode &node: nodes) { const QVector<ShPtrOutputPin> outPins = node->outputPins(); for (const ShPtrOutputPin &outPin: outPins) { const QVector<ShPtrInputPin> inputPins = outPin->inputPins(); for (const ShPtrInputPin &inputPin: inputPins) { const QPoint pt1 = outPin->rect().center(); const QPoint pt2 = inputPin->rect().center(); const QColor color = Colors::nodeBorder(theme); drawLineWithArraw(painter, color, pt1, pt2); } } } } //============================================================== // Вывод линии со стрелкой //============================================================== void FormDesigner::drawLineWithArraw(QPainter *painter, const QColor &color, const QPoint &pt1, const QPoint &pt2) const { Q_ASSERT(painter != nullptr); painter->save(); // Рисование линии painter->setRenderHint(QPainter::Antialiasing); painter->setPen({color, 2}); painter->drawLine(pt1, pt2); // Рисование стрелки const QPointF vector = pt2 - pt1; const double halfLen = sqrt(vector.x() * vector.x() + vector.y() * vector.y()) / 2; const double rad = calcAngle(pt1, pt2); const QPointF arrowPt1 = pt1 + QPointF{(halfLen + 5) * cos(rad), (halfLen + 5) * sin(rad)}; const double rad1_ = rad + qDegreesToRadians(150.0); const QPointF arrowPt2{arrowPt1.x() + cos(rad1_) * 8, arrowPt1.y() + sin(rad1_) * 8}; const double rad2_ = rad - qDegreesToRadians(150.0); const QPointF arrowPt3{arrowPt1.x() + cos(rad2_) * 8, arrowPt1.y() + sin(rad2_) * 8}; const QPolygonF polygon = QPolygonF{} << arrowPt2 << arrowPt1 << arrowPt3; painter->setPen(color); painter->setBrush(color); painter->drawPolygon(polygon); painter->restore(); } //============================================================== // Вывод перетаскиваемого узла //============================================================== void FormDesigner::drawDragNode(QPainter *painter) const { Q_ASSERT(painter != nullptr); if (isDragNode_) { const QPixmap image{":/res_images/images/drag_node_light.png"}; Q_ASSERT(!image.isNull()); painter->drawPixmap(dragNodePos_ + QPoint{10, 10}, image); } } //============================================================== // Задание размера символа //============================================================== void FormDesigner::setCharSize(QPainter *painter) { Q_ASSERT(painter != nullptr); const QSize charSize = ::strSize(*painter, "0"); BaseNode::setCharSize(charSize); } //============================================================== // Функция вызывается при выборе пункта контекстного меню // "Change file path" для узла InFileNode //============================================================== void FormDesigner::changeFilePath(ShPtrInputFileNode node) const { Q_ASSERT(node != nullptr); const QString caption = tr("Open File"); const QString path = QFileDialog::getOpenFileName(nullptr, caption); if (!path.isEmpty()) { node->setFilePath(path); } } //============================================================== // Создание контекстного меню //============================================================== QMenu* FormDesigner::createContextMenu() const { auto menu = new QMenu{}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QMenu *const menuAddNode = menu->addMenu(tr("Add node")); #ifdef Q_OS_WASM menuAddNode->setFont(font()); #endif // Q_OS_WASM menuAddNode->addMenu(createStandardNodesContextMenu()); menuAddNode->addMenu(createVisualizationNodesContextMenu()); menuAddNode->addMenu(createScriptNodesContextMenu()); menuAddNode->addMenu(createCommunicationNodesContextMenu()); menuAddNode->addMenu(createOtherNodesContextMenu()); QAction *const actPaste = menu->addAction(tr("Paste")); actPaste->setIcon(Icons::paste(theme)); actPaste->setShortcut(QString{"Ctrl+V"}); actPaste->setEnabled(false); return menu; } //============================================================== // Создание контекстного меню узлов категории "Standart" //============================================================== QMenu* FormDesigner::createStandardNodesContextMenu() const { const auto menu = new QMenu{tr("Standard")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actGenerate = menu->addAction(Icons::standardNode(theme), "Generate"); connect(actGenerate, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actInFile = menu->addAction(Icons::standardNode(theme), "InFile"); connect(actInFile, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actTake = menu->addAction(Icons::standardNode(theme), "Take"); connect(actTake, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actSkip = menu->addAction(Icons::standardNode(theme), "Skip"); connect(actSkip, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actReverse = menu->addAction(Icons::standardNode(theme), "Reverse"); connect(actReverse, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actMerge = menu->addAction(Icons::standardNode(theme), "Merge"); connect(actMerge, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actOutFile = menu->addAction(Icons::standardNode(theme), "OutFile"); connect(actOutFile, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actPaintOp = menu->addAction(Icons::standardNode(theme), "PaintOp"); actPaintOp->setEnabled(false); return menu; } //============================================================== // Создание контекстного меню узлов категории "Visualization" //============================================================== QMenu* FormDesigner::createVisualizationNodesContextMenu() const { const auto menu = new QMenu{tr("Visualization")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actSize = menu->addAction(Icons::standardNode(theme), "Size"); connect(actSize, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actDump = menu->addAction(Icons::standardNode(theme), "Dump"); connect(actDump, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actStruct = menu->addAction(Icons::standardNode(theme), "Struct"); connect(actStruct, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); QAction *const actGraph = menu->addAction(Icons::standardNode(theme), "Graph"); actGraph->setEnabled(false); QAction *const actPaint = menu->addAction(Icons::standardNode(theme), "Paint"); connect(actPaint, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); return menu; } //============================================================== // Создание контекстного меню узлов категории "Script" //============================================================== QMenu* FormDesigner::createScriptNodesContextMenu() const { const auto menu = new QMenu{tr("Script")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actSIn = menu->addAction(Icons::standardNode(theme), "SIn"); actSIn->setEnabled(false); QAction *const actSChange = menu->addAction(Icons::standardNode(theme), "SChange"); actSChange->setEnabled(false); QAction *const actSMerge = menu->addAction(Icons::standardNode(theme), "SMerge"); actSMerge->setEnabled(false); QAction *const actSOut = menu->addAction(Icons::standardNode(theme), "SOut"); actSOut->setEnabled(false); return menu; } //============================================================== // Создание контекстного меню узлов категории "Communication" //============================================================== QMenu* FormDesigner::createCommunicationNodesContextMenu() const { const auto menu = new QMenu{tr("Communication")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actTcpServer = menu->addAction(Icons::communicationNode(theme), "TcpServer"); actTcpServer->setEnabled(false); QAction *const actTcpClient = menu->addAction(Icons::communicationNode(theme), "TcpClient"); actTcpClient->setEnabled(false); QAction *const actUdpServer = menu->addAction(Icons::communicationNode(theme), "UdpServer"); actUdpServer->setEnabled(false); QAction *const actUdpClient = menu->addAction(Icons::communicationNode(theme), "UdpClient"); actUdpClient->setEnabled(false); QAction *const actComReader = menu->addAction(Icons::communicationNode(theme), "ComReader"); #ifndef Q_OS_WASM connect(actComReader, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); #else actComReader->setEnabled(false); #endif // Q_OS_WASM QAction *const actComWriter = menu->addAction(Icons::communicationNode(theme), "ComWriter"); #ifndef Q_OS_WASM connect(actComWriter, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); #else actComWriter->setEnabled(false); #endif // Q_OS_WASM return menu; } //============================================================== // Создание контекстного меню узлов категории "Other" //============================================================== QMenu* FormDesigner::createOtherNodesContextMenu() const { const auto menu = new QMenu{tr("Other")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actBlock = menu->addAction(Icons::standardNode(theme), "Block"); actBlock->setEnabled(false); QAction *const actCache = menu->addAction(Icons::standardNode(theme), "Cache"); actCache->setEnabled(false); QAction *const actNon = menu->addAction(Icons::standardNode(theme), "Non"); actNon->setEnabled(false); QAction *const actArea = menu->addAction(Icons::standardNode(theme), "Area"); connect(actArea, &QAction::triggered, this, &FormDesigner::slotAddNodeFromContextMenu); return menu; } //============================================================== // Создание меню для преобразования узлов категории "Standard" //============================================================== QMenu* FormDesigner::createMorphStandardNodeContextMenu() const { const auto menu = new QMenu{tr("Standard")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actGenerate = menu->addAction(Icons::standardNode(theme), "Generate"); actGenerate->setEnabled(false); QAction *const actInFile = menu->addAction(Icons::standardNode(theme), "InFile"); actInFile->setEnabled(false); QAction *const actTake = menu->addAction(Icons::standardNode(theme), "Take"); actTake->setEnabled(false); QAction *const actSkip = menu->addAction(Icons::standardNode(theme), "Skip"); actSkip->setEnabled(false); QAction *const actReverse = menu->addAction(Icons::standardNode(theme), "Reverse"); actReverse->setEnabled(false); QAction *const actMerge = menu->addAction(Icons::standardNode(theme), "Merge"); actMerge->setEnabled(false); QAction *const actOutFile = menu->addAction(Icons::standardNode(theme), "OutFile"); actOutFile->setEnabled(false); QAction *const actPaintOp = menu->addAction(Icons::standardNode(theme), "PaintOp"); actPaintOp->setEnabled(false); return menu; } //============================================================== // Создание меню для преобразования узлов категории "Visualization" //============================================================== QMenu* FormDesigner::createMorphVisualizationNodeContextMenu() const { const auto menu = new QMenu{tr("Visualization")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actSize = menu->addAction(Icons::standardNode(theme), "Size"); actSize->setEnabled(false); QAction *const actDump = menu->addAction(Icons::standardNode(theme), "Dump"); actDump->setEnabled(false); QAction *const actStruct = menu->addAction(Icons::standardNode(theme), "Struct"); actStruct->setEnabled(false); QAction *const actGraph = menu->addAction(Icons::standardNode(theme), "Graph"); actGraph->setEnabled(false); QAction *const actPaint = menu->addAction(Icons::standardNode(theme), "Paint"); actPaint->setEnabled(false); return menu; } //============================================================== // Создание меню для преобразования узлов категории "Script" //============================================================== QMenu* FormDesigner::createMorphScriptNodeContextMenu() const { const auto menu = new QMenu{tr("Script")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actSIn = menu->addAction(Icons::standardNode(theme), "SIn"); actSIn->setEnabled(false); QAction *const actSChange = menu->addAction(Icons::standardNode(theme), "SChange"); actSChange->setEnabled(false); QAction *const actSMerge = menu->addAction(Icons::standardNode(theme), "SMerge"); actSMerge->setEnabled(false); QAction *const actSOut = menu->addAction(Icons::standardNode(theme), "SOut"); actSOut->setEnabled(false); return menu; } //============================================================== // Создание меню для преобразования узлов категории "Communication" //============================================================== QMenu* FormDesigner::createMorphCommunicationNodeContextMenu() const { const auto menu = new QMenu{tr("Communication")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actTcpServer = menu->addAction(Icons::communicationNode(theme), "TcpServer"); actTcpServer->setEnabled(false); QAction *const actTcpClient = menu->addAction(Icons::communicationNode(theme), "TcpClient"); actTcpClient->setEnabled(false); QAction *const actUdpServer = menu->addAction(Icons::communicationNode(theme), "UdpServer"); actUdpServer->setEnabled(false); QAction *const actUdpClient = menu->addAction(Icons::communicationNode(theme), "UdpClient"); actUdpClient->setEnabled(false); QAction *const actComReader = menu->addAction(Icons::communicationNode(theme), "ComReader"); actComReader->setEnabled(false); QAction *const actComWriter = menu->addAction(Icons::communicationNode(theme), "ComWriter"); actComWriter->setEnabled(false); return menu; } //============================================================== // Создание меню для преобразования узлов категории "Other" //============================================================== QMenu* FormDesigner::createMorphOtherNodeContextMenu() const { const auto menu = new QMenu{tr("Other")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM const ColorThemes theme = globalSettings()->colorTheme(); QAction *const actBlock = menu->addAction(Icons::standardNode(theme), "Block"); actBlock->setEnabled(false); QAction *const actCache = menu->addAction(Icons::standardNode(theme), "Cache"); actCache->setEnabled(false); QAction *const actNon = menu->addAction(Icons::standardNode(theme), "Non"); actNon->setEnabled(false); QAction *const actArea = menu->addAction(Icons::standardNode(theme), "Area"); actArea->setEnabled(false); return menu; } //============================================================== // Создание меню для преобразования узлов //============================================================== QMenu* FormDesigner::createMorphNodeContextMenu() const { const auto menu = new QMenu{tr("Morph to")}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM menu->addMenu(createMorphStandardNodeContextMenu()); menu->addMenu(createMorphVisualizationNodeContextMenu()); menu->addMenu(createMorphCommunicationNodeContextMenu()); menu->addMenu(createMorphScriptNodeContextMenu()); menu->addMenu(createMorphOtherNodeContextMenu()); return menu; } //============================================================== // Создание контекстного меню узлов "Standart" //============================================================== QMenu* FormDesigner::createNodeContextMenu(ShPtrBaseNode node) const { Q_ASSERT(node != nullptr); const ColorThemes theme = globalSettings()->colorTheme(); auto menu = new QMenu{}; #ifdef Q_OS_WASM menu->setFont(font()); #endif // Q_OS_WASM menu->addMenu(createMorphNodeContextMenu()); menu->addSeparator(); QAction *const actCut = menu->addAction(Icons::cut(theme), tr("Cut")); actCut->setShortcut(QString{"Ctrl+X"}); actCut->setEnabled(false); QAction *const actCopy = menu->addAction(Icons::copy(theme), tr("Copy")); actCopy->setShortcut(QString{"Ctrl+C"}); actCopy->setEnabled(false); QAction *const actPaste = menu->addAction(Icons::paste(theme), tr("Paste")); actPaste->setShortcut(QString{"Ctrl+V"}); actPaste->setEnabled(false); menu->addSeparator(); addTypeNodeMenuItems(menu, node); QAction *const actRemove = menu->addAction(Icons::delete_(theme), tr("Remove")); actRemove->setShortcut(QString{"Del"}); connect(actRemove, &QAction::triggered, this, &FormDesigner::slotRemoveNodeFromContextMenu); return menu; } //============================================================== // Добавление пунктов в контекстное меню для определённого типа узла //============================================================== void FormDesigner::addTypeNodeMenuItems(QMenu *menu, ShPtrBaseNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); switch (node->type()) { case NodeTypes::Generate: { const ShPtrGenerateNode generateNode = qSharedPointerCast<GenerateNode>(node); addGenerateNodeMenuItems(menu, generateNode); break; } case NodeTypes::InFile: { const ShPtrInputFileNode inFileNode = qSharedPointerCast<InputFileNode>(node); addInFileNodeMenuItems(menu, inFileNode); break; } case NodeTypes::OutFile: { const ShPtrOutputFileNode outFileNode = qSharedPointerCast<OutputFileNode>(node); addOutFileNodeMenuItems(menu, outFileNode); break; } case NodeTypes::Take: { const ShPtrTakeNode takeNode = qSharedPointerCast<TakeNode>(node); addTakeNodeMenuItems(menu, takeNode); break; } case NodeTypes::Skip: { const ShPtrSkipNode skipNode = qSharedPointerCast<SkipNode>(node); addSkipNodeMenuItems(menu, skipNode); break; } case NodeTypes::Reverse: { const ShPtrReverseNode reverseNode = qSharedPointerCast<ReverseNode>(node); addReverseNodeMenuItems(menu, reverseNode); break; } case NodeTypes::Size: { const ShPtrSizeNode sizeNode = qSharedPointerCast<SizeNode>(node); addSizeNodeMenuItems(menu, sizeNode); break; } case NodeTypes::Dump: { const ShPtrDumpNode dumpNode = qSharedPointerCast<DumpNode>(node); addDumpNodeMenuItems(menu, dumpNode); break; } case NodeTypes::Struct: { const ShPtrStructNode structNode = qSharedPointerCast<StructNode>(node); addStructNodeMenuItems(menu, structNode); break; } case NodeTypes::Graph: { const ShPtrGraphNode graphNode = qSharedPointerCast<GraphNode>(node); addGraphNodeMenuItems(menu, graphNode); break; } case NodeTypes::Paint: { const ShPtrPaintNode paintNode = qSharedPointerCast<PaintNode>(node); addPaintNodeMenuItems(menu, paintNode); break; } #ifndef Q_OS_WASM case NodeTypes::ComReader: { const ShPtrComReaderNode comReaderNode = qSharedPointerCast<ComReaderNode>(node); addComReaderNodeMenuItems(menu, comReaderNode); break; } case NodeTypes::ComWriter: { const ShPtrComWriterNode comWriterNode = qSharedPointerCast<ComWriterNode>(node); addComWriterNodeMenuItems(menu, comWriterNode); break; } #endif // Q_OS_WASM case NodeTypes::Area: { const ShPtrAreaNode areaNode = qSharedPointerCast<AreaNode>(node); addAreaNodeMenuItems(menu, areaNode); break; } default: { break; } } } //============================================================== // Добавление пунктов в контекстное меню для узла Generate //============================================================== void FormDesigner::addGenerateNodeMenuItems(QMenu *menu, ShPtrGenerateNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); QMenu *const generateTypeMenu = menu->addMenu(tr("Generate type")); #ifdef Q_OS_WASM generateTypeMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actGenerateTypeStandard = generateTypeMenu->addAction(tr("Standard"), generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Standard); }); actGenerateTypeStandard->setCheckable(true); actGenerateTypeStandard->setChecked(isStandard(node->generateType())); QAction *const actGenerateTypeRandom = generateTypeMenu->addAction(tr("Random"), generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Random); }); actGenerateTypeRandom->setCheckable(true); actGenerateTypeRandom->setChecked(isRandom(node->generateType())); QAction *const actGenerateTypeInt8 = generateTypeMenu->addAction("Int8", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Int8); }); actGenerateTypeInt8->setCheckable(true); actGenerateTypeInt8->setChecked(isInt8(node->generateType())); QAction *const actGenerateTypeUInt8 = generateTypeMenu->addAction("UInt8", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::UInt8); }); actGenerateTypeUInt8->setCheckable(true); actGenerateTypeUInt8->setChecked(isUInt8(node->generateType())); QAction *const actGenerateTypeInt16 = generateTypeMenu->addAction("Int16", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Int16); }); actGenerateTypeInt16->setCheckable(true); actGenerateTypeInt16->setChecked(isInt16(node->generateType())); QAction *const actGenerateTypeUInt16 = generateTypeMenu->addAction("UInt16", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::UInt16); }); actGenerateTypeUInt16->setCheckable(true); actGenerateTypeUInt16->setChecked(isUInt16(node->generateType())); QAction *const actGenerateTypeInt32 = generateTypeMenu->addAction("Int32", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Int32); }); actGenerateTypeInt32->setCheckable(true); actGenerateTypeInt32->setChecked(isInt32(node->generateType())); QAction *const actGenerateTypeUInt32 = generateTypeMenu->addAction("UInt32", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::UInt32); }); actGenerateTypeUInt32->setCheckable(true); actGenerateTypeUInt32->setChecked(isUInt32(node->generateType())); QAction *const actGenerateTypeInt64 = generateTypeMenu->addAction("Int64", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Int64); }); actGenerateTypeInt64->setCheckable(true); actGenerateTypeInt64->setChecked(isInt64(node->generateType())); QAction *const actGenerateTypeUInt64 = generateTypeMenu->addAction("UInt64", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::UInt64); }); actGenerateTypeUInt64->setCheckable(true); actGenerateTypeUInt64->setChecked(isUInt64(node->generateType())); QAction *const actGenerateTypeFloat = generateTypeMenu->addAction("Float", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Float); }); actGenerateTypeFloat->setCheckable(true); actGenerateTypeFloat->setChecked(isFloat(node->generateType())); QAction *const actGenerateTypeDouble = generateTypeMenu->addAction("Double", generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Double); }); actGenerateTypeDouble->setCheckable(true); actGenerateTypeDouble->setChecked(isDouble(node->generateType())); QAction *const actGenerateTypeString = generateTypeMenu->addAction(tr("String"), generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::String); }); actGenerateTypeString->setCheckable(true); actGenerateTypeString->setChecked(isString(node->generateType())); QAction *const actGenerateTypeColor = generateTypeMenu->addAction(tr("Color"), generateTypeMenu, [node]() { node->setGenerateType(GenerateTypes::Color); }); actGenerateTypeColor->setCheckable(true); actGenerateTypeColor->setChecked(isColor(node->generateType())); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла InFile //============================================================== void FormDesigner::addInFileNodeMenuItems(QMenu *menu, ShPtrInputFileNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Изменить путь к файлу //---------------------------------------------------------- QAction *const actChangeFilePath = menu->addAction(tr("Change file path..."), menu, [this, node]() { this->changeFilePath(node); } ); Q_UNUSED(actChangeFilePath); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла OutFile //============================================================== void FormDesigner::addOutFileNodeMenuItems(QMenu *menu, ShPtrOutputFileNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); } //============================================================== // Добавление пунктов в контекстное меню для узла Take //============================================================== void FormDesigner::addTakeNodeMenuItems(QMenu *menu, ShPtrTakeNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Признак пропуска //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Skip //============================================================== void FormDesigner::addSkipNodeMenuItems(QMenu *menu, ShPtrSkipNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Признак пропуска //---------------------------------------------------------- QAction *const actMintColor = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actMintColor->setCheckable(true); actMintColor->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Reverse //============================================================== void FormDesigner::addReverseNodeMenuItems(QMenu *menu, ShPtrReverseNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Признак пропуска //---------------------------------------------------------- QAction *const actMintColor = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actMintColor->setCheckable(true); actMintColor->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Size //============================================================== void FormDesigner::addSizeNodeMenuItems(QMenu *menu, ShPtrSizeNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Размерность //---------------------------------------------------------- QMenu *const unitMenu = menu->addMenu("Unit"); #ifdef Q_OS_WASM unitMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actByte = unitMenu->addAction(tr("Byte"), unitMenu, [node]() { node->setUnit(SizeUnits::Byte); }); actByte->setCheckable(true); actByte->setChecked(isByte(node->unit())); QAction *const actKilobyte = unitMenu->addAction(tr("Kilobyte"), unitMenu, [node]() { node->setUnit(SizeUnits::Kilobyte); }); actKilobyte->setCheckable(true); actKilobyte->setChecked(isKilobyte(node->unit())); QAction *const actMegabyte = unitMenu->addAction(tr("Megabyte"), unitMenu, [node]() { node->setUnit(SizeUnits::Megabyte); }); actMegabyte->setCheckable(true); actMegabyte->setChecked(isMegabyte(node->unit())); //---------------------------------------------------------- // Признак пропуска //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Dump //============================================================== void FormDesigner::addDumpNodeMenuItems(QMenu *menu, ShPtrDumpNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Режимы отображения //---------------------------------------------------------- QMenu *const modeMenu = menu->addMenu("Mode"); #ifdef Q_OS_WASM modeMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actBinaryMode = modeMenu->addAction(tr("Binary"), modeMenu, [node]() { node->setDumpMode(DumpModes::Binary); }); actBinaryMode->setCheckable(true); actBinaryMode->setChecked(isBinary(node->dumpMode())); QAction *const actTextMode = modeMenu->addAction(tr("Text"), modeMenu, [node]() { node->setDumpMode(DumpModes::Text); }); actTextMode->setCheckable(true); actTextMode->setChecked(isText(node->dumpMode())); //---------------------------------------------------------- // Ширина в байтах //---------------------------------------------------------- QMenu *const byteWidthMenu = menu->addMenu("Width (B)"); #ifdef Q_OS_WASM byteWidthMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actWidthByte8 = byteWidthMenu->addAction("8", byteWidthMenu, [node]() { node->setByteWidth(ByteWidths::Width8); }); actWidthByte8->setCheckable(true); actWidthByte8->setChecked(isWidth8(node->byteWidth())); QAction *const actWidthByte16 = byteWidthMenu->addAction("16", byteWidthMenu, [node]() { node->setByteWidth(ByteWidths::Width16); }); actWidthByte16->setCheckable(true); actWidthByte16->setChecked(isWidth16(node->byteWidth())); //---------------------------------------------------------- // Признак пропуска //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Paint //============================================================== void FormDesigner::addPaintNodeMenuItems(QMenu *menu, ShPtrPaintNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Признака масштабирования при выводе в узел //---------------------------------------------------------- QMenu *const scaleInNodeMenu = menu->addMenu(tr("Scale in node")); #ifdef Q_OS_WASM scaleInNodeMenu->setFont(font()); #endif // Q_OS_WASM for (int i = 1; i <= 10; ++i) { const int scale = i * 10; const QString strScale = QString{"%1%"}.arg(scale); QAction *const actScaleInNode = scaleInNodeMenu->addAction(strScale, scaleInNodeMenu, [node, scale]() { node->setScaleInNode(scale); }); actScaleInNode->setCheckable(true); actScaleInNode->setChecked(node->scaleInNode() == scale); } //---------------------------------------------------------- // Признак вывода в узел //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Struct //============================================================== void FormDesigner::addStructNodeMenuItems(QMenu *menu, ShPtrStructNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Признак вывода в узел //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла Graph //============================================================== void FormDesigner::addGraphNodeMenuItems(QMenu *menu, ShPtrGraphNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Тип данных точек //---------------------------------------------------------- QMenu *const menuDataType = menu->addMenu(tr("Data type")); #ifdef Q_OS_WASM menuDataType->setFont(font()); #endif // Q_OS_WASM QAction *const actDataType_Bool = menuDataType->addAction("Bool"); Q_UNUSED(actDataType_Bool) QAction *const actDataType_Int8 = menuDataType->addAction("Int8"); Q_UNUSED(actDataType_Int8) QAction *const actDataType_UInt8 = menuDataType->addAction("UInt8"); Q_UNUSED(actDataType_UInt8) QAction *const actDataType_Int16 = menuDataType->addAction("Int16"); Q_UNUSED(actDataType_Int16) QAction *const actDataType_UInt16 = menuDataType->addAction("UInt16"); Q_UNUSED(actDataType_UInt16) QAction *const actDataType_Int32 = menuDataType->addAction("Int32"); Q_UNUSED(actDataType_Int32) QAction *const actDataType_UInt32 = menuDataType->addAction("UInt32"); Q_UNUSED(actDataType_UInt32) QAction *const actDataType_Int64 = menuDataType->addAction("Int64"); Q_UNUSED(actDataType_Int64) QAction *const actDataType_Float = menuDataType->addAction("Float"); Q_UNUSED(actDataType_Float) QAction *const actDataType_Double = menuDataType->addAction("Double"); Q_UNUSED(actDataType_Double) //---------------------------------------------------------- // Расстояние между точками в пикселях //---------------------------------------------------------- QMenu *const menuDistance = menu->addMenu("Distance between points (px)"); #ifdef Q_OS_WASM menuDistance->setFont(font()); #endif // Q_OS_WASM QAction *const actDistance_1 = menuDistance->addAction("1"); Q_UNUSED(actDistance_1) QAction *const actDistance_2 = menuDistance->addAction("2"); Q_UNUSED(actDistance_2) QAction *const actDistance_3 = menuDistance->addAction("3"); Q_UNUSED(actDistance_3) QAction *const actDistance_4 = menuDistance->addAction("4"); Q_UNUSED(actDistance_4) QAction *const actDistance_5 = menuDistance->addAction("5"); Q_UNUSED(actDistance_5) //---------------------------------------------------------- // Признак вывода в узел //---------------------------------------------------------- QAction *const actBypass = menu->addAction(tr("Bypass"), menu, [node]() { node->setBypass(!node->isBypass()); }); actBypass->setCheckable(true); actBypass->setChecked(node->isBypass()); menu->addSeparator(); } #ifndef Q_OS_WASM //============================================================== // Добавление пунктов в контекстное меню для узла ComReader //============================================================== void FormDesigner::addComReaderNodeMenuItems(QMenu *menu, ShPtrComReaderNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Имя порта //---------------------------------------------------------- QMenu *const menuPortName = menu->addMenu(tr("Port name")); const QStringList comPortNames = comPortManager()->portNames(); for (const QString &name: comPortNames) { QAction *const actPortName = menuPortName->addAction(name, menuPortName, [node, name]() { node->setPortName(name); }); actPortName->setCheckable(true); actPortName->setChecked(node->portName() == name); } //---------------------------------------------------------- // Частота порта //---------------------------------------------------------- QMenu *const menuBaudRate = menu->addMenu(tr("Baud rate")); QAction *const actBaudRate_1200 = menuBaudRate->addAction("1200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_1200); }); actBaudRate_1200->setCheckable(true); actBaudRate_1200->setChecked(isBaud_1200(node->baudRate())); QAction *const actBaudRate_2400 = menuBaudRate->addAction("2400", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_2400); }); actBaudRate_2400->setCheckable(true); actBaudRate_2400->setChecked(isBaud_2400(node->baudRate())); QAction *const actBaudRate_4800 = menuBaudRate->addAction("4800", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_4800); }); actBaudRate_4800->setCheckable(true); actBaudRate_4800->setChecked(isBaud_4800(node->baudRate())); QAction *const actBaudRate_9600 = menuBaudRate->addAction("9600", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_9600); }); actBaudRate_9600->setCheckable(true); actBaudRate_9600->setChecked(isBaud_9600(node->baudRate())); QAction *const actBaudRate_19200 = menuBaudRate->addAction("19200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_19200); }); actBaudRate_19200->setCheckable(true); actBaudRate_19200->setChecked(isBaud_19200(node->baudRate())); QAction *const actBaudRate_38400 = menuBaudRate->addAction("38400", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_38400); }); actBaudRate_38400->setCheckable(true); actBaudRate_38400->setChecked(isBaud_38400(node->baudRate())); QAction *const actBaudRate_57600 = menuBaudRate->addAction("57600", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_57600); }); actBaudRate_57600->setCheckable(true); actBaudRate_57600->setChecked(isBaud_57600(node->baudRate())); QAction *const actBaudRate_115200 = menuBaudRate->addAction("115200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_115200); }); actBaudRate_115200->setCheckable(true); actBaudRate_115200->setChecked(isBaud_115200(node->baudRate())); //---------------------------------------------------------- // Формат пакета //---------------------------------------------------------- QMenu *const menuPacketMode = menu->addMenu(tr("Packet mode")); QAction *const actPacketMode_Raw = menuPacketMode->addAction(tr("Raw")); actPacketMode_Raw->setCheckable(true); actPacketMode_Raw->setChecked(true); //---------------------------------------------------------- // Открытие/закрытие порта //---------------------------------------------------------- const QString openCloseText = node->isOpenPort() ? tr("Close") : tr("Open"); QAction *const actPortOpenClose = menu->addAction(openCloseText, menu, [node]() { node->changeState(); }); Q_UNUSED(actPortOpenClose) menu->addSeparator(); } //============================================================== // Добавление пунктов в контекстное меню для узла ComWriter //============================================================== void FormDesigner::addComWriterNodeMenuItems(QMenu *menu, ShPtrComWriterNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Имя порта //---------------------------------------------------------- QMenu *const menuPortName = menu->addMenu(tr("Port name")); const QStringList comPortNames = comPortManager()->portNames(); for (const QString &name: comPortNames) { QAction *const actPortName = menuPortName->addAction(name, menuPortName, [node, name]() { node->setPortName(name); }); actPortName->setCheckable(true); actPortName->setChecked(node->portName() == name); } //---------------------------------------------------------- // Частота порта //---------------------------------------------------------- QMenu *const menuBaudRate = menu->addMenu(tr("Baud rate")); QAction *const actBaudRate_1200 = menuBaudRate->addAction("1200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_1200); }); actBaudRate_1200->setCheckable(true); actBaudRate_1200->setChecked(isBaud_1200(node->baudRate())); QAction *const actBaudRate_2400 = menuBaudRate->addAction("2400", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_2400); }); actBaudRate_2400->setCheckable(true); actBaudRate_2400->setChecked(isBaud_2400(node->baudRate())); QAction *const actBaudRate_4800 = menuBaudRate->addAction("4800", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_4800); }); actBaudRate_4800->setCheckable(true); actBaudRate_4800->setChecked(isBaud_4800(node->baudRate())); QAction *const actBaudRate_9600 = menuBaudRate->addAction("9600", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_9600); }); actBaudRate_9600->setCheckable(true); actBaudRate_9600->setChecked(isBaud_9600(node->baudRate())); QAction *const actBaudRate_19200 = menuBaudRate->addAction("19200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_19200); }); actBaudRate_19200->setCheckable(true); actBaudRate_19200->setChecked(isBaud_19200(node->baudRate())); QAction *const actBaudRate_38400 = menuBaudRate->addAction("38400", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_38400); }); actBaudRate_38400->setCheckable(true); actBaudRate_38400->setChecked(isBaud_38400(node->baudRate())); QAction *const actBaudRate_57600 = menuBaudRate->addAction("57600", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_57600); }); actBaudRate_57600->setCheckable(true); actBaudRate_57600->setChecked(isBaud_57600(node->baudRate())); QAction *const actBaudRate_115200 = menuBaudRate->addAction("115200", menuBaudRate, [node]() { node->setBaudRate(ComPortBaudRates::Baud_115200); }); actBaudRate_115200->setCheckable(true); actBaudRate_115200->setChecked(isBaud_115200(node->baudRate())); //---------------------------------------------------------- // Формат пакета //---------------------------------------------------------- QMenu *const menuPacketMode = menu->addMenu(tr("Packet mode")); QAction *const actPacketMode_Raw = menuPacketMode->addAction(tr("Raw")); actPacketMode_Raw->setCheckable(true); actPacketMode_Raw->setChecked(true); //---------------------------------------------------------- // Открытие/закрытие порта //---------------------------------------------------------- const QString openCloseText = node->isOpenPort() ? tr("Close") : tr("Open"); QAction *const actPortOpenClose = menu->addAction(openCloseText, menu, [node]() { node->changeState(); }); Q_UNUSED(actPortOpenClose) menu->addSeparator(); } #endif // Q_OS_WASM //============================================================== // Добавление пунктов в контекстное меню для узла Area //============================================================== void FormDesigner::addAreaNodeMenuItems(QMenu *menu, ShPtrAreaNode node) const { Q_ASSERT(menu != nullptr); Q_ASSERT(node != nullptr); //---------------------------------------------------------- // Цвет //---------------------------------------------------------- QMenu *const colorMenu = menu->addMenu("Color"); #ifdef Q_OS_WASM colorMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actMintColor = colorMenu->addAction(tr("Mint"), colorMenu, [node]() { node->setColor(AreaNodeColors::Mint); }); actMintColor->setCheckable(true); actMintColor->setChecked(isMint(node->color())); QAction *const actTechBlueColor = colorMenu->addAction(tr("TechBlue"), colorMenu, [node]() { node->setColor(AreaNodeColors::TechBlue); }); actTechBlueColor->setCheckable(true); actTechBlueColor->setChecked(isTechBlue(node->color())); QAction *const actLavenderColor = colorMenu->addAction(tr("Lavender"), colorMenu, [node]() { node->setColor(AreaNodeColors::Lavender); }); actLavenderColor->setCheckable(true); actLavenderColor->setChecked(isLavender(node->color())); QAction *const actPeachColor = colorMenu->addAction(tr("Peach"), colorMenu, [node]() { node->setColor(AreaNodeColors::Peach); }); actPeachColor->setCheckable(true); actPeachColor->setChecked(isPeach(node->color())); QAction *const actGrayColor = colorMenu->addAction(tr("Gray"), colorMenu, [node]() { node->setColor(AreaNodeColors::Gray); }); actGrayColor->setCheckable(true); actGrayColor->setChecked(isGray(node->color())); QAction *const actSolarColor = colorMenu->addAction(tr("Solar"), colorMenu, [node]() { node->setColor(AreaNodeColors::Solar); }); actSolarColor->setCheckable(true); actSolarColor->setChecked(isSolar(node->color())); //---------------------------------------------------------- // Выравнивание текста //---------------------------------------------------------- QMenu *const textAlignMenu = menu->addMenu(tr("Text align")); #ifdef Q_OS_WASM textAlignMenu->setFont(font()); #endif // Q_OS_WASM QAction *const actTextAlignTop = textAlignMenu->addAction(tr("Top"), textAlignMenu, [node]() { node->setTextAlign(AreaNodeTextAligns::Top); }); actTextAlignTop->setCheckable(true); actTextAlignTop->setChecked(isTop(node->textAlign())); QAction *const actTextAlignBottom = textAlignMenu->addAction(tr("Bottom"), textAlignMenu, [node]() { node->setTextAlign(AreaNodeTextAligns::Bottom); }); actTextAlignBottom->setCheckable(true); actTextAlignBottom->setChecked(isBottom(node->textAlign())); menu->addSeparator(); }