mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-03 09:14:12 +02:00
Merge pull request #1214 from ispyisail/feature/mcp-conductor-defaults
Add a qet_edit op for a folio's wire defaults (one number per potential)
This commit is contained in:
@@ -487,6 +487,13 @@ Python, plus the hang guard on `addConductor` and the database refresh in
|
||||
at names none of them and is refused, so address a potential from one of
|
||||
its leaves. Property names are the file's own, so `qet_conductors` reads
|
||||
back exactly what was set.
|
||||
- **`set_conductor_default` sets a folio's conductor defaults**, the
|
||||
Conductors tab of Folio properties: `onetextperfolio` (`"true"` shows one
|
||||
wire number per potential on the folio), or any `set_conductor` property,
|
||||
which conductors drawn later on that folio start from. `"folio": -1` sets
|
||||
the project's defaults instead, which each folio added afterwards copies;
|
||||
it does not change existing folios. Like the dialogs, it is not on the
|
||||
undo stack.
|
||||
- **`link_elements` takes a folio for each end**, because a master and its
|
||||
slave are normally on different folios. Whether a pair may be linked is
|
||||
decided by QElectroTech's own `isLinkable()`, so a script cannot make a
|
||||
|
||||
@@ -1425,6 +1425,10 @@ OPS = {
|
||||
"set_project_title": ("setProjectTitle", [("title", "str")]),
|
||||
"set_folio_border": ("setFolioBorder", [("folio", "folio"), ("property", "str"),
|
||||
("value", "str")]),
|
||||
# A folio's conductor defaults, or with "folio": -1 the project's ones
|
||||
# that each new folio copies.
|
||||
"set_conductor_default": ("setConductorDefault", [("folio", "folio"), ("property", "str"),
|
||||
("value", "str")]),
|
||||
"embed_title_block_template": ("embedTitleBlockTemplate", [("name", "str")]),
|
||||
"duplicate_elements": ("duplicateElements", [("folio", "folio"), ("elements", "elmts"),
|
||||
("to_folio", "folio"), ("x", "num"), ("y", "num")]),
|
||||
@@ -1499,6 +1503,10 @@ CONDUCTOR_PROPERTIES = ["num", "formula", "function", "bus", "cable",
|
||||
"color2", "bicolor", "style", "dash-size",
|
||||
"condsize", "numsize", "displaytext"]
|
||||
|
||||
# A folio's conductor defaults take the same names, plus the folio-wide
|
||||
# "one text per potential" switch, which no single conductor carries.
|
||||
CONDUCTOR_DEFAULT_PROPERTIES = ["onetextperfolio"] + CONDUCTOR_PROPERTIES
|
||||
|
||||
# Methods this tool needs that only exist in a build carrying the drawing
|
||||
# verbs. Probed in the script rather than assumed, because the failure mode
|
||||
# otherwise is a TypeError on line N of a generated file the caller never
|
||||
@@ -1752,6 +1760,11 @@ def _build_script(operations: list, output: str) -> str:
|
||||
if op.get("kind") == "element_info" and not op.get("field"):
|
||||
raise ValueError(f"operation {i}: element_info needs a non-empty "
|
||||
f"\"field\" (information key)")
|
||||
if (name == "set_conductor_default"
|
||||
and op.get("property") not in CONDUCTOR_DEFAULT_PROPERTIES):
|
||||
raise ValueError(f"operation {i}: unknown conductor default "
|
||||
f"{op.get('property')!r}; expected one of "
|
||||
f"{', '.join(CONDUCTOR_DEFAULT_PROPERTIES)}")
|
||||
if name == "set_folio_border" and op.get("property") not in FOLIO_BORDER_PROPERTIES:
|
||||
raise ValueError(f"operation {i}: unknown folio border property "
|
||||
f"{op.get('property')!r}; expected one of "
|
||||
@@ -2840,6 +2853,12 @@ TOOLS = [
|
||||
"set_folio_border sets one "
|
||||
"of the folio frame's " + ", ".join(FOLIO_BORDER_PROPERTIES) +
|
||||
" (counts 1-99, sizes 1-1000, display-* true/false). "
|
||||
"set_conductor_default sets one of a folio's conductor defaults "
|
||||
"(Folio properties > Conductors): onetextperfolio (true/false, one "
|
||||
"wire number per potential on the folio) or any set_conductor "
|
||||
"property, which new conductors on that folio start from; \"folio\": "
|
||||
"-1 sets the project's defaults that each folio added later copies. "
|
||||
"Not on the undo stack. "
|
||||
"embed_title_block_template copies a template into the project from "
|
||||
"the common/company/custom collection that has it (only reachable if "
|
||||
"the binary's compiled-in template path resolves to something real -- "
|
||||
|
||||
@@ -401,6 +401,8 @@ class EditValidation(unittest.TestCase):
|
||||
"regex": False, "case_sensitive": True}],
|
||||
"set_project_title": [{"op": "set_project_title", "title": "T"}],
|
||||
"set_folio_border": [f, {"op": "set_folio_border", "folio": "$f", "property": "columns", "value": "10"}],
|
||||
"set_conductor_default": [f, {"op": "set_conductor_default", "folio": "$f",
|
||||
"property": "onetextperfolio", "value": "true"}],
|
||||
"embed_title_block_template": [{"op": "embed_title_block_template", "name": "default"}],
|
||||
"duplicate_elements": el + [{"op": "duplicate_elements", "id": "d", "folio": "$f",
|
||||
"elements": ["$e"], "to_folio": "$f", "x": 50, "y": 50}],
|
||||
@@ -525,6 +527,8 @@ class EditValidation(unittest.TestCase):
|
||||
("unknown kind", {"op": "search_and_replace", "kind": "folio", "field": "x",
|
||||
"pattern": "a", "replacement": "b", "regex": False,
|
||||
"case_sensitive": False}),
|
||||
("unknown conductor default", {"op": "set_conductor_default", "folio": 0,
|
||||
"property": "label", "value": "x"}),
|
||||
("unknown conductor field", {"op": "search_and_replace", "kind": "conductor",
|
||||
"field": "label", "pattern": "a", "replacement": "b",
|
||||
"regex": False, "case_sensitive": False}),
|
||||
@@ -3685,6 +3689,28 @@ class Integration(unittest.TestCase):
|
||||
with self.subTest(prop=prop, value=good):
|
||||
self.ok(self.sb.edit(base, [{"op": "set_folio_border", "folio": 0, "property": prop, "value": good}]))
|
||||
|
||||
def test_conductor_defaults(self):
|
||||
"""The folio's "one text per potential" switch (#1178), and the
|
||||
project's defaults that a folio added later copies, as saved."""
|
||||
base = self.sb.new(folios=1)
|
||||
r = self.ok(self.sb.edit(base, [
|
||||
{"op": "set_conductor_default", "folio": 0, "property": "onetextperfolio", "value": "true"},
|
||||
{"op": "set_conductor_default", "folio": 0, "property": "conductor_section", "value": "1.5"},
|
||||
{"op": "set_conductor_default", "folio": -1, "property": "onetextperfolio", "value": "true"},
|
||||
{"op": "add_folio"}]))
|
||||
root = ET.parse(r["output"]).getroot()
|
||||
folios = [d.find("defaultconductor") for d in root.iter("diagram")]
|
||||
self.assertEqual([d.get("onetextperfolio") for d in folios], ["1", "1"],
|
||||
"set on folio 0; copied from the project's defaults by the new folio")
|
||||
self.assertEqual(folios[0].get("conductor_section"), "1.5")
|
||||
self.assertEqual(root.find("newdiagrams/conductors").get("onetextperfolio"), "1")
|
||||
for prop, bad in (("onetextperfolio", "yes"), ("numsize", "0"), ("color", "notacolour")):
|
||||
with self.subTest(prop=prop, value=bad):
|
||||
self.assertFalse(self.sb.edit(base, [{"op": "set_conductor_default", "folio": 0,
|
||||
"property": prop, "value": bad}])["ok"])
|
||||
self.assertFalse(self.sb.edit(base, [{"op": "set_conductor_default", "folio": 5,
|
||||
"property": "onetextperfolio", "value": "true"}])["ok"])
|
||||
|
||||
# ---- duplicating ----
|
||||
|
||||
def test_duplicate_returns_copies_in_the_order_asked(self):
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "../qetproject.h"
|
||||
#include "../qetresult.h"
|
||||
#include "../qetgraphicsitem/conductor.h"
|
||||
#include "../qetgraphicsitem/conductortextitem.h"
|
||||
#include "../conductorsegment.h"
|
||||
#include "../qetgraphicsitem/diagramimageitem.h"
|
||||
|
||||
@@ -3701,6 +3702,89 @@ bool QetScriptApi::setFolioBorder(int folioIndex, const QString &property, const
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QetScriptApi::conductorDefault
|
||||
One property of the conductor defaults: a folio's (what its new
|
||||
conductors start from, and where "one text per potential" lives), or
|
||||
with folioIndex -1, the project's, which each new folio copies.
|
||||
Empty if the folio or the property does not exist.
|
||||
*/
|
||||
QString QetScriptApi::conductorDefault(int folioIndex, const QString &property) const
|
||||
{
|
||||
if (!m_project) return QString();
|
||||
ConductorProperties p;
|
||||
if (folioIndex == -1) {
|
||||
p = m_project->defaultConductorProperties();
|
||||
} else {
|
||||
const QList<Diagram *> diagrams = m_project->diagrams();
|
||||
if (folioIndex < 0 || folioIndex >= diagrams.count()) return QString();
|
||||
p = diagrams.at(folioIndex)->defaultConductorProperties;
|
||||
}
|
||||
if (property == QLatin1String("onetextperfolio"))
|
||||
return p.m_one_text_per_folio ? QStringLiteral("true") : QStringLiteral("false");
|
||||
return conductorPropertyValue(p, property);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QetScriptApi::setConductorDefault
|
||||
Set one property of the conductor defaults, under the names
|
||||
setConductorProperty() takes plus "onetextperfolio" (true/false: one
|
||||
number per potential on each folio). Like the Folio properties and
|
||||
Project properties dialogs, this is not on the undo stack: neither
|
||||
dialog has an undo command for it.
|
||||
*/
|
||||
bool QetScriptApi::setConductorDefault(int folioIndex, const QString &property, const QString &value)
|
||||
{
|
||||
if (!m_project) return false;
|
||||
if (m_project->isReadOnly()) {
|
||||
log(QStringLiteral("qet.setConductorDefault: project is read-only"));
|
||||
return false;
|
||||
}
|
||||
Diagram *diagram = nullptr;
|
||||
if (folioIndex != -1) {
|
||||
const QList<Diagram *> diagrams = m_project->diagrams();
|
||||
if (folioIndex < 0 || folioIndex >= diagrams.count()) return false;
|
||||
diagram = diagrams.at(folioIndex);
|
||||
}
|
||||
const ConductorProperties old_p = diagram ? diagram->defaultConductorProperties
|
||||
: m_project->defaultConductorProperties();
|
||||
ConductorProperties new_p = old_p;
|
||||
if (property == QLatin1String("onetextperfolio")) {
|
||||
const QString v = value.toLower();
|
||||
if (v != QLatin1String("true") && v != QLatin1String("false")) {
|
||||
log(QStringLiteral("qet.setConductorDefault: onetextperfolio is true or false, not '%1'").arg(value));
|
||||
return false;
|
||||
}
|
||||
new_p.m_one_text_per_folio = (v == QLatin1String("true"));
|
||||
} else if (!setConductorPropertyValue(new_p, property, value)) {
|
||||
log(QStringLiteral("qet.setConductorDefault: cannot set '%1' to '%2'; properties are onetextperfolio, %3")
|
||||
.arg(property, value, conductorPropertyNames().join(QStringLiteral(", "))));
|
||||
return false;
|
||||
}
|
||||
if (new_p == old_p) return true;
|
||||
|
||||
if (!diagram) {
|
||||
m_project->setDefaultConductorProperties(new_p);
|
||||
return true;
|
||||
}
|
||||
diagram->defaultConductorProperties = new_p;
|
||||
// Show or hide the conductor texts now, as the Folio properties dialog
|
||||
// does (DiagramPropertiesDialog), or an export later in this run would
|
||||
// draw them as they were.
|
||||
if (new_p.m_one_text_per_folio != old_p.m_one_text_per_folio)
|
||||
{
|
||||
const QList<Conductor *> conductor_list = diagram->conductors();
|
||||
for (Conductor *c : conductor_list)
|
||||
{
|
||||
const ConductorProperties cp = c->properties();
|
||||
c->textItem()->setVisible(cp.type == ConductorProperties::Multi && cp.m_show_text);
|
||||
}
|
||||
for (Conductor *c : conductor_list)
|
||||
c->calculateTextItemPosition();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QetScriptApi::elementGeometry
|
||||
Where an element is: x and y are its origin (what setElementPosition()
|
||||
|
||||
@@ -538,6 +538,11 @@ class QetScriptApi : public QObject
|
||||
Q_INVOKABLE QString folioBorder(int folioIndex, const QString &property) const;
|
||||
Q_INVOKABLE bool setFolioBorder(int folioIndex, const QString &property, const QString &value);
|
||||
|
||||
// -- the conductor defaults of a folio (Folio properties > Conductors),
|
||||
// or with folioIndex -1, the project's defaults for new folios --
|
||||
Q_INVOKABLE QString conductorDefault(int folioIndex, const QString &property) const;
|
||||
Q_INVOKABLE bool setConductorDefault(int folioIndex, const QString &property, const QString &value);
|
||||
|
||||
// -- title block templates: which exist, embedding one into the project --
|
||||
Q_INVOKABLE QStringList titleBlockTemplates() const;
|
||||
Q_INVOKABLE bool embedTitleBlockTemplate(const QString &name);
|
||||
|
||||
Reference in New Issue
Block a user