mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 15:34:13 +01:00
Add manual conductor routing to the scripting API
Conductor::moveSegment(index, dx, dy) is the same primitive handlerMouseMoveEvent()/handlerMouseReleaseEvent() apply on a drag -- move both axes on the target segment (each of ConductorSegment's moveX()/moveY() silently no-ops on the wrong axis or a static, terminal-anchored segment), recompute the path, and push one ChangeConductorCommand undo step via the existing saveProfile(). Caught while writing the first test for it: moveSegment() never set modified_path, so Conductor::toXml() skipped writing <segment> children and a manually rerouted conductor silently reverted to auto-routing on the very next save -- the change took effect in the running scene but never reached disk. Fixed by setting the flag, the same as every other path-modifying call site already does. qet.conductorSegments() lists a conductor's segments (endpoints in scene coordinates, orientation, static/movable) so a script can find the index it wants; qet.moveConductorSegment() applies the move and refuses a static segment or an out-of-range index. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1310,6 +1310,34 @@ const QList<ConductorSegment *> Conductor::segmentsList() const
|
|||||||
return(segments_vector);
|
return(segments_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Conductor::moveSegment
|
||||||
|
Move one segment of this conductor by (dx, dy), the same primitive
|
||||||
|
handlerMouseMoveEvent()/handlerMouseReleaseEvent() apply on a manual
|
||||||
|
drag -- moveX()/moveY() each silently no-op on the wrong axis or a
|
||||||
|
static (terminal-anchored) segment, so both are always called and
|
||||||
|
whichever applies takes effect. Unlike a drag this commits the whole
|
||||||
|
move as a single undo step.
|
||||||
|
@param index a segmentsList() index
|
||||||
|
@param dx @param dy the movement, in the diagram's own coordinates
|
||||||
|
@return false if index is out of range
|
||||||
|
*/
|
||||||
|
bool Conductor::moveSegment(int index, qreal dx, qreal dy)
|
||||||
|
{
|
||||||
|
const QList<ConductorSegment *> segs = segmentsList();
|
||||||
|
if (index < 0 || index >= segs.count()) return false;
|
||||||
|
|
||||||
|
before_mov_text_pos_ = m_text_item->pos();
|
||||||
|
ConductorSegment *seg = segs.at(index);
|
||||||
|
seg->moveX(dx);
|
||||||
|
seg->moveY(dy);
|
||||||
|
modified_path = true;
|
||||||
|
segmentsToPath();
|
||||||
|
calculateTextItemPosition();
|
||||||
|
saveProfile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Conductor::length
|
@brief Conductor::length
|
||||||
@return the length of this conductor
|
@return the length of this conductor
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ class Conductor : public QGraphicsObject
|
|||||||
public:
|
public:
|
||||||
QVector <QPointF> handlerPoints() const;
|
QVector <QPointF> handlerPoints() const;
|
||||||
const QList<ConductorSegment *> segmentsList() const;
|
const QList<ConductorSegment *> segmentsList() const;
|
||||||
|
bool moveSegment(int index, qreal dx, qreal dy);
|
||||||
|
|
||||||
void setPropertyToPotential(
|
void setPropertyToPotential(
|
||||||
const ConductorProperties &property,
|
const ConductorProperties &property,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "../qetproject.h"
|
#include "../qetproject.h"
|
||||||
#include "../qetresult.h"
|
#include "../qetresult.h"
|
||||||
#include "../qetgraphicsitem/conductor.h"
|
#include "../qetgraphicsitem/conductor.h"
|
||||||
|
#include "../conductorsegment.h"
|
||||||
#include "../qetgraphicsitem/diagramimageitem.h"
|
#include "../qetgraphicsitem/diagramimageitem.h"
|
||||||
#include "../qetgraphicsitem/dynamicelementtextitem.h"
|
#include "../qetgraphicsitem/dynamicelementtextitem.h"
|
||||||
#include "../qetgraphicsitem/independenttextitem.h"
|
#include "../qetgraphicsitem/independenttextitem.h"
|
||||||
@@ -914,6 +915,84 @@ bool QetScriptApi::setConductorProperty(int folioIndex, const QString &elementUu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief QetScriptApi::conductorSegments
|
||||||
|
List the drawn path of the conductor on a terminal, one line per
|
||||||
|
segment: "index: (x1,y1)-(x2,y2) horizontal|vertical static|movable".
|
||||||
|
static marks a segment anchored to a terminal (moveConductorSegment()
|
||||||
|
on it is a no-op, the same as dragging its handle would be -- there is
|
||||||
|
no handle on it in the GUI). Points are in scene coordinates, matching
|
||||||
|
element_geometry().
|
||||||
|
*/
|
||||||
|
QStringList QetScriptApi::conductorSegments(int folioIndex, const QString &elementUuid,
|
||||||
|
int terminalIndex) const
|
||||||
|
{
|
||||||
|
// const_cast: findConductor logs, and log() writes to stderr, which is
|
||||||
|
// not a const operation on this object. The lookup itself changes
|
||||||
|
// nothing.
|
||||||
|
auto *self = const_cast<QetScriptApi *>(this);
|
||||||
|
Conductor *conductor = self->findConductor(folioIndex, elementUuid, terminalIndex,
|
||||||
|
QStringLiteral("conductorSegments"));
|
||||||
|
if (!conductor) return {};
|
||||||
|
|
||||||
|
QStringList result;
|
||||||
|
const QList<ConductorSegment *> segs = conductor->segmentsList();
|
||||||
|
for (int i = 0; i < segs.count(); ++i) {
|
||||||
|
ConductorSegment *seg = segs.at(i);
|
||||||
|
const QPointF p1 = conductor->mapToScene(seg->firstPoint());
|
||||||
|
const QPointF p2 = conductor->mapToScene(seg->secondPoint());
|
||||||
|
result << QStringLiteral("%1: (%2,%3)-(%4,%5) %6 %7")
|
||||||
|
.arg(i)
|
||||||
|
.arg(p1.x()).arg(p1.y()).arg(p2.x()).arg(p2.y())
|
||||||
|
.arg(seg->isHorizontal() ? QStringLiteral("horizontal") : QStringLiteral("vertical"),
|
||||||
|
seg->isStatic() ? QStringLiteral("static") : QStringLiteral("movable"));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief QetScriptApi::moveConductorSegment
|
||||||
|
Move one segment of the conductor on a terminal by (dx, dy) and push
|
||||||
|
one undo step for the whole move -- Conductor::moveSegment(), the same
|
||||||
|
primitive a manual handle drag applies. A segment only moves
|
||||||
|
perpendicular to its own direction, the same as dragging its handle:
|
||||||
|
dx moves a vertical segment, dy moves a horizontal one, and the other
|
||||||
|
of the pair is ignored (ConductorSegment::moveX()/moveY() each silently
|
||||||
|
no-op on the wrong axis) -- check conductorSegments() for which one
|
||||||
|
applies before calling this. dx/dy are in scene coordinates; a
|
||||||
|
translation-only item (every conductor) makes a scene-space delta equal
|
||||||
|
to a local one, so no conversion is needed. A static segment or an
|
||||||
|
out-of-range index is refused.
|
||||||
|
*/
|
||||||
|
bool QetScriptApi::moveConductorSegment(int folioIndex, const QString &elementUuid,
|
||||||
|
int terminalIndex, int segmentIndex,
|
||||||
|
double dx, double dy)
|
||||||
|
{
|
||||||
|
if (!m_project) return false;
|
||||||
|
if (m_project->isReadOnly()) {
|
||||||
|
log(QStringLiteral("qet.moveConductorSegment: project is read-only"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Conductor *conductor = findConductor(folioIndex, elementUuid, terminalIndex,
|
||||||
|
QStringLiteral("moveConductorSegment"));
|
||||||
|
if (!conductor) return false;
|
||||||
|
|
||||||
|
const QList<ConductorSegment *> segs = conductor->segmentsList();
|
||||||
|
if (segmentIndex < 0 || segmentIndex >= segs.count()) {
|
||||||
|
log(QStringLiteral("qet.moveConductorSegment: terminal %1 of %2 has %3 "
|
||||||
|
"segment(s), no index %4")
|
||||||
|
.arg(terminalIndex).arg(elementUuid).arg(segs.count()).arg(segmentIndex));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (segs.at(segmentIndex)->isStatic()) {
|
||||||
|
log(QStringLiteral("qet.moveConductorSegment: segment %1 is anchored to a "
|
||||||
|
"terminal and cannot be moved").arg(segmentIndex));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return conductor->moveSegment(segmentIndex, dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
QString QetScriptApi::elementLinkType(int folioIndex, const QString &elementUuid) const
|
QString QetScriptApi::elementLinkType(int folioIndex, const QString &elementUuid) const
|
||||||
{
|
{
|
||||||
Element *element = findElement(folioIndex, elementUuid);
|
Element *element = findElement(folioIndex, elementUuid);
|
||||||
|
|||||||
@@ -402,6 +402,14 @@ class QetScriptApi : public QObject
|
|||||||
int terminalIndex, const QString &property,
|
int terminalIndex, const QString &property,
|
||||||
const QString &value);
|
const QString &value);
|
||||||
|
|
||||||
|
// -- a conductor's own drawn path, not the whole potential's
|
||||||
|
// properties above -- one conductor only, addressed the same way --
|
||||||
|
Q_INVOKABLE QStringList conductorSegments(int folioIndex, const QString &elementUuid,
|
||||||
|
int terminalIndex) const;
|
||||||
|
Q_INVOKABLE bool moveConductorSegment(int folioIndex, const QString &elementUuid,
|
||||||
|
int terminalIndex, int segmentIndex,
|
||||||
|
double dx, double dy);
|
||||||
|
|
||||||
// -- cross-references: master/slave and report links --
|
// -- cross-references: master/slave and report links --
|
||||||
Q_INVOKABLE QString elementLinkType(int folioIndex, const QString &elementUuid) const;
|
Q_INVOKABLE QString elementLinkType(int folioIndex, const QString &elementUuid) const;
|
||||||
Q_INVOKABLE QStringList linkedElements(int folioIndex, const QString &elementUuid) const;
|
Q_INVOKABLE QStringList linkedElements(int folioIndex, const QString &elementUuid) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user