удалено: build/.qt/QtDeploySupport.cmake

удалено:       build/.qt/QtDeployTargets.cmake
	удалено:       build/CMakeCache.txt
	удалено:       build/CMakeFiles/4.1.2/CMakeCXXCompiler.cmake
	удалено:       build/CMakeFiles/4.1.2/CMakeDetermineCompilerABI_CXX.bin
	удалено:       build/CMakeFiles/4.1.2/CMakeSystem.cmake
	удалено:       build/CMakeFiles/4.1.2/CompilerIdCXX/CMakeCXXCompilerId.cpp
	удалено:       build/CMakeFiles/4.1.2/CompilerIdCXX/a.out
	удалено:       build/CMakeFiles/CMakeConfigureLog.yaml
	удалено:       build/CMakeFiles/CMakeDirectoryInformation.cmake
	удалено:       build/CMakeFiles/CMakeRuleHashes.txt
	удалено:       build/CMakeFiles/InstallScripts.json
	удалено:       build/CMakeFiles/Makefile.cmake
	удалено:       build/CMakeFiles/Makefile2
	удалено:       build/CMakeFiles/TargetDirectories.txt
	удалено:       build/CMakeFiles/cmake.check_cache
	удалено:       build/CMakeFiles/idef0_editor.dir/DependInfo.cmake
	удалено:       build/CMakeFiles/idef0_editor.dir/build.make
	удалено:       build/CMakeFiles/idef0_editor.dir/cmake_clean.cmake
	удалено:       build/CMakeFiles/idef0_editor.dir/compiler_depend.internal
	удалено:       build/CMakeFiles/idef0_editor.dir/compiler_depend.make
	удалено:       build/CMakeFiles/idef0_editor.dir/compiler_depend.ts
	удалено:       build/CMakeFiles/idef0_editor.dir/depend.make
	удалено:       build/CMakeFiles/idef0_editor.dir/flags.make
	удалено:       build/CMakeFiles/idef0_editor.dir/idef0_editor_autogen/mocs_compilation.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/idef0_editor_autogen/mocs_compilation.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/link.d
	удалено:       build/CMakeFiles/idef0_editor.dir/link.txt
	удалено:       build/CMakeFiles/idef0_editor.dir/progress.make
	удалено:       build/CMakeFiles/idef0_editor.dir/src/MainWindow.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/MainWindow.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/ArrowItem.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/ArrowItem.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/BlockItem.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/BlockItem.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/DiagramScene.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/DiagramScene.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/JunctionItem.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/items/JunctionItem.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor.dir/src/main.cpp.o
	удалено:       build/CMakeFiles/idef0_editor.dir/src/main.cpp.o.d
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/AutogenInfo.json
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/AutogenUsed.txt
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/DependInfo.cmake
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/ParseCache.txt
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/build.make
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/cmake_clean.cmake
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/compiler_depend.internal
удалено:       build/CMakeFiles/idef0_editor_autogen.dir/compiler_depend.make
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/compiler_depend.ts
	удалено:       build/CMakeFiles/idef0_editor_autogen.dir/progress.make
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/DependInfo.cmake
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/build.make
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/cmake_clean.cmake
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/compiler_depend.make
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/compiler_depend.ts
	удалено:       build/CMakeFiles/idef0_editor_autogen_timestamp_deps.dir/progress.make
	удалено:       build/CMakeFiles/progress.marks
	удалено:       build/Makefile
	удалено:       build/cmake_install.cmake
	удалено:       build/idef0_editor
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_BlockItem.cpp
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_BlockItem.cpp.d
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_DiagramScene.cpp
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_DiagramScene.cpp.d
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_JunctionItem.cpp
	удалено:       build/idef0_editor_autogen/DWIBBXP2LJ/moc_JunctionItem.cpp.d
	удалено:       build/idef0_editor_autogen/UVLADIE3JM/moc_MainWindow.cpp
	удалено:       build/idef0_editor_autogen/UVLADIE3JM/moc_MainWindow.cpp.d
	удалено:       build/idef0_editor_autogen/deps
	удалено:       build/idef0_editor_autogen/moc_predefs.h
	удалено:       build/idef0_editor_autogen/mocs_compilation.cpp
	удалено:       build/idef0_editor_autogen/timestamp
	удалено:       codex
	изменено:      src/items/ArrowItem.cpp
	изменено:      src/items/ArrowItem.h
	изменено:      src/items/BlockItem.h
	изменено:      src/items/DiagramScene.cpp
	изменено:      src/items/DiagramScene.h
This commit is contained in:
Gregory Bednov 2026-02-23 00:23:03 +03:00
commit abdbae5a11
79 changed files with 218 additions and 46399 deletions

View file

@ -66,6 +66,47 @@ void ArrowItem::setLabelOffset(const QPointF& off) {
updateLabelItem(m_lastPolyline.isEmpty() ? computePolyline() : m_lastPolyline);
}
bool ArrowItem::adjustEndpoint(Endpoint& ep, const QPointF& delta) {
if (ep.block) {
auto seg = ep.block->portSegment(ep.port);
QPointF local = ep.localPos.value_or(ep.block->portLocalPos(ep.port));
local += ep.block->mapFromScene(delta);
if (qFuzzyCompare(seg.first.x(), seg.second.x())) {
local.setX(seg.first.x());
local.setY(std::clamp(local.y(), seg.first.y(), seg.second.y()));
} else {
local.setY(seg.first.y());
local.setX(std::clamp(local.x(), seg.first.x(), seg.second.x()));
}
ep.localPos = local;
return true;
}
if (ep.scenePos) {
QPointF p = *ep.scenePos + delta;
if (scene()) {
const QRectF r = scene()->sceneRect();
// snap to nearest edge it was originally on
const qreal tol = 4.0;
if (std::abs(ep.scenePos->x() - r.left()) < tol) {
p.setX(r.left());
p.setY(std::clamp(p.y(), r.top(), r.bottom()));
} else if (std::abs(ep.scenePos->x() - r.right()) < tol) {
p.setX(r.right());
p.setY(std::clamp(p.y(), r.top(), r.bottom()));
} else if (std::abs(ep.scenePos->y() - r.top()) < tol) {
p.setY(r.top());
p.setX(std::clamp(p.x(), r.left(), r.right()));
} else if (std::abs(ep.scenePos->y() - r.bottom()) < tol) {
p.setY(r.bottom());
p.setX(std::clamp(p.x(), r.left(), r.right()));
}
}
ep.scenePos = p;
return true;
}
return false;
}
void ArrowItem::setFrom(const Endpoint& ep) {
if (m_from.block) m_from.block->removeArrow(this);
if (m_from.junction) m_from.junction->removeArrow(this);
@ -394,6 +435,13 @@ QVector<QPointF> ArrowItem::computePolyline() const {
: QPointF(0, ((a - b).y() >= 0 ? 1 : -1)),
QPointF(-1,0))
: portDirection(m_to, false, QPointF(-1,0), scene());
// ensure right border always behaves like an input (approach from left)
if (!m_hasTempEnd && m_to.scenePos && scene()) {
const qreal rightX = scene()->sceneRect().right();
if (almostEqual(m_to.scenePos->x(), rightX)) {
dirB = QPointF(-1, 0);
}
}
auto expandRect = [](const QRectF& r, qreal m) {
return QRectF(r.x()-m, r.y()-m, r.width()+2*m, r.height()+2*m);
@ -594,6 +642,22 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent* e) {
const QVector<QPointF> pts = computePolyline();
const QPointF pos = e->scenePos();
// Проверим, не жмем ли по началу/концу для сдвига точки соединения.
if (!pts.isEmpty()) {
if (QLineF(pos, pts.first()).length() <= tol) {
m_dragPart = DragPart::FromEnd;
m_lastDragScenePos = pos;
e->accept();
return;
}
if (QLineF(pos, pts.last()).length() <= tol) {
m_dragPart = DragPart::ToEnd;
m_lastDragScenePos = pos;
e->accept();
return;
}
}
m_dragPart = DragPart::None;
int closestIdx = -1;
qreal best = tol;
@ -637,6 +701,25 @@ void ArrowItem::mouseMoveEvent(QGraphicsSceneMouseEvent* e) {
return;
}
if (m_dragPart == DragPart::FromEnd) {
const QPointF delta = e->scenePos() - m_lastDragScenePos;
m_lastDragScenePos = e->scenePos();
if (adjustEndpoint(m_from, delta)) {
updatePath();
}
e->accept();
return;
}
if (m_dragPart == DragPart::ToEnd) {
const QPointF delta = e->scenePos() - m_lastDragScenePos;
m_lastDragScenePos = e->scenePos();
if (adjustEndpoint(m_to, delta)) {
updatePath();
}
e->accept();
return;
}
if (m_dragPart == DragPart::None) {
QGraphicsPathItem::mouseMoveEvent(e);
return;
@ -673,6 +756,15 @@ void ArrowItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* e) {
e->accept();
return;
}
if ((m_dragPart == DragPart::FromEnd || m_dragPart == DragPart::ToEnd) && e->button() == Qt::LeftButton) {
m_dragPart = DragPart::None;
unsetCursor();
if (auto* ds = qobject_cast<DiagramScene*>(scene())) {
ds->requestSnapshot();
}
e->accept();
return;
}
if (m_dragPart != DragPart::None && e->button() == Qt::LeftButton) {
m_dragPart = DragPart::None;
unsetCursor();

View file

@ -45,7 +45,7 @@ public:
std::optional<QPointF> hitTest(const QPointF& scenePos, qreal radius) const;
private:
enum class DragPart { None, BendX, TopHorizontal, BottomHorizontal };
enum class DragPart { None, BendX, TopHorizontal, BottomHorizontal, FromEnd, ToEnd };
Endpoint m_from;
Endpoint m_to;
@ -77,4 +77,5 @@ protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent* e) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* e) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e) override;
bool adjustEndpoint(Endpoint& ep, const QPointF& delta);
};

View file

@ -22,7 +22,9 @@ public:
void setId(int id) { m_id = id; }
QPointF portScenePos(Port p) const;
QPair<QPointF, QPointF> portSegment(Port p) const;
bool hitTestPort(const QPointF& scenePos, Port* outPort, QPointF* outLocalPos = nullptr, qreal radiusPx = 10.0) const;
QPointF portLocalPos(Port p) const;
void addArrow(ArrowItem* a);
void removeArrow(ArrowItem* a);
@ -39,7 +41,4 @@ private:
QRectF m_rect; // local rect
int m_id;
QSet<ArrowItem*> m_arrows;
QPointF portLocalPos(Port p) const;
QPair<QPointF, QPointF> portSegment(Port p) const;
};

View file

@ -19,11 +19,7 @@ DiagramScene::DiagramScene(QObject* parent)
const qreal w = 1122;
const qreal h = 793;
setSceneRect(-w * 0.5, -h * 0.5, w, h);
auto* frame = addRect(sceneRect(), QPen(QColor(80, 80, 80), 1.5, Qt::DashLine), Qt::NoBrush);
frame->setZValue(-5);
frame->setEnabled(false);
frame->setAcceptedMouseButtons(Qt::NoButton);
frame->setData(0, QVariant(QStringLiteral("static-frame")));
ensureFrame();
pushSnapshot();
}
@ -362,16 +358,8 @@ DiagramScene::Snapshot DiagramScene::captureSnapshot() const {
void DiagramScene::restoreSnapshot(const Snapshot& snap) {
m_restoringSnapshot = true;
cancelCurrentDrag();
// Clear dynamic items but keep the static frame.
QList<QGraphicsItem*> toRemove;
for (QGraphicsItem* it : items()) {
if (it->data(0).toString() == QStringLiteral("static-frame")) continue;
toRemove.append(it);
}
for (QGraphicsItem* it : toRemove) {
removeItem(it);
delete it;
}
clear();
ensureFrame();
m_nextBlockId = 1;
m_nextJunctionId = 1;
@ -425,6 +413,7 @@ void DiagramScene::restoreSnapshot(const Snapshot& snap) {
}
m_restoringSnapshot = false;
resetHistory(captureSnapshot());
}
void DiagramScene::pushSnapshot() {
@ -452,7 +441,52 @@ void DiagramScene::undo() {
restoreSnapshot(m_history[m_historyIndex]);
}
bool DiagramScene::goDownIntoSelected() {
const auto sel = selectedItems();
if (sel.size() != 1) return false;
auto* b = qgraphicsitem_cast<BlockItem*>(sel.first());
if (!b) return false;
return goDownIntoBlock(b);
}
bool DiagramScene::goUp() {
if (m_hierarchy.isEmpty()) return false;
Snapshot child = captureSnapshot();
m_children[m_currentBlockId] = child;
const HierNode parent = m_hierarchy.takeLast();
m_currentBlockId = parent.blockId;
restoreSnapshot(parent.snapshot);
return true;
}
bool DiagramScene::goDownIntoBlock(BlockItem* b) {
if (!b) return false;
Snapshot current = captureSnapshot();
m_hierarchy.push_back({m_currentBlockId, current});
m_currentBlockId = b->id();
Snapshot child = m_children.value(m_currentBlockId, Snapshot{});
restoreSnapshot(child);
return true;
}
void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent* e) {
if (e->button() == Qt::MiddleButton) {
const auto itemsUnder = items(e->scenePos());
for (QGraphicsItem* it : itemsUnder) {
if (auto* b = qgraphicsitem_cast<BlockItem*>(it)) {
if (goDownIntoBlock(b)) {
e->accept();
return;
}
}
}
if (goUp()) {
e->accept();
return;
}
}
if (e->button() == Qt::LeftButton) {
if (e->modifiers().testFlag(Qt::ControlModifier)) {
if (tryBranchAtArrow(e->scenePos())) {
@ -526,6 +560,18 @@ void DiagramScene::keyPressEvent(QKeyEvent* e) {
e->accept();
return;
}
if ((e->key() == Qt::Key_Down || e->key() == Qt::Key_PageDown) && e->modifiers().testFlag(Qt::ControlModifier)) {
if (goDownIntoSelected()) {
e->accept();
return;
}
}
if ((e->key() == Qt::Key_Up || e->key() == Qt::Key_PageUp) && e->modifiers().testFlag(Qt::ControlModifier)) {
if (goUp()) {
e->accept();
return;
}
}
QGraphicsScene::keyPressEvent(e);
}
@ -567,18 +613,20 @@ void DiagramScene::deleteSelection() {
}
}
// delete arrows first to avoid dangling removal from deleted blocks/junctions
QVector<ArrowItem*> arrowsToDelete;
QVector<QGraphicsItem*> othersToDelete;
for (QGraphicsItem* it : toDelete) {
if (qgraphicsitem_cast<ArrowItem*>(it)) {
removeItem(it);
delete it;
if (it->type() == ArrowItem::Type) {
if (auto* a = static_cast<ArrowItem*>(it)) arrowsToDelete.push_back(a);
} else {
othersToDelete.push_back(it);
}
}
for (QGraphicsItem* it : toDelete) {
if (!qgraphicsitem_cast<ArrowItem*>(it)) {
removeItem(it);
delete it;
}
for (ArrowItem* a : arrowsToDelete) {
delete a;
}
for (QGraphicsItem* it : othersToDelete) {
delete it;
}
if (!toDelete.isEmpty()) pushSnapshot();
@ -602,3 +650,26 @@ void DiagramScene::maybeSnapshotMovedItems() {
m_pressPositions.clear();
if (moved) pushSnapshot();
}
void DiagramScene::resetHistory(const Snapshot& base) {
m_history.clear();
m_history.push_back(base);
m_historyIndex = 0;
}
void DiagramScene::ensureFrame() {
bool exists = false;
for (QGraphicsItem* it : items()) {
if (it->data(0).toString() == QStringLiteral("static-frame")) {
exists = true;
break;
}
}
if (!exists) {
auto* frame = addRect(sceneRect(), QPen(QColor(80, 80, 80), 1.5, Qt::DashLine), Qt::NoBrush);
frame->setZValue(-5);
frame->setEnabled(false);
frame->setAcceptedMouseButtons(Qt::NoButton);
frame->setData(0, QVariant(QStringLiteral("static-frame")));
}
}

View file

@ -14,6 +14,9 @@ public:
BlockItem* createBlockAt(const QPointF& scenePos);
BlockItem* createBlockWithId(const QPointF& scenePos, int id, const QString& title);
void requestSnapshot();
bool goDownIntoSelected();
bool goDownIntoBlock(BlockItem* b);
bool goUp();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent* e) override;
@ -22,23 +25,6 @@ protected:
void keyPressEvent(QKeyEvent* e) override;
private:
ArrowItem* m_dragArrow = nullptr;
QPointer<BlockItem> m_dragFromBlock;
QPointer<JunctionItem> m_dragFromJunction;
BlockItem::Port m_dragFromPort = BlockItem::Port::Output;
int m_nextBlockId = 1;
int m_nextJunctionId = 1;
bool m_snapshotScheduled = false;
bool m_restoringSnapshot = false;
bool m_itemDragActive = false;
QHash<QGraphicsItem*, QPointF> m_pressPositions;
bool tryStartArrowDrag(const QPointF& scenePos);
bool tryFinishArrowDrag(const QPointF& scenePos);
bool tryBranchAtArrow(const QPointF& scenePos);
void cancelCurrentDrag();
void deleteSelection();
struct Snapshot {
struct Endpoint {
enum class Kind { None, Block, Junction, Scene } kind = Kind::None;
@ -63,6 +49,28 @@ private:
QVector<Arrow> arrows;
};
struct HierNode { int blockId; Snapshot snapshot; };
ArrowItem* m_dragArrow = nullptr;
QPointer<BlockItem> m_dragFromBlock;
QPointer<JunctionItem> m_dragFromJunction;
BlockItem::Port m_dragFromPort = BlockItem::Port::Output;
int m_nextBlockId = 1;
int m_nextJunctionId = 1;
bool m_snapshotScheduled = false;
bool m_restoringSnapshot = false;
bool m_itemDragActive = false;
QHash<QGraphicsItem*, QPointF> m_pressPositions;
int m_currentBlockId = -1;
QVector<HierNode> m_hierarchy;
QHash<int, Snapshot> m_children; // blockId -> saved child diagram
bool tryStartArrowDrag(const QPointF& scenePos);
bool tryFinishArrowDrag(const QPointF& scenePos);
bool tryBranchAtArrow(const QPointF& scenePos);
void cancelCurrentDrag();
void deleteSelection();
QVector<Snapshot> m_history;
int m_historyIndex = -1;
@ -72,6 +80,8 @@ private:
void scheduleSnapshot();
void undo();
void maybeSnapshotMovedItems();
void resetHistory(const Snapshot& base);
void ensureFrame();
enum class Edge { None, Left, Right, Top, Bottom };
Edge hitTestEdge(const QPointF& scenePos, QPointF* outScenePoint = nullptr) const;