From 76fda3f0e6796c3b5c4852de58f1895a2b4176c5 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 2 Aug 2026 07:30:14 +1200 Subject: [PATCH 001/350] Reflect unsaved-changes state in the main window title On macOS in particular there's currently no way to tell from the window chrome alone whether the active project has unsaved changes. The main window's title is set once in the constructor to a static string and never updated afterward, and QET never sets Qt's windowModified property anywhere -- so the native "document modified" indicator (the dot in the close button on macOS; an asterisk in the title on platforms that render it as text) never appears. Add QETDiagramEditor::updateWindowModifiedState(), which sets the window title to "[*] - QElectroTech" (the "[*]" is Qt's own placeholder convention for this) and calls setWindowModified() with the active project's own modified flag. Call it from two places: - subWindowActivated(), the single existing choke point already used whenever the visible MDI tab changes, so switching projects immediately reflects the newly active one's own state. - A new per-project connection to QETProject::projectModified, added in addProject() alongside the existing undo-stack registration, filtered to only act when the modified project is the currently active one. With no project open, the title and modified flag both revert to the original static, unmodified state. Implements https://github.com/qelectrotech/qelectrotech-source-mirror/discussions/596 --- sources/qetdiagrameditor.cpp | 33 +++++++++++++++++++++++++++++++++ sources/qetdiagrameditor.h | 1 + 2 files changed, 34 insertions(+) diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 5b2ba6779..7f9a2d4c7 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -1283,6 +1283,12 @@ bool QETDiagramEditor::addProject(QETProject *project, bool update_panel) undo_group.addStack(project -> undoStack()); + connect(project, &QETProject::projectModified, this, [this](QETProject *modified_project, bool) { + if (modified_project == currentProject()) { + updateWindowModifiedState(); + } + }); + m_element_collection_widget->addProject(project); // met a jour le panel d'elements @@ -2553,6 +2559,7 @@ void QETDiagramEditor::subWindowActivated(QMdiSubWindow *subWindows) slot_updateWindowsMenu(); emit syncElementsPanel(); updateUsageTrackersActiveState(); + updateWindowModifiedState(); } /** @@ -2578,6 +2585,32 @@ void QETDiagramEditor::updateUsageTrackersActiveState() } } +/** + @brief QETDiagramEditor::updateWindowModifiedState + Reflect the currently active project's unsaved-changes state in the + main window's title and native "document modified" indicator (e.g. + the dot in the close button on macOS). Called whenever the active + project changes, or whenever the active project's own modified state + changes. + + The window title's "[*]" placeholder is Qt's own convention: combined + with setWindowModified(), it lets each platform render the modified + indicator its own way (or not at all, on platforms without one) + without QET having to draw anything itself. +*/ +void QETDiagramEditor::updateWindowModifiedState() +{ + if (QETProject *project = currentProject()) { + setWindowTitle(QString("%1[*] - %2").arg( + project->pathNameTitle(), + tr("QElectroTech", "window title"))); + setWindowModified(project->projectOptionsWereModified()); + } else { + setWindowTitle(tr("QElectroTech", "window title")); + setWindowModified(false); + } +} + /** @brief QETDiagramEditor::selectionChanged This slot is called when a diagram selection was changed. diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 0114a186e..1d54899e8 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -98,6 +98,7 @@ class QETDiagramEditor : public QETMainWindow ProjectView *findProject(const QString &) const; QMdiSubWindow *subWindowForWidget(QWidget *) const; void updateUsageTrackersActiveState(); + void updateWindowModifiedState(); signals: void syncElementsPanel(); From a3511e86940bd9bf5a3dd8c9ea3060e73354cdf4 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 2 Aug 2026 08:12:22 +1200 Subject: [PATCH 002/350] Give Conductor its own persisted uuid Slice 1 of discussion #503 (from-to wiring list built on projectDataBase). Conductor is the one item type on a diagram without a stable identity of its own -- Element and Diagram both have a uuid, Conductor didn't. This is the prerequisite the wiring-list tables need: a conductor table keyed by uuid, the same way the existing element table is keyed by Element::uuid(). - Conductor gets a QUuid m_uuid, generated in the constructor, with uuid()/newUuid() accessors mirroring Element's exact pattern. - toXml()/fromXml() read/write a "uuid" attribute the same way Element already does, including the same generate-on-missing fallback (QUuid(e.attribute("uuid", QUuid::createUuid().toString()))) for projects saved before this change. - PasteDiagramCommand::redo() calls newUuid() on every pasted conductor (content.conductors(), all three categories), mirroring the existing per-element newUuid() call right above it -- otherwise copy-paste would duplicate a conductor's uuid. Backward compatibility: Conductor::valideXml() doesn't require the "uuid" attribute, so old files parse unchanged. Verified by opening a genuinely pre-uuid project (examples/industrial.qet, 150 folios, 671 conductors, legacy integer terminal1/terminal2 references with no uuid attribute at all) -- loads and renders correctly, gets uuids assigned on load, and those uuids are stable across a second load/save cycle (byte-identical uuid values). Verified paste separately: copying a selection with conductors and pasting produces distinct new uuids for every pasted conductor, none colliding with the originals or each other. --- sources/diagramcommands.cpp | 7 +++++++ sources/qetgraphicsitem/conductor.cpp | 8 ++++++++ sources/qetgraphicsitem/conductor.h | 4 ++++ 3 files changed, 19 insertions(+) diff --git a/sources/diagramcommands.cpp b/sources/diagramcommands.cpp index 2922c32b1..763f1f987 100644 --- a/sources/diagramcommands.cpp +++ b/sources/diagramcommands.cpp @@ -75,6 +75,13 @@ void PasteDiagramCommand::redo() { first_redo = false; + //make new uuid for every pasted conductor, because old uuid are + //the uuid of the copied conductor + const QList all_pasted_conductors = content.conductors(); + for (Conductor *c : all_pasted_conductors) { + c -> newUuid(); + } + //this is the first paste, we do some actions for the new element const QList elmts_list = content.m_elements; for (Element *e : elmts_list) diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index 291608620..546f64b3e 100644 --- a/sources/qetgraphicsitem/conductor.cpp +++ b/sources/qetgraphicsitem/conductor.cpp @@ -91,6 +91,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2) : //set Zvalue at 11 to be upper than the DiagramImageItem and element setZValue(11); m_previous_z_value = zValue(); + m_uuid = QUuid::createUuid(); //Add this conductor to the list of conductors of each of the two terminals bool ajout_p1 = terminal1 -> addConductor(this); @@ -1005,6 +1006,12 @@ void Conductor::pointsToSegments(const QList& points_list) { */ bool Conductor::fromXml(QDomElement &dom_element) { + //Older project files have no conductor uuid attribute at all -- + //generate one on load, same treatment terminal uuids got when + //that field was introduced (see terminal1/terminal2 handling in + //toXml() below). + m_uuid = QUuid(dom_element.attribute("uuid", QUuid::createUuid().toString())); + setPos(dom_element.attribute("x", nullptr).toDouble(), dom_element.attribute("y", nullptr).toDouble()); @@ -1043,6 +1050,7 @@ QDomElement Conductor::toXml(QDomDocument &dom_document, { QDomElement dom_element = dom_document.createElement("conductor"); + dom_element.setAttribute("uuid", m_uuid.toString()); dom_element.setAttribute("x", QString::number(pos().x())); dom_element.setAttribute("y", QString::number(pos().y())); diff --git a/sources/qetgraphicsitem/conductor.h b/sources/qetgraphicsitem/conductor.h index dc4d5586b..91ca92afb 100644 --- a/sources/qetgraphicsitem/conductor.h +++ b/sources/qetgraphicsitem/conductor.h @@ -21,6 +21,7 @@ #include "../conductorproperties.h" #include +#include class ConductorProfile; class ConductorSegmentProfile; @@ -77,6 +78,8 @@ class Conductor : public QGraphicsObject int type() const override { return Type; } Diagram *diagram() const; ConductorTextItem *textItem() const; + QUuid uuid() const {return m_uuid;} + void newUuid() {m_uuid = QUuid::createUuid();} //create new uuid for this conductor void updatePath(const QRectF & = QRectF()); //This method do nothing, it's only made to be used with Q_PROPERTY @@ -205,6 +208,7 @@ class Conductor : public QGraphicsObject Highlight must_highlight_; bool m_valid; bool m_freeze_label = false; + QUuid m_uuid; /// QPen et QBrush objects used to draw conductors static QPen conductor_pen; From ca42a2b7ff46dc018ad872ecdb91a882c9e1f4e9 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Sun, 2 Aug 2026 15:18:57 +0200 Subject: [PATCH 003/350] Auto-break conductor --- .../diagramevent/diagrameventaddelement.cpp | 176 +++++++++++++++++- sources/qetdiagrameditor.cpp | 21 +++ sources/qetdiagrameditor.h | 1 + sources/qetproject.cpp | 28 +++ sources/qetproject.h | 4 + 5 files changed, 222 insertions(+), 8 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index 203a0d953..5410551ca 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -20,11 +20,16 @@ #include "../conductorautonumerotation.h" #include "../diagram.h" #include "../undocommand/addgraphicsobjectcommand.h" +#include "../undocommand/deleteqgraphicsitemcommand.h" #include "../factory/elementfactory.h" #include "../qetapp.h" #include "../qetdiagrameditor.h" #include "../qetgraphicsitem/element.h" #include "../qetgraphicsitem/conductor.h" +#include "../qetgraphicsitem/terminal.h" +#include "../qet.h" +#include +#include /** @brief DiagramEventAddElement::DiagramEventAddElement @@ -248,16 +253,171 @@ void DiagramEventAddElement::addElement() QUndoCommand *undo_object = new QUndoCommand(tr("Ajouter %1").arg(element->name())); new AddGraphicsObjectCommand(element, m_diagram, m_element -> pos(), undo_object); - //When we search for free aligned terminal we temporally remove m_element to - //avoid any interaction with the function Element::AlignedFreeTerminals - //This is useful when an element has two (or more) terminals on opposite sides, - //because m_element is exactly at the same pos of the new element - //added to the scene so new conductor are created between terminal of the new element - //and the opposite terminal of m_element. + //When we search for free aligned terminal we temporally remove m_element to + //avoid any interaction with the function Element::AlignedFreeTerminals + //This is useful when an element has two (or more) terminals on opposite sides, + //because m_element is exactly at the same pos of the new element + //added to the scene so new conductor are created between terminal of the new element + //and the opposite terminal of m_element. m_diagram->removeItem(m_element); - while (!element -> AlignedFreeTerminals().isEmpty() && m_diagram -> project() -> autoConductor()) + + //Auto break conductor: if a terminal of the new element lies on an existing + //conductor, break the conductor and reconnect through the new element's terminal. + //Track the endpoints of broken conductors so auto-connect doesn't create duplicates. + QSet broken_endpoints; + + if (m_diagram->project()->autoBreakConductor()) { - QPair pair = element -> AlignedFreeTerminals().takeFirst(); + //Track which conductors we already handled for this element + QList conductors_handled; + //Track which terminals of the new element are already used (by break or other-connect) + QSet used_terminals; + + foreach (Terminal *t, element->terminals()) + { + QPointF t_dock = t->dockConductor(); + + foreach (Conductor *c, m_diagram->conductors()) + { + //Skip conductors we already handled or connected to the new element + if (conductors_handled.contains(c) || + c->terminal1->parentElement() == element || + c->terminal2->parentElement() == element) + continue; + + //Check if dock point lies on the conductor path. + //Convert dock_point to the conductor's local coordinate system, + //because c->path() is in local coordinates (generated via mapFromScene). + QPointF local_dock = c->mapFromScene(t_dock); + bool point_on_conductor = false; + QPainterPath path = c->path(); + for (int i = 0; i < path.elementCount() - 1; ++i) + { + const QPainterPath::Element &e1 = path.elementAt(i); + const QPainterPath::Element &e2 = path.elementAt(i + 1); + QLineF segment(QPointF(e1.x, e1.y), QPointF(e2.x, e2.y)); + QPointF projection; + if (QET::orthogonalProjection(local_dock, segment, &projection)) + { + qreal dist = QLineF(local_dock, projection).length(); + if (dist < 5.0) + { + point_on_conductor = true; + break; + } + } + } + + if (!point_on_conductor) + continue; + + //The terminal lies on this conductor. + //Break it: delete old conductor, create one new conductor from the + //aligned endpoint to the new terminal. The other endpoint is left + //for auto-connect to handle (e.g. connecting to the opposite terminal + //of the new element). + Terminal *c1 = c->terminal1; + Terminal *c2 = c->terminal2; + + conductors_handled.append(c); + + //Get scene positions for endpoint selection + QPointF c1_dock = c1->dockConductor(); + QPointF c2_dock = c2->dockConductor(); + + //Determine which endpoint to connect based on terminal orientation. + //Terminal::orientation() already accounts for element rotation, + //so a North terminal rotated 90° returns East, etc. + Terminal *connect_to = nullptr; + Terminal *other = nullptr; + + switch (t->orientation()) { + case Qet::North: + if (c1_dock.y() < t_dock.y()) { connect_to = c1; other = c2; } + else if (c2_dock.y() < t_dock.y()) { connect_to = c2; other = c1; } + break; + case Qet::South: + if (c1_dock.y() > t_dock.y()) { connect_to = c1; other = c2; } + else if (c2_dock.y() > t_dock.y()) { connect_to = c2; other = c1; } + break; + case Qet::East: + if (c1_dock.x() > t_dock.x()) { connect_to = c1; other = c2; } + else if (c2_dock.x() > t_dock.x()) { connect_to = c2; other = c1; } + break; + case Qet::West: + if (c1_dock.x() < t_dock.x()) { connect_to = c1; other = c2; } + else if (c2_dock.x() < t_dock.x()) { connect_to = c2; other = c1; } + break; + } + + //Fallback: use nearest endpoint + if (!connect_to) { + qreal d1 = QLineF(t_dock, c1_dock).length(); + qreal d2 = QLineF(t_dock, c2_dock).length(); + if (d1 <= d2) { connect_to = c1; other = c2; } + else { connect_to = c2; other = c1; } + } + + //Delete the old conductor + DiagramContent content; + content.m_other_conductors.append(c); + new DeleteQGraphicsItemCommand(m_diagram, content, undo_object); + + //Create new conductor from the aligned endpoint to the new terminal + Conductor *new_c = new Conductor(connect_to, t); + new AddGraphicsObjectCommand(new_c, m_diagram, QPointF(), undo_object); + ConductorAutoNumerotation can(new_c, m_diagram, undo_object); + can.numerate(); + if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) + new_c->setFreezeLabel(true); + + broken_endpoints.insert(connect_to); + used_terminals.insert(t); + + //Also connect the 'other' endpoint to preserve bent conductor segments. + //For L-shaped conductors (e.g. horizontal + vertical), the 'other' endpoint + //may be far from the new element. Find the nearest free terminal of the new + //element and create a conductor to it. + QPointF other_dock = other->dockConductor(); + Terminal *other_terminal = nullptr; + qreal best_dist = std::numeric_limits::max(); + foreach (Terminal *ot, element->terminals()) + { + if (used_terminals.contains(ot)) + continue; + + qreal dist = QLineF(ot->dockConductor(), other_dock).length(); + if (dist < best_dist) { + best_dist = dist; + other_terminal = ot; + } + } + + if (other_terminal) { + Conductor *new_c2 = new Conductor(other, other_terminal); + new AddGraphicsObjectCommand(new_c2, m_diagram, QPointF(), undo_object); + ConductorAutoNumerotation can2(new_c2, m_diagram, undo_object); + can2.numerate(); + if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) + new_c2->setFreezeLabel(true); + + broken_endpoints.insert(other); + used_terminals.insert(other_terminal); + } + } + } + } + + //Auto-connect: collect all aligned pairs first, then filter and process. + QList> aligned_pairs; + if (m_diagram->project()->autoConductor()) + aligned_pairs = element->AlignedFreeTerminals(); + + for (const QPair &pair : aligned_pairs) + { + //Skip if the other terminal was an endpoint of a broken conductor + if (broken_endpoints.contains(pair.second)) + continue; Conductor *conductor = new Conductor(pair.first, pair.second); new AddGraphicsObjectCommand(conductor, m_diagram, QPointF(), undo_object); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 5b2ba6779..dd6e0a572 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -369,6 +369,21 @@ void QETDiagramEditor::setUpActions() pv->project()->setAutoConductor(ac); }); + //AutoBreakConductor + m_auto_break_conductor = new QAction (QET::Icons::Conductor, tr("Coupure automatique de conducteur(s)","Tool tip of auto break conductor"), this); + m_auto_break_conductor->setStatusTip (tr("Couper automatiquement les conducteurs existants lors du placement d'un élément", "Status tip of auto break conductor")); + m_auto_break_conductor->setCheckable (true); + { + QSettings settings; + m_auto_break_conductor->setChecked(settings.value("diagrameditor/auto_break_conductor", false).toBool()); + } + connect(m_auto_break_conductor, &QAction::triggered, [this](bool abc) { + QSettings settings; + settings.setValue("diagrameditor/auto_break_conductor", abc); + if (ProjectView *pv = currentProjectView()) + pv->project()->setAutoBreakConductor(abc); + }); + //Switch background color m_grey_background = new QAction (QET::Icons::DiagramBg, tr("Couleur de fond blanc/gris","Tool tip of white/grey background button"), this); m_grey_background -> setStatusTip (tr("Affiche la couleur de fond du folio en blanc ou en gris", "Status tip of white/grey background button")); @@ -808,6 +823,7 @@ void QETDiagramEditor::setUpToolBar() diagram_tool_bar -> addAction (m_edit_diagram_properties); diagram_tool_bar -> addAction (m_conductor_reset); diagram_tool_bar -> addAction (m_auto_conductor); + diagram_tool_bar -> addAction (m_auto_break_conductor); m_add_item_tool_bar = new QToolBar(tr("Ajouter"), this); m_add_item_tool_bar->setObjectName("adding"); @@ -1892,9 +1908,14 @@ void QETDiagramEditor::slot_updateModeActions() { m_auto_conductor -> setEnabled (true); m_auto_conductor -> setChecked (pv -> project() -> autoConductor()); + m_auto_break_conductor -> setEnabled (true); + m_auto_break_conductor -> setChecked (pv -> project() -> autoBreakConductor()); } else + { m_auto_conductor -> setDisabled(true); + m_auto_break_conductor -> setDisabled(true); + } } /** diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 0114a186e..fdd3c12bb 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -191,6 +191,7 @@ class QETDiagramEditor : public QETMainWindow *redo, ///< Redo the latest cancelled operation *m_paste, ///< Paste clipboard content on the current diagram *m_auto_conductor, ///< Enable/Disable the use of auto conductor + *m_auto_break_conductor, ///< Enable/Disable the use of auto break conductor *conductor_default, ///< Show a dialog to edit default conductor properties *m_grey_background, ///< Switch the background color in white or grey *m_draw_grid, ///< Switch the background grid display or not diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 3d205edfa..6d248e925 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -69,6 +69,10 @@ m_project_properties_handler{this} init(); QSettings settings; + + //Read auto break conductor default from global settings + m_auto_break_conductor = settings.value(QStringLiteral("diagrameditor/auto_break_conductor"), false).toBool(); + int size = settings.beginReadArray(QStringLiteral("diagrameditor/defaultguides")); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); @@ -924,6 +928,28 @@ void QETProject::setAutoConductor(bool ac) m_auto_conductor = ac; } +/** + @brief QETProject::autoBreakConductor + @return true if use of auto break conductor is authorized. + See also Q_PROPERTY autoBreakConductor +*/ +bool QETProject::autoBreakConductor() const +{ + return m_auto_break_conductor; +} + +/** + @brief QETProject::setAutoBreakConductor + @param abc + Enable the use of auto break conductor if true + See also Q_PROPERTY autoBreakConductor +*/ +void QETProject::setAutoBreakConductor(bool abc) +{ + if (abc != m_auto_break_conductor) + m_auto_break_conductor = abc; +} + /** @brief QETProject::autoFolioNumberingNewFolios emit Signal to add new Diagram with autonum @@ -1732,6 +1758,7 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project) { m_current_conductor_autonum = conds_autonums.attribute(QStringLiteral("current_autonum")); m_freeze_new_conductors = conds_autonums.attribute(QStringLiteral("freeze_new_conductors")) == QLatin1String("true"); + m_auto_break_conductor = conds_autonums.attribute(QStringLiteral("auto_break_conductors")) == QLatin1String("true"); for (auto elmt : QET::findInDomElement(conds_autonums, QStringLiteral("conductor_autonum"))) { NumerotationContext nc; @@ -1858,6 +1885,7 @@ void QETProject::writeDefaultPropertiesXml(QDomElement &xml_element) QDomElement conductor_autonums = xml_document.createElement("conductors_autonums"); conductor_autonums.setAttribute("current_autonum", m_current_conductor_autonum); conductor_autonums.setAttribute("freeze_new_conductors", m_freeze_new_conductors ? "true" : "false"); + conductor_autonums.setAttribute("auto_break_conductors", m_auto_break_conductor ? "true" : "false"); foreach (QString key, conductorAutoNum().keys()) { QDomElement conductor_autonum = conductorAutoNum(key).toXml(xml_document, "conductor_autonum"); if (key != "" && conductorAutoNumFormula(key) != "") { diff --git a/sources/qetproject.h b/sources/qetproject.h index dfd5ab8ea..891512c43 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -90,6 +90,7 @@ class QETProject : public QObject }; Q_PROPERTY(bool autoConductor READ autoConductor WRITE setAutoConductor) + Q_PROPERTY(bool autoBreakConductor READ autoBreakConductor WRITE setAutoBreakConductor) // constructors, destructor public: @@ -181,9 +182,11 @@ class QETProject : public QObject void setFreezeNewConductors(bool); bool autoConductor () const; + bool autoBreakConductor () const; bool autoElement () const; bool autoFolio () const; void setAutoConductor (bool ac); + void setAutoBreakConductor (bool abc); void setAutoElement (bool ae); void autoFolioNumberingNewFolios (); void autoFolioNumberingSelectedFolios(int, int, const QString&); @@ -312,6 +315,7 @@ class QETProject : public QObject QHash m_element_autonum; //Title and NumContext hash QString m_current_element_autonum; bool m_auto_conductor = true; + bool m_auto_break_conductor = false; XmlElementCollection *m_elements_collection = nullptr; bool m_freeze_new_elements = false; bool m_freeze_new_conductors = false; From 6b9cb0a220b3ffdb3199756c9929232daf460f8f Mon Sep 17 00:00:00 2001 From: ispyisail Date: Mon, 3 Aug 2026 10:28:26 +1200 Subject: [PATCH 004/350] Add user-defined custom properties on elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ElementInfoWidget's fixed ~40 predefined ELMT_* keys had no way for a user to add a genuinely new element-info key, even though DiagramContext already stores/round-trips arbitrary keys generically via toXml()/fromXml(). Adds an "Ajouter une propriété personnalisée" button that appends a CustomElementInfoPartWidget row (both key and value user-editable, unlike the fixed ElementInfoPartWidget rows bound to one predefined key). The typed key is validated live against the existing DiagramContext::isKeyAcceptable() and flagged with a red border when it doesn't match, instead of silently dropping it. Any key already present on the element that isn't one of the predefined/special keys is re-displayed as a custom row on next selection. Implements the scope proposed in discussion #611. --- cmake/qet_compilation_vars.cmake | 2 + sources/ui/customelementinfopartwidget.cpp | 113 +++++++++++++++++++++ sources/ui/customelementinfopartwidget.h | 61 +++++++++++ sources/ui/elementinfowidget.cpp | 95 +++++++++++++++++ sources/ui/elementinfowidget.h | 7 ++ 5 files changed, 278 insertions(+) create mode 100644 sources/ui/customelementinfopartwidget.cpp create mode 100644 sources/ui/customelementinfopartwidget.h diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake index 57a012916..56ed72ebc 100644 --- a/cmake/qet_compilation_vars.cmake +++ b/cmake/qet_compilation_vars.cmake @@ -683,6 +683,8 @@ set(QET_SRC_FILES ${QET_DIR}/sources/ui/dynamicelementtextitemeditor.h ${QET_DIR}/sources/ui/dynamicelementtextmodel.cpp ${QET_DIR}/sources/ui/dynamicelementtextmodel.h + ${QET_DIR}/sources/ui/customelementinfopartwidget.cpp + ${QET_DIR}/sources/ui/customelementinfopartwidget.h ${QET_DIR}/sources/ui/elementinfopartwidget.cpp ${QET_DIR}/sources/ui/elementinfopartwidget.h ${QET_DIR}/sources/ui/elementinfowidget.cpp diff --git a/sources/ui/customelementinfopartwidget.cpp b/sources/ui/customelementinfopartwidget.cpp new file mode 100644 index 000000000..a1130f807 --- /dev/null +++ b/sources/ui/customelementinfopartwidget.cpp @@ -0,0 +1,113 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "customelementinfopartwidget.h" + +#include "../diagramcontext.h" +#include "../qeticons.h" + +#include +#include +#include + +/** + @brief CustomElementInfoPartWidget::CustomElementInfoPartWidget + Constructor + @param key initial key name (empty for a freshly added row) + @param value initial value + @param parent parent widget +*/ +CustomElementInfoPartWidget::CustomElementInfoPartWidget( + const QString &key, + const QString &value, + QWidget *parent) : + QWidget(parent), + m_key_edit(new QLineEdit(key, this)), + m_value_edit(new QLineEdit(value, this)), + m_remove_button(new QToolButton(this)) +{ + m_key_edit->setPlaceholderText(tr("nom_de_la_propriete")); + m_key_edit->setToolTip(tr("Lettres minuscules, chiffres, tiret et underscore uniquement")); + m_value_edit->setClearButtonEnabled(true); + + m_remove_button->setIcon(QET::Icons::Remove); + m_remove_button->setToolTip(tr("Supprimer cette propriété")); + m_remove_button->setAutoRaise(true); + + auto *layout = new QGridLayout(this); + layout->setContentsMargins(0, 2, 0, 2); + layout->setVerticalSpacing(2); + layout->setHorizontalSpacing(0); + layout->addWidget(m_key_edit, 0, 0); + layout->addWidget(m_value_edit, 1, 0); + layout->addWidget(m_remove_button, 0, 1, 2, 1); + + connect(m_key_edit, &QLineEdit::textChanged, this, &CustomElementInfoPartWidget::validateKey); + connect(m_key_edit, &QLineEdit::textChanged, this, &CustomElementInfoPartWidget::changed); + connect(m_value_edit, &QLineEdit::textChanged, this, &CustomElementInfoPartWidget::changed); + connect(m_remove_button, &QToolButton::clicked, this, [this]() { + emit removeRequested(this); + }); + + setFocusProxy(m_key_edit); + validateKey(); +} + +CustomElementInfoPartWidget::~CustomElementInfoPartWidget() +{ +} + +/** + @return the key name currently typed in this row +*/ +QString CustomElementInfoPartWidget::key() const +{ + return m_key_edit->text().trimmed(); +} + +/** + @return the value currently typed in this row +*/ +QString CustomElementInfoPartWidget::value() const +{ + return m_value_edit->text(); +} + +/** + @return true if the typed key is non-empty and matches + DiagramContext::isKeyAcceptable() +*/ +bool CustomElementInfoPartWidget::hasValidKey() const +{ + const QString k = key(); + return !k.isEmpty() && DiagramContext::isKeyAcceptable(k); +} + +/** + @brief CustomElementInfoPartWidget::validateKey + Flag the key field when it doesn't match the accepted format, + instead of silently dropping it later. +*/ +void CustomElementInfoPartWidget::validateKey() +{ + const QString k = key(); + if (k.isEmpty() || DiagramContext::isKeyAcceptable(k)) { + m_key_edit->setStyleSheet(QString()); + } else { + m_key_edit->setStyleSheet(QStringLiteral("border: 1px solid red;")); + } +} diff --git a/sources/ui/customelementinfopartwidget.h b/sources/ui/customelementinfopartwidget.h new file mode 100644 index 000000000..c5bd3d1e9 --- /dev/null +++ b/sources/ui/customelementinfopartwidget.h @@ -0,0 +1,61 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef CUSTOMELEMENTINFOPARTWIDGET_H +#define CUSTOMELEMENTINFOPARTWIDGET_H + +#include + +class QLineEdit; +class QToolButton; + +/** + @brief The CustomElementInfoPartWidget class + A single row letting the user define their own element information + key/value pair, unlike ElementInfoPartWidget which is bound to one + predefined key. The key is validated against + DiagramContext::isKeyAcceptable() as the user types. +*/ +class CustomElementInfoPartWidget : public QWidget +{ + Q_OBJECT + + public: + explicit CustomElementInfoPartWidget( + const QString &key = QString(), + const QString &value = QString(), + QWidget *parent = nullptr); + ~CustomElementInfoPartWidget() override; + + QString key() const; + QString value() const; + bool hasValidKey() const; + + signals: + void changed(); + void removeRequested(CustomElementInfoPartWidget *self); + + private slots: + void validateKey(); + + private: + QLineEdit *m_key_edit; + QLineEdit *m_value_edit; + QToolButton *m_remove_button; +}; + +#endif // CUSTOMELEMENTINFOPARTWIDGET_H diff --git a/sources/ui/elementinfowidget.cpp b/sources/ui/elementinfowidget.cpp index 0b240809b..a566643c5 100644 --- a/sources/ui/elementinfowidget.cpp +++ b/sources/ui/elementinfowidget.cpp @@ -17,12 +17,14 @@ */ #include "elementinfowidget.h" #include +#include #include "../diagram.h" #include "../qetapp.h" #include "../qetgraphicsitem/element.h" #include "../qetinformation.h" #include "../ui_elementinfowidget.h" #include "../undocommand/changeelementinformationcommand.h" +#include "customelementinfopartwidget.h" #include "elementinfopartwidget.h" /** @@ -47,6 +49,7 @@ ElementInfoWidget::ElementInfoWidget(Element *elmt, QWidget *parent) : ElementInfoWidget::~ElementInfoWidget() { qDeleteAll(m_eipw_list); + qDeleteAll(m_custom_eipw_list); delete ui; } @@ -207,6 +210,11 @@ void ElementInfoWidget::buildInterface() ui->scroll_vlayout->addWidget(eipw); m_eipw_list << eipw; } + + m_add_custom_property_btn = new QPushButton(tr("Ajouter une propriété personnalisée"), this); + connect(m_add_custom_property_btn, &QPushButton::clicked, this, [this]() { addCustomProperty(); }); + ui->scroll_vlayout->addWidget(m_add_custom_property_btn); + ui->scroll_vlayout->addStretch(); // Existing potential isolating checkbox @@ -235,6 +243,67 @@ void ElementInfoWidget::buildInterface() m_potential_isolating_cb->setVisible(false); } } +/** + @brief ElementInfoWidget::predefinedKeys + @return every key this widget already exposes a dedicated row for, + whether through ElementInfoPartWidget (the ~40 ELMT_* keys) or one + of the standalone checkboxes. Anything present in the element's + informations but absent from this list is a user-defined custom + property. +*/ +QStringList ElementInfoWidget::predefinedKeys() const +{ + QStringList keys = (m_element.data()->elementData().m_type == ElementData::Terminal) + ? QETInformation::terminalElementInfoKeys() + : QETInformation::elementInfoKeys(); + + keys << QStringLiteral("auto_num_locked") + << QStringLiteral("potential_isolating") + << QStringLiteral("exclude_from_bom"); + + return keys; +} + +/** + @brief ElementInfoWidget::addCustomProperty + Append a new user-defined key/value row to the widget. + @param key initial key, left empty for a freshly added row + @param value initial value +*/ +void ElementInfoWidget::addCustomProperty(const QString &key, const QString &value) +{ + auto *widget = new CustomElementInfoPartWidget(key, value, this); + + const int insert_index = ui->scroll_vlayout->indexOf(m_add_custom_property_btn); + ui->scroll_vlayout->insertWidget(insert_index >= 0 ? insert_index : ui->scroll_vlayout->count(), widget); + m_custom_eipw_list << widget; + + connect(widget, &CustomElementInfoPartWidget::removeRequested, this, &ElementInfoWidget::removeCustomProperty); + connect(widget, &CustomElementInfoPartWidget::changed, this, [this]() { + if (m_live_edit) apply(); + }); + + if (key.isEmpty()) { + widget->setFocus(); + } +} + +/** + @brief ElementInfoWidget::removeCustomProperty + Remove a user-defined key/value row. + @param widget the row to remove +*/ +void ElementInfoWidget::removeCustomProperty(CustomElementInfoPartWidget *widget) +{ + if (!m_custom_eipw_list.removeOne(widget)) + return; + + ui->scroll_vlayout->removeWidget(widget); + widget->deleteLater(); + + if (m_live_edit) apply(); +} + /** @brief ElementInfoWidget::infoPartWidgetForKey @param key @@ -271,6 +340,21 @@ void ElementInfoWidget::updateUi() for (ElementInfoPartWidget *eipw : m_eipw_list) { eipw -> setText (element_info[eipw->key()].toString()); } + + // Rebuild the custom-property rows to match whatever + // user-defined keys this element currently carries. + while (!m_custom_eipw_list.isEmpty()) { + CustomElementInfoPartWidget *w = m_custom_eipw_list.takeLast(); + ui->scroll_vlayout->removeWidget(w); + delete w; + } + const auto known_keys = predefinedKeys(); + for (const QString &key : element_info.keys()) { + if (!known_keys.contains(key)) { + addCustomProperty(key, element_info[key].toString()); + } + } + // Load the lock status for auto numbering if (m_element->elementData().m_type == ElementData::Terminal) { QString lock_value = element_info.value(QStringLiteral("auto_num_locked")).toString(); @@ -314,6 +398,17 @@ DiagramContext ElementInfoWidget::currentInfo() const } } + for (const auto &custom : std::as_const(m_custom_eipw_list)) + { + if (custom->hasValidKey() && !custom->value().isEmpty()) + { + QString txt{custom->value()}; + txt.remove(QStringLiteral("\r")); + txt.remove(QStringLiteral("\n")); + info_.addValue(custom->key(), txt); + } + } + // Save the auto numbering lock status if (m_element->elementData().m_type == ElementData::Terminal) { info_.addValue(QStringLiteral("auto_num_locked"), ui->m_auto_num_locked_cb->isChecked() ? QStringLiteral("true") : QStringLiteral("false")); diff --git a/sources/ui/elementinfowidget.h b/sources/ui/elementinfowidget.h index d47d455b6..263a276ae 100644 --- a/sources/ui/elementinfowidget.h +++ b/sources/ui/elementinfowidget.h @@ -26,8 +26,10 @@ class Element; class QUndoCommand; class ElementInfoPartWidget; +class CustomElementInfoPartWidget; class ChangeElementInformationCommand; class QCheckBox; +class QPushButton; namespace Ui { class ElementInfoWidget; @@ -63,15 +65,20 @@ class ElementInfoWidget : public AbstractElementPropertiesEditorWidget private: void buildInterface(); ElementInfoPartWidget *infoPartWidgetForKey(const QString &key) const; + QStringList predefinedKeys() const; private slots: void firstActivated(); void elementInfoChange(); + void addCustomProperty(const QString &key = QString(), const QString &value = QString()); + void removeCustomProperty(CustomElementInfoPartWidget *widget); //ATTRIBUTES private: Ui::ElementInfoWidget *ui; QList m_eipw_list; + QList m_custom_eipw_list; + QPushButton *m_add_custom_property_btn = nullptr; QCheckBox *m_potential_isolating_cb = nullptr; QCheckBox *m_exclude_from_bom_cb = nullptr; bool m_first_activation; From d850241f91725b1ce2ecee06fcf7a143c7a3446c Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Mon, 3 Aug 2026 19:17:38 +0200 Subject: [PATCH 005/350] fix --- .../diagramevent/diagrameventaddelement.cpp | 102 ++++++++++++------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index 5410551ca..9e8648f7d 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -275,8 +275,20 @@ void DiagramEventAddElement::addElement() foreach (Terminal *t, element->terminals()) { + //Skip terminals already used by a previous break+reconnect (other_terminal) + if (used_terminals.contains(t)) + continue; + QPointF t_dock = t->dockConductor(); + //Collect all conductors that pass through this dock point. + struct ConductorMatch { + Conductor *conductor; + Terminal *connect_to; //endpoint "before" the dock point (based on orientation) + Terminal *other; //endpoint "after" the dock point + }; + QList all_matches; + foreach (Conductor *c, m_diagram->conductors()) { //Skip conductors we already handled or connected to the new element @@ -286,8 +298,6 @@ void DiagramEventAddElement::addElement() continue; //Check if dock point lies on the conductor path. - //Convert dock_point to the conductor's local coordinate system, - //because c->path() is in local coordinates (generated via mapFromScene). QPointF local_dock = c->mapFromScene(t_dock); bool point_on_conductor = false; QPainterPath path = c->path(); @@ -311,23 +321,11 @@ void DiagramEventAddElement::addElement() if (!point_on_conductor) continue; - //The terminal lies on this conductor. - //Break it: delete old conductor, create one new conductor from the - //aligned endpoint to the new terminal. The other endpoint is left - //for auto-connect to handle (e.g. connecting to the opposite terminal - //of the new element). Terminal *c1 = c->terminal1; Terminal *c2 = c->terminal2; - - conductors_handled.append(c); - - //Get scene positions for endpoint selection QPointF c1_dock = c1->dockConductor(); QPointF c2_dock = c2->dockConductor(); - //Determine which endpoint to connect based on terminal orientation. - //Terminal::orientation() already accounts for element rotation, - //so a North terminal rotated 90° returns East, etc. Terminal *connect_to = nullptr; Terminal *other = nullptr; @@ -350,7 +348,6 @@ void DiagramEventAddElement::addElement() break; } - //Fallback: use nearest endpoint if (!connect_to) { qreal d1 = QLineF(t_dock, c1_dock).length(); qreal d2 = QLineF(t_dock, c2_dock).length(); @@ -358,27 +355,58 @@ void DiagramEventAddElement::addElement() else { connect_to = c2; other = c1; } } - //Delete the old conductor + all_matches.append({c, connect_to, other}); + } + + if (all_matches.isEmpty()) + continue; + + //Find the best match (closest connect_to endpoint). + const ConductorMatch &best = *std::min_element(all_matches.constBegin(), all_matches.constEnd(), + [&](const ConductorMatch &a, const ConductorMatch &b) { + return QLineF(t_dock, a.connect_to->dockConductor()).length() + < QLineF(t_dock, b.connect_to->dockConductor()).length(); + }); + + //Only break conductors that share the same "other" endpoint as the best match. + //This prevents bridging independent nets: if two unrelated conductors + //cross at a dock point, only the one belonging to the same circuit + //(same other endpoint) gets broken. The other is left untouched. + QList matches; + for (const auto &m : all_matches) { + if (m.other == best.other) + matches.append(m); + } + + //Mark terminal as used + used_terminals.insert(t); + + //Delete all matched conductors in one batch DiagramContent content; - content.m_other_conductors.append(c); + for (const auto &m : matches) { + content.m_other_conductors.append(m.conductor); + conductors_handled.append(m.conductor); + } new DeleteQGraphicsItemCommand(m_diagram, content, undo_object); - //Create new conductor from the aligned endpoint to the new terminal - Conductor *new_c = new Conductor(connect_to, t); - new AddGraphicsObjectCommand(new_c, m_diagram, QPointF(), undo_object); + //Create new conductors from each connect_to endpoint to this terminal. + //This creates junctions at the terminal when multiple conductors + //from the same circuit pass through the dock point (e.g. left and + //right conductors going to the same terminal strip terminal). + for (const auto &m : matches) { + Conductor *new_c = new Conductor(m.connect_to, t); + new AddGraphicsObjectCommand(new_c, m_diagram, QPointF(), undo_object); ConductorAutoNumerotation can(new_c, m_diagram, undo_object); can.numerate(); if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) new_c->setFreezeLabel(true); - broken_endpoints.insert(connect_to); - used_terminals.insert(t); + broken_endpoints.insert(m.connect_to); + } - //Also connect the 'other' endpoint to preserve bent conductor segments. - //For L-shaped conductors (e.g. horizontal + vertical), the 'other' endpoint - //may be far from the new element. Find the nearest free terminal of the new - //element and create a conductor to it. - QPointF other_dock = other->dockConductor(); + //Connect the shared "other" endpoint to the nearest free terminal + //with matching orientation. + QPointF other_dock = best.other->dockConductor(); Terminal *other_terminal = nullptr; qreal best_dist = std::numeric_limits::max(); foreach (Terminal *ot, element->terminals()) @@ -386,7 +414,20 @@ void DiagramEventAddElement::addElement() if (used_terminals.contains(ot)) continue; - qreal dist = QLineF(ot->dockConductor(), other_dock).length(); + //Check that the other_dock approaches from the correct direction + //relative to the candidate terminal's orientation. + QPointF ot_dock = ot->dockConductor(); + bool orientation_ok = false; + switch (ot->orientation()) { + case Qet::North: orientation_ok = other_dock.y() < ot_dock.y(); break; + case Qet::South: orientation_ok = other_dock.y() > ot_dock.y(); break; + case Qet::East: orientation_ok = other_dock.x() > ot_dock.x(); break; + case Qet::West: orientation_ok = other_dock.x() < ot_dock.x(); break; + } + if (!orientation_ok) + continue; + + qreal dist = QLineF(ot_dock, other_dock).length(); if (dist < best_dist) { best_dist = dist; other_terminal = ot; @@ -394,17 +435,16 @@ void DiagramEventAddElement::addElement() } if (other_terminal) { - Conductor *new_c2 = new Conductor(other, other_terminal); + Conductor *new_c2 = new Conductor(best.other, other_terminal); new AddGraphicsObjectCommand(new_c2, m_diagram, QPointF(), undo_object); ConductorAutoNumerotation can2(new_c2, m_diagram, undo_object); can2.numerate(); if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) new_c2->setFreezeLabel(true); - broken_endpoints.insert(other); + broken_endpoints.insert(best.other); used_terminals.insert(other_terminal); } - } } } From 5ec49eeddae2cf868be35655b611f82b89bd58a4 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Mon, 3 Aug 2026 21:48:34 +0200 Subject: [PATCH 006/350] fix bug 2 --- .../diagramevent/diagrameventaddelement.cpp | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index 9e8648f7d..e8f0f8635 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -361,22 +361,27 @@ void DiagramEventAddElement::addElement() if (all_matches.isEmpty()) continue; - //Find the best match (closest connect_to endpoint). - const ConductorMatch &best = *std::min_element(all_matches.constBegin(), all_matches.constEnd(), - [&](const ConductorMatch &a, const ConductorMatch &b) { - return QLineF(t_dock, a.connect_to->dockConductor()).length() - < QLineF(t_dock, b.connect_to->dockConductor()).length(); - }); - - //Only break conductors that share the same "other" endpoint as the best match. - //This prevents bridging independent nets: if two unrelated conductors - //cross at a dock point, only the one belonging to the same circuit - //(same other endpoint) gets broken. The other is left untouched. - QList matches; + //Group matches by their "other" endpoint and find the largest group. + //This ensures that when multiple independent circuits cross at the + //same dock point, the group with the most conductors gets priority, + //not whichever happens to have the nearest connect_to endpoint. + QMap> groups; for (const auto &m : all_matches) { - if (m.other == best.other) - matches.append(m); + groups[m.other].append(m); } + Terminal *best_other = nullptr; + int best_count = 0; + for (auto it = groups.constBegin(); it != groups.constEnd(); ++it) { + if (it.value().size() > best_count) { + best_count = it.value().size(); + best_other = it.key(); + } + } + + //Only break conductors in the largest group (same "other" endpoint). + //This prevents bridging independent nets: if two unrelated conductors + //cross at a dock point, only the larger group gets broken. + const QList &matches = groups[best_other]; //Mark terminal as used used_terminals.insert(t); @@ -406,7 +411,7 @@ void DiagramEventAddElement::addElement() //Connect the shared "other" endpoint to the nearest free terminal //with matching orientation. - QPointF other_dock = best.other->dockConductor(); + QPointF other_dock = best_other->dockConductor(); Terminal *other_terminal = nullptr; qreal best_dist = std::numeric_limits::max(); foreach (Terminal *ot, element->terminals()) @@ -435,14 +440,14 @@ void DiagramEventAddElement::addElement() } if (other_terminal) { - Conductor *new_c2 = new Conductor(best.other, other_terminal); + Conductor *new_c2 = new Conductor(best_other, other_terminal); new AddGraphicsObjectCommand(new_c2, m_diagram, QPointF(), undo_object); ConductorAutoNumerotation can2(new_c2, m_diagram, undo_object); can2.numerate(); if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) new_c2->setFreezeLabel(true); - broken_endpoints.insert(best.other); + broken_endpoints.insert(best_other); used_terminals.insert(other_terminal); } } From 29ba7c96368120cd7ce511e5595a8417dead5735 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Tue, 4 Aug 2026 10:32:25 +1200 Subject: [PATCH 007/350] Remember last-used shape/text style for new items this session Drawing tools on the diagram canvas always started new shapes and free text from a fixed hardcoded default (Qt's plain QPen()/QBrush(), and the static Preferences font) -- changing a shape's color or a text's font had zero effect on what the next new item of that type got, even within the same editing session. Add LastUsedStyle: a small in-memory, session-scoped static helper (no QSettings, no persistence across restarts -- this is a live "what did I just use" value, not a new app-wide default). Write side hooks capture the value right where the properties editors already apply a change (ShapeGraphicsItemPropertiesWidget::associatedUndo(), both the live-edit dock path and the modal editProperty() dialog path; and IndiTextPropertiesWidget::on_m_font_pb_clicked() right after the font dialog returns). Read side hooks apply the stored value, if any, to a newly created item: DiagramEventAddShape::mousePressEvent for shapes, IndependentTextItem's constructor for free text (falling back to the existing QETApp::indiTextsItemFont() Preferences default otherwise). Doesn't touch the element/symbol editor's own drawing tools (a separate subsystem) or add last-used text color (no color control exists in the text properties UI to originate it from yet). --- cmake/qet_compilation_vars.cmake | 2 + sources/diagramevent/diagrameventaddshape.cpp | 9 ++ sources/lastusedstyle.cpp | 106 ++++++++++++++++++ sources/lastusedstyle.h | 63 +++++++++++ .../qetgraphicsitem/independenttextitem.cpp | 6 +- sources/ui/inditextpropertieswidget.cpp | 2 + .../ui/shapegraphicsitempropertieswidget.cpp | 5 + 7 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 sources/lastusedstyle.cpp create mode 100644 sources/lastusedstyle.h diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake index 57a012916..0a81ce8d2 100644 --- a/cmake/qet_compilation_vars.cmake +++ b/cmake/qet_compilation_vars.cmake @@ -205,6 +205,8 @@ set(QET_SRC_FILES ${QET_DIR}/sources/exportpropertieswidget.h ${QET_DIR}/sources/genericpanel.cpp ${QET_DIR}/sources/genericpanel.h + ${QET_DIR}/sources/lastusedstyle.cpp + ${QET_DIR}/sources/lastusedstyle.h ${QET_DIR}/sources/machine_info.cpp ${QET_DIR}/sources/machine_info.h ${QET_DIR}/sources/main.cpp diff --git a/sources/diagramevent/diagrameventaddshape.cpp b/sources/diagramevent/diagrameventaddshape.cpp index 8a5f0967c..0ab945266 100644 --- a/sources/diagramevent/diagrameventaddshape.cpp +++ b/sources/diagramevent/diagrameventaddshape.cpp @@ -18,6 +18,7 @@ #include "diagrameventaddshape.h" #include "../diagram.h" +#include "../lastusedstyle.h" #include "../undocommand/addgraphicsobjectcommand.h" /** @@ -77,6 +78,14 @@ void DiagramEventAddShape::mousePressEvent(QGraphicsSceneMouseEvent *event) if (!m_shape_item) { m_shape_item = new QetShapeItem(pos, pos, m_shape_type); + //Start from whatever pen/brush was last applied this + //session, rather than always the hardcoded default. + if (LastUsedStyle::hasShapePen()) { + m_shape_item->setPen(LastUsedStyle::shapePen()); + } + if (LastUsedStyle::hasShapeBrush()) { + m_shape_item->setBrush(LastUsedStyle::shapeBrush()); + } m_diagram->addItem (m_shape_item); event->setAccepted(true); return; diff --git a/sources/lastusedstyle.cpp b/sources/lastusedstyle.cpp new file mode 100644 index 000000000..0dad351a8 --- /dev/null +++ b/sources/lastusedstyle.cpp @@ -0,0 +1,106 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "lastusedstyle.h" + +QPen LastUsedStyle::m_shape_pen; +bool LastUsedStyle::m_has_shape_pen = false; +QBrush LastUsedStyle::m_shape_brush; +bool LastUsedStyle::m_has_shape_brush = false; +QFont LastUsedStyle::m_text_font; +bool LastUsedStyle::m_has_text_font = false; + +/** + @return true if a shape pen was set this session +*/ +bool LastUsedStyle::hasShapePen() +{ + return m_has_shape_pen; +} + +/** + @return the last pen applied to a shape this session +*/ +QPen LastUsedStyle::shapePen() +{ + return m_shape_pen; +} + +/** + @brief LastUsedStyle::setShapePen + Record @a pen as the last-used shape pen for this session + @param pen +*/ +void LastUsedStyle::setShapePen(const QPen &pen) +{ + m_shape_pen = pen; + m_has_shape_pen = true; +} + +/** + @return true if a shape brush was set this session +*/ +bool LastUsedStyle::hasShapeBrush() +{ + return m_has_shape_brush; +} + +/** + @return the last brush applied to a shape this session +*/ +QBrush LastUsedStyle::shapeBrush() +{ + return m_shape_brush; +} + +/** + @brief LastUsedStyle::setShapeBrush + Record @a brush as the last-used shape brush for this session + @param brush +*/ +void LastUsedStyle::setShapeBrush(const QBrush &brush) +{ + m_shape_brush = brush; + m_has_shape_brush = true; +} + +/** + @return true if a text font was set this session +*/ +bool LastUsedStyle::hasTextFont() +{ + return m_has_text_font; +} + +/** + @return the last font applied to a free text item this session +*/ +QFont LastUsedStyle::textFont() +{ + return m_text_font; +} + +/** + @brief LastUsedStyle::setTextFont + Record @a font as the last-used free text font for this session + @param font +*/ +void LastUsedStyle::setTextFont(const QFont &font) +{ + m_text_font = font; + m_has_text_font = true; +} diff --git a/sources/lastusedstyle.h b/sources/lastusedstyle.h new file mode 100644 index 000000000..17c1f50b3 --- /dev/null +++ b/sources/lastusedstyle.h @@ -0,0 +1,63 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef LAST_USED_STYLE_H +#define LAST_USED_STYLE_H + +#include +#include +#include + +/** + @brief The LastUsedStyle class + Session-scoped "last used" style for new shapes and free text created + on the diagram canvas: whatever pen/brush/font was last applied through + the properties editors becomes the starting point for the next new + item of that type, the way most drawing tools behave. + + Deliberately in-memory only, not QSettings-backed: this is a live + "what did I just use" value for the current editing session, not an + app-wide default (that's already covered by the Preferences dialog's + font setting, read as the fallback when nothing has been set yet). +*/ +class LastUsedStyle +{ + public: + static bool hasShapePen(); + static QPen shapePen(); + static void setShapePen(const QPen &pen); + + static bool hasShapeBrush(); + static QBrush shapeBrush(); + static void setShapeBrush(const QBrush &brush); + + static bool hasTextFont(); + static QFont textFont(); + static void setTextFont(const QFont &font); + + private: + LastUsedStyle() = delete; + + static QPen m_shape_pen; + static bool m_has_shape_pen; + static QBrush m_shape_brush; + static bool m_has_shape_brush; + static QFont m_text_font; + static bool m_has_text_font; +}; + +#endif // LAST_USED_STYLE_H diff --git a/sources/qetgraphicsitem/independenttextitem.cpp b/sources/qetgraphicsitem/independenttextitem.cpp index ba92533b8..36c5eb5d8 100644 --- a/sources/qetgraphicsitem/independenttextitem.cpp +++ b/sources/qetgraphicsitem/independenttextitem.cpp @@ -19,6 +19,7 @@ #include "../diagram.h" #include "../diagramcommands.h" +#include "../lastusedstyle.h" #include "../qet.h" #include "../qetapp.h" #include "../utils/qetutils.h" @@ -33,7 +34,10 @@ IndependentTextItem::IndependentTextItem() : DiagramTextItem(nullptr) { - setFont(QETApp::indiTextsItemFont()); + //Start from the font last applied to a text item this session, + //falling back to the app-wide Preferences default otherwise. + setFont(LastUsedStyle::hasTextFont() ? LastUsedStyle::textFont() + : QETApp::indiTextsItemFont()); QSettings settings; setRotation(settings.value("diagrameditor/independent_text_rotation", 0).toInt()); } diff --git a/sources/ui/inditextpropertieswidget.cpp b/sources/ui/inditextpropertieswidget.cpp index 45884a1cb..0ebe9ba15 100644 --- a/sources/ui/inditextpropertieswidget.cpp +++ b/sources/ui/inditextpropertieswidget.cpp @@ -20,6 +20,7 @@ #include "../QPropertyUndoCommand/qpropertyundocommand.h" #include "../diagram.h" #include "../diagramcommands.h" +#include "../lastusedstyle.h" #include "../qetgraphicsitem/independenttextitem.h" #include "../ui_inditextpropertieswidget.h" @@ -455,6 +456,7 @@ void IndiTextPropertiesWidget::on_m_font_pb_clicked() m_font_is_selected = true; ui->m_font_pb->setText(font.family()); ui->m_size_sb->setValue(font.pointSize()); + LastUsedStyle::setTextFont(m_selected_font); apply(); } else { ui->m_font_pb->setText(tr("Police")); diff --git a/sources/ui/shapegraphicsitempropertieswidget.cpp b/sources/ui/shapegraphicsitempropertieswidget.cpp index 242f1dd2f..5d4580321 100644 --- a/sources/ui/shapegraphicsitempropertieswidget.cpp +++ b/sources/ui/shapegraphicsitempropertieswidget.cpp @@ -20,6 +20,7 @@ #include "../QPropertyUndoCommand/qpropertyundocommand.h" #include "../diagram.h" +#include "../lastusedstyle.h" #include "../qetgraphicsitem/qetshapeitem.h" #include "../ui_shapegraphicsitempropertieswidget.h" @@ -180,6 +181,7 @@ QUndoCommand* ShapeGraphicsItemPropertiesWidget::associatedUndo() const { undo = new QPropertyUndoCommand(m_shape, "pen", old_pen, new_pen); undo->setText(tr("Modifier le trait d'une forme")); + LastUsedStyle::setShapePen(new_pen); } QBrush old_brush = m_shape->brush(); @@ -196,6 +198,7 @@ QUndoCommand* ShapeGraphicsItemPropertiesWidget::associatedUndo() const undo = new QPropertyUndoCommand(m_shape, "brush", old_brush, new_brush); undo->setText(tr("Modifier le remplissage d'une forme")); } + LastUsedStyle::setShapeBrush(new_brush); } if (ui->m_close_polygon->isChecked() != m_shape->isClosed()) @@ -321,6 +324,7 @@ QUndoCommand* ShapeGraphicsItemPropertiesWidget::associatedUndo() const if (new_pen != old_pen) { new QPropertyUndoCommand(m_shape, "pen", old_pen, new_pen, undo); + LastUsedStyle::setShapePen(new_pen); } QBrush old_brush = m_shape->brush(); @@ -330,6 +334,7 @@ QUndoCommand* ShapeGraphicsItemPropertiesWidget::associatedUndo() const if (new_brush != old_brush) { new QPropertyUndoCommand(m_shape, "brush", old_brush, new_brush, undo); + LastUsedStyle::setShapeBrush(new_brush); } if (ui->m_close_polygon->isChecked() != m_shape->isClosed()) { From 32dd686144f2af7abcd49e80853ad1576176a0e5 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Tue, 4 Aug 2026 18:51:22 +1200 Subject: [PATCH 008/350] Add "rotate group" to actually rotate a selection as a whole RotateSelectionCommand's existing "Pivoter" action (Space) only ever bumps each selected item's own rotation property -- QGraphicsItem's setRotation() spins an item around its own local origin and never touches pos(). Select three elements arranged in a row and rotate: each spins 90 degrees individually, but the row stays a row. That's "rotate each item," not "rotate the group." Add a rotate_as_group parameter to RotateSelectionCommand (default false, so the existing action and its one call site are unchanged). When set, it computes a shared pivot once -- the bounding-box center of the whole selection -- and queues a second, parallel "pos" QPropertyUndoCommand alongside the existing "rotation" one, rotating each item's position around that pivot by the same angle. Scoped the position change to Element/IndependentTextItem/ DiagramImageItem only: these are the only selectable types with scene-space pos(). ConductorTextItem, DynamicElementTextItem and ElementTextItemGroup are all parent-relative children (confirmed by reading their constructors), so when their owning Element is also selected and gets its own pos() rotated, they're carried along for free by Qt's normal parent/child transform propagation -- exactly what the existing "skip rotation if parent is also selected" guard already assumes for those three cases. Exposed as a new, separate action ("Pivoter le groupe", Shift+Space) next to the existing one rather than changing Space's behavior, since some workflows may rely on the current per-item rotation. --- sources/qetdiagrameditor.cpp | 12 ++++ sources/qetdiagrameditor.h | 1 + .../undocommand/rotateselectioncommand.cpp | 61 +++++++++++++++++-- sources/undocommand/rotateselectioncommand.h | 6 +- 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 5b2ba6779..199e923a2 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -628,6 +628,7 @@ void QETDiagramEditor::setUpActions() //Selections Actions (related to a selected item) m_delete_selection = m_selection_actions_group.addAction( QET::Icons::EditDelete, tr("Supprimer") ); m_rotate_selection = m_selection_actions_group.addAction( QET::Icons::TransformRotate, tr("Pivoter") ); + m_rotate_group_selection = m_selection_actions_group.addAction( QET::Icons::TransformRotate, tr("Pivoter le groupe") ); m_rotate_texts = m_selection_actions_group.addAction( QET::Icons::ObjectRotateRight, tr("Orienter les textes") ); m_find_element = m_selection_actions_group.addAction( QET::Icons::ZoomDraw, tr("Retrouver dans le panel") ); m_edit_selection = m_selection_actions_group.addAction( QET::Icons::ElementEdit, tr("Éditer l'item sélectionné") ); @@ -635,16 +636,19 @@ void QETDiagramEditor::setUpActions() ShortcutManager::instance().registerAction(m_delete_selection, "diagrameditor.delete_selection", tr("Éditeur de schémas"), Qt::Key_Delete); ShortcutManager::instance().registerAction(m_rotate_selection, "diagrameditor.rotate_selection", tr("Éditeur de schémas"), Qt::Key_Space); + ShortcutManager::instance().registerAction(m_rotate_group_selection, "diagrameditor.rotate_group_selection", tr("Éditeur de schémas"), Qt::SHIFT | Qt::Key_Space); ShortcutManager::instance().registerAction(m_rotate_texts, "diagrameditor.rotate_texts", tr("Éditeur de schémas"), Qt::CTRL | Qt::Key_Space); ShortcutManager::instance().registerAction(m_edit_selection, "diagrameditor.edit_selection", tr("Éditeur de schémas"), Qt::CTRL | Qt::Key_E); m_delete_selection->setStatusTip( tr("Enlève les éléments sélectionnés du folio", "status bar tip")); m_rotate_selection->setStatusTip( tr("Pivote les éléments et textes sélectionnés", "status bar tip")); + m_rotate_group_selection->setStatusTip( tr("Pivote la sélection comme un groupe autour de son centre, au lieu de chaque élément sur place", "status bar tip")); m_rotate_texts ->setStatusTip( tr("Pivote les textes sélectionnés à un angle précis", "status bar tip")); m_find_element ->setStatusTip( tr("Retrouve l'élément sélectionné dans le panel", "status bar tip")); m_delete_selection ->setData("delete_selection"); m_rotate_selection ->setData("rotate_selection"); + m_rotate_group_selection->setData("rotate_group_selection"); m_rotate_texts ->setData("rotate_selected_text"); m_find_element ->setData("find_selected_element"); m_edit_selection ->setData("edit_selected_element"); @@ -1601,6 +1605,12 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action) if(c->isValid()) diagram->undoStack().push(c); } + else if (value == "rotate_group_selection") + { + RotateSelectionCommand *c = new RotateSelectionCommand(diagram, 90, nullptr, true); + if(c->isValid()) + diagram->undoStack().push(c); + } else if (value == "rotate_selected_text") diagram->undoStack().push(new RotateTextsCommand(diagram)); else if (value == "find_selected_element" && currentElement()) @@ -1735,6 +1745,7 @@ void QETDiagramEditor::slot_updateComplexActions() << m_copy << m_delete_selection << m_rotate_selection + << m_rotate_group_selection << m_edit_selection << m_group_selected_texts; for(QAction *action : action_list) @@ -1763,6 +1774,7 @@ void QETDiagramEditor::slot_updateComplexActions() m_copy -> setEnabled(copiable_items); m_delete_selection -> setEnabled(!ro && deletable_items); m_rotate_selection -> setEnabled(!ro && diagram_->canRotateSelection()); + m_rotate_group_selection -> setEnabled(!ro && diagram_->canRotateSelection()); //Action that need selected texts or texts group QList texts = DiagramContent(diagram_).selectedTexts(); diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 0114a186e..ecc3b5164 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -216,6 +216,7 @@ class QETDiagramEditor : public QETMainWindow *m_edit_selection, ///< To edit selected item *m_delete_selection, ///< Delete selection *m_rotate_selection, ///< Rotate selected elements and text items by 90 degrees + *m_rotate_group_selection = nullptr, ///< Rotate the selection as a whole around its shared center, instead of each item in place *m_rotate_texts, ///< Direct selected text items to a specific angle *m_find_element, ///< Find the selected element in the panel *m_group_selected_texts = nullptr, diff --git a/sources/undocommand/rotateselectioncommand.cpp b/sources/undocommand/rotateselectioncommand.cpp index a3d3cc821..f893c5510 100644 --- a/sources/undocommand/rotateselectioncommand.cpp +++ b/sources/undocommand/rotateselectioncommand.cpp @@ -29,21 +29,37 @@ #include "../qetgraphicsitem/independenttextitem.h" #include +#include -RotateSelectionCommand::RotateSelectionCommand(Diagram *diagram, qreal angle, QUndoCommand *parent) : +RotateSelectionCommand::RotateSelectionCommand(Diagram *diagram, qreal angle, QUndoCommand *parent, bool rotate_as_group) : QUndoCommand(parent), m_diagram(diagram) { - setText(QObject::tr("Pivoter la selection")); - + setText(rotate_as_group ? QObject::tr("Pivoter le groupe") : QObject::tr("Pivoter la selection")); + if(!m_diagram->isReadOnly()) { + //Shared pivot for group rotation: the bounding-box center of + //everything selected, computed once up front from the + //selection as a whole (not just the items that end up being + //individually repositioned below). + QPointF pivot; + if (rotate_as_group) + { + QRectF bounding_rect; + for (QGraphicsItem *item : m_diagram->selectedItems()) + bounding_rect |= item->sceneBoundingRect(); + pivot = bounding_rect.center(); + } + for (QGraphicsItem *item : m_diagram->selectedItems()) { switch (item->type()) { case Element::Type: m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "rotation", QVariant(item->rotation()), QVariant(item->rotation()+angle), this); + if (rotate_as_group) + addGroupPositionUndo(item, pivot, angle); break; case ConductorTextItem::Type: { @@ -53,9 +69,19 @@ m_diagram(diagram) break; case IndependentTextItem::Type: m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "rotation", QVariant(item->rotation()), QVariant(item->rotation()+angle), this); + if (rotate_as_group) + addGroupPositionUndo(item, pivot, angle); break; case DynamicElementTextItem::Type: { + //No pos() undo here even in group mode: this item is + //only rotated in place when its parent Element isn't + //also selected (guard below), and its pos() is + //parent-local, not scene coordinates -- when the + //parent Element *is* selected and gets its own pos() + //rotated around the shared pivot above, this child + //text item is carried along for free by Qt's normal + //parent/child transform propagation. if(item->parentItem() && !item->parentItem()->isSelected()) m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "rotation", QVariant(item->rotation()), QVariant(item->rotation()+angle), this); } @@ -69,17 +95,44 @@ m_diagram(diagram) break; case DiagramImageItem::Type: m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "rotation", QVariant(item->rotation()), QVariant(item->rotation()+angle), this); + if (rotate_as_group) + addGroupPositionUndo(item, pivot, angle); break; default: break; } } - + for (QPropertyUndoCommand *undo : m_undo) undo->setAnimated(true, false); } } +/** + @brief RotateSelectionCommand::addGroupPositionUndo + Queue a "pos" QPropertyUndoCommand that rotates @a item's position + around @a pivot by @a angle degrees (Qt's clockwise-positive + convention, matching QGraphicsItem::setRotation() so a group + rotation turns the same direction as each item's own spin). + Only meaningful for items whose pos() is in scene coordinates + (Element, IndependentTextItem, DiagramImageItem) -- never call this + for a child item positioned relative to its own parent. + @param item : item to reposition, its own rotation undo already queued + @param pivot : shared pivot point, in scene coordinates + @param angle : rotation angle in degrees +*/ +void RotateSelectionCommand::addGroupPositionUndo(QGraphicsItem *item, const QPointF &pivot, qreal angle) +{ + const QPointF old_pos = item->pos(); + const qreal radians = qDegreesToRadians(angle); + const QPointF delta = old_pos - pivot; + const QPointF new_pos( + pivot.x() + delta.x() * qCos(radians) - delta.y() * qSin(radians), + pivot.y() + delta.x() * qSin(radians) + delta.y() * qCos(radians) + ); + m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "pos", QVariant(old_pos), QVariant(new_pos), this); +} + /** @brief RotateSelectionCommand::undo */ diff --git a/sources/undocommand/rotateselectioncommand.h b/sources/undocommand/rotateselectioncommand.h index abc75bcc9..df96fba96 100644 --- a/sources/undocommand/rotateselectioncommand.h +++ b/sources/undocommand/rotateselectioncommand.h @@ -21,10 +21,12 @@ #include #include #include +#include class Diagram; class ConductorTextItem; class QPropertyUndoCommand; +class QGraphicsItem; /** @brief The RotateSelectionCommand class @@ -33,13 +35,15 @@ class QPropertyUndoCommand; class RotateSelectionCommand : public QUndoCommand { public: - RotateSelectionCommand(Diagram *diagram, qreal angle=90, QUndoCommand *parent=nullptr); + RotateSelectionCommand(Diagram *diagram, qreal angle=90, QUndoCommand *parent=nullptr, bool rotate_as_group=false); void undo() override; void redo() override; bool isValid(); private: + void addGroupPositionUndo(QGraphicsItem *item, const QPointF &pivot, qreal angle); + Diagram *m_diagram =nullptr; QList> m_cond_text; From 06d1d70142a8d206487a8b94ecb80f09f0463d8d Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Tue, 4 Aug 2026 16:48:52 +0200 Subject: [PATCH 009/350] bug 2 --- .../diagramevent/diagrameventaddelement.cpp | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index e8f0f8635..2f018e28b 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -31,6 +31,34 @@ #include #include +namespace { + /** + @brief distanceToSegment + @param point : point to measure from + @param segment : the finite segment (not the infinite line through it) + @return the distance from @a point to the closest point actually on + @a segment. Unlike QET::orthogonalProjection(), which reports a hit + for any point on the segment's infinite extension, this clamps the + projection to the segment itself: a point collinear with a wire but + past its actual drawn end is correctly reported as far away, not "on" + the wire. + */ + qreal distanceToSegment(const QPointF &point, const QLineF &segment) + { + const QPointF a = segment.p1(); + const QPointF b = segment.p2(); + const QPointF ab = b - a; + const qreal len2 = QPointF::dotProduct(ab, ab); + + if (len2 <= 0.0) + return QLineF(point, a).length(); + + qreal t = QPointF::dotProduct(point - a, ab) / len2; + t = qBound(0.0, t, 1.0); + return QLineF(point, a + t * ab).length(); + } +} + /** @brief DiagramEventAddElement::DiagramEventAddElement Defaut constructor @@ -297,7 +325,9 @@ void DiagramEventAddElement::addElement() c->terminal2->parentElement() == element) continue; - //Check if dock point lies on the conductor path. + //Check if dock point lies on the conductor path. Distance is + //measured to the segment itself (clamped), not the infinite + //line through it -- see distanceToSegment(). QPointF local_dock = c->mapFromScene(t_dock); bool point_on_conductor = false; QPainterPath path = c->path(); @@ -306,15 +336,10 @@ void DiagramEventAddElement::addElement() const QPainterPath::Element &e1 = path.elementAt(i); const QPainterPath::Element &e2 = path.elementAt(i + 1); QLineF segment(QPointF(e1.x, e1.y), QPointF(e2.x, e2.y)); - QPointF projection; - if (QET::orthogonalProjection(local_dock, segment, &projection)) + if (distanceToSegment(local_dock, segment) < 5.0) { - qreal dist = QLineF(local_dock, projection).length(); - if (dist < 5.0) - { - point_on_conductor = true; - break; - } + point_on_conductor = true; + break; } } From e3d11a499223251afd75ca7600d26e771364d244 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Wed, 5 Aug 2026 05:26:57 +1200 Subject: [PATCH 010/350] Fix command-line tools hanging forever on a modal message box `qelectrotech --resave examples/schema_indus.qet out.qet` never returns. It is not slow -- ten minutes of wall clock consumed 0.16s of CPU, so it is blocked, not working. The GUI opens the same project without complaint, so the file is fine and the fault is in the headless path. A backtrace of the stuck process: main CLIExport::run QETProject::QETProject(QString const&, QObject*) QETProject::openFile(QFile*) QETProject::readProjectXml(QDomDocument&) QET::QetMessageBox::warning(...) QDialog::exec() <- waits forever That project records version="0.3", so loading it raises the "partially compatible with your version" warning. Interactively somebody presses Open; with no display nobody can, and exec() spins its event loop indefinitely. Any modal box reachable while loading does this -- the version warning is just the one an example file happens to trigger. Fixed at the wrapper all 52 call sites already go through rather than at the one warning, so the whole class is closed: QetMessageBox gains a non-interactive mode which writes the message to stderr and returns an answer instead of constructing a dialog. main.cpp turns it on in the CLI branch, beside the existing setBackupEnabled(false). The answer is the caller's defaultButton when it gave one, otherwise the first "carry on" button offered (Ok, Open, Yes, Save...), otherwise the first button set. Both warnings in readProjectXml offer Open|Cancel and abort on Cancel, so they resolve to Open and the project loads, which is what a batch invocation wants. The text still reaches the user on stderr, where previously it was lost inside an invisible dialog. GUI behaviour is unchanged: the flag defaults to false and is set in exactly one place, the command-line branch of main(). Verified: schema_indus.qet goes from hanging to resaving in 0.3s; all 23 example projects now complete a double-resave with element, conductor, terminal and uuid sets intact; unit tests pass. --- sources/main.cpp | 6 +++ sources/qetmessagebox.cpp | 90 +++++++++++++++++++++++++++++++++++++++ sources/qetmessagebox.h | 22 ++++++++++ 3 files changed, 118 insertions(+) diff --git a/sources/main.cpp b/sources/main.cpp index eede1bfb8..e723d0d43 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -19,6 +19,7 @@ #include "machine_info.h" #include "qet.h" #include "qetapp.h" +#include "qetmessagebox.h" #include "qetproject.h" #include "singleapplication.h" #include "utils/qetsettings.h" @@ -249,6 +250,11 @@ QGuiApplication::setHighDpiScaleFactorRoundingPolicy(QetSettings::hdpiScaleFacto // runs on a background thread referencing the project and races the // process exit (intermittent segfault in QET::writeToFile). QETProject::setBackupEnabled(false); + // Answer message boxes instead of showing them: opening a project + // saved by an older QElectroTech raises a warning from + // QETProject::readProjectXml(), and with nobody able to dismiss it + // QDialog::exec() would spin its event loop forever. + QET::QetMessageBox::setNonInteractive(true); return CLIExport::run(export_app.arguments()); } } diff --git a/sources/qetmessagebox.cpp b/sources/qetmessagebox.cpp index 31d6e41a8..2731baf00 100644 --- a/sources/qetmessagebox.cpp +++ b/sources/qetmessagebox.cpp @@ -17,6 +17,84 @@ */ #include "qetmessagebox.h" +#include + +namespace { + bool g_non_interactive = false; + + /** + @brief autoAnswer + Report a message box on stderr and pick an answer, for use when there + is no user to click anything. @see QET::QetMessageBox::setNonInteractive + @param severity : short word naming the kind of box, for the log line + @param title + @param text + @param buttons : the buttons the caller offered + @param defaultButton : the caller's preferred answer, may be NoButton + @return the button to report as pressed + */ + QMessageBox::StandardButton autoAnswer( + const char *severity, + const QString &title, + const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) + { + //Honour the caller's own default when it named one. + if (defaultButton != QMessageBox::NoButton + && (buttons & defaultButton)) { + QTextStream(stderr) << severity << ": " << title << " -- " << text + << "\n(no display: answered with the caller's default button)\n"; + return defaultButton; + } + + //Otherwise prefer a "carry on" answer over one that cancels, so a + //batch run completes rather than silently doing nothing. + static const QMessageBox::StandardButton preference[] = { + QMessageBox::Ok, QMessageBox::Open, QMessageBox::Yes, + QMessageBox::Save, QMessageBox::Apply, QMessageBox::YesToAll, + QMessageBox::Retry, QMessageBox::Ignore, QMessageBox::Close + }; + for (auto candidate : preference) { + if (buttons & candidate) { + QTextStream(stderr) << severity << ": " << title << " -- " << text + << "\n(no display: continuing)\n"; + return candidate; + } + } + + //Nothing affirmative on offer -- fall back to whatever is set. + for (int bit = QMessageBox::Ok; bit <= QMessageBox::RestoreDefaults; bit <<= 1) { + auto candidate = static_cast(bit); + if (buttons & candidate) { + QTextStream(stderr) << severity << ": " << title << " -- " << text + << "\n(no display: answered automatically)\n"; + return candidate; + } + } + + QTextStream(stderr) << severity << ": " << title << " -- " << text + << "\n(no display: no button offered)\n"; + return QMessageBox::NoButton; + } +} + +/** + @brief QET::QetMessageBox::setNonInteractive + @param non_interactive +*/ +void QET::QetMessageBox::setNonInteractive(bool non_interactive) { + g_non_interactive = non_interactive; +} + +/** + @brief QET::QetMessageBox::isNonInteractive + @return true when message boxes are answered without a user +*/ +bool QET::QetMessageBox::isNonInteractive() { + return g_non_interactive; +} + /** @see Documentation Qt pour QMessageBox::critical */ @@ -27,6 +105,9 @@ QMessageBox::StandardButton QET::QetMessageBox::critical ( QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { + if (g_non_interactive) { + return autoAnswer("Critical", title, text, buttons, defaultButton); + } #ifdef Q_OS_MACOS QMessageBox message_box( QMessageBox::Critical, @@ -59,6 +140,9 @@ QMessageBox::StandardButton QET::QetMessageBox::information( QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { + if (g_non_interactive) { + return autoAnswer("Information", title, text, buttons, defaultButton); + } #ifdef Q_OS_MACOS QMessageBox message_box( QMessageBox::Information, @@ -91,6 +175,9 @@ QMessageBox::StandardButton QET::QetMessageBox::question ( QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { + if (g_non_interactive) { + return autoAnswer("Question", title, text, buttons, defaultButton); + } #ifdef Q_OS_MACOS QMessageBox message_box( QMessageBox::Question, @@ -123,6 +210,9 @@ QMessageBox::StandardButton QET::QetMessageBox::warning ( QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { + if (g_non_interactive) { + return autoAnswer("Warning", title, text, buttons, defaultButton); + } #ifdef Q_OS_MACOS QMessageBox message_box( QMessageBox::Warning, diff --git a/sources/qetmessagebox.h b/sources/qetmessagebox.h index 60238595a..6e838f4e4 100644 --- a/sources/qetmessagebox.h +++ b/sources/qetmessagebox.h @@ -27,6 +27,28 @@ namespace QET { Qt:Sheet flag, thus enabling a better MacOS integration. */ namespace QetMessageBox { + /** + Enable non-interactive mode. + + In non-interactive mode the functions below never construct a + dialog. They write the message to stderr and return an answer + immediately, so a headless run cannot block on a modal box that + nobody is there to dismiss. + + This is needed because these are reachable from the command-line + tools: opening a project written by an older QElectroTech raises + a warning from QETProject::readProjectXml(), and with no display + to click it, QDialog::exec() spins its event loop forever. + + The answer is chosen as: the caller's defaultButton when it gave + one, otherwise the first "carry on" button among those offered + (Ok, Open, Yes, Save, Apply...), otherwise the first button set. + So the two warnings above resolve to Open and the project loads, + which is what a batch invocation wants. + */ + void setNonInteractive(bool non_interactive); + bool isNonInteractive(); + QMessageBox::StandardButton critical ( QWidget *, const QString &, From 1216855cfa5407523e07130cfc4a2256fad20c2f Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Tue, 4 Aug 2026 23:10:18 +0200 Subject: [PATCH 011/350] Fix broken auto-numbering conductor/element/folio selection in project properties connect() used the string-based currentIndexChanged(QString) signal, which was removed from QComboBox in Qt6. Selecting a conductor/element/folio auto-numbering context in the combo box in the project properties dialog never updated the other fields. Switch to currentTextChanged with the modern pointer-to-member connect() syntax, which also catches signal/slot mismatches at compile time. This is still backward compatible with Qt5 (as long as this is needed). --- sources/ui/configpage/projectconfigpages.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/ui/configpage/projectconfigpages.cpp b/sources/ui/configpage/projectconfigpages.cpp index e4fcb69ef..c1143cffa 100644 --- a/sources/ui/configpage/projectconfigpages.cpp +++ b/sources/ui/configpage/projectconfigpages.cpp @@ -396,17 +396,17 @@ void ProjectAutoNumConfigPage::buildConnections() //Conductor Tab connect(m_saw_conductor, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextConductor); connect(m_saw_conductor, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextConductor); - connect(m_saw_conductor->contextComboBox(), SIGNAL(currentIndexChanged(QString)), this, SLOT(updateContextConductor(QString))); + connect(m_saw_conductor->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextConductor); //Element Tab connect(m_saw_element, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextElement); connect(m_saw_element, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextElement); - connect(m_saw_element->contextComboBox(), SIGNAL(currentIndexChanged(QString)), this, SLOT(updateContextElement(QString))); + connect(m_saw_element->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextElement); //Folio Tab connect(m_saw_folio, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextFolio); connect(m_saw_folio, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextFolio); - connect(m_saw_folio->contextComboBox(), SIGNAL(currentIndexChanged(QString)), this, SLOT(updateContextFolio(QString))); + connect(m_saw_folio->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextFolio); // Auto Folio Numbering connect (m_faw, SIGNAL (applyPressed()), this, SLOT (applyAutoNum())); From fb51489436b2b2e6cc0f6a083cb4fd3daf9d171d Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Wed, 5 Aug 2026 09:39:15 +0200 Subject: [PATCH 012/350] Fix of previous commit: use textActivated signal instead. --- sources/ui/configpage/projectconfigpages.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sources/ui/configpage/projectconfigpages.cpp b/sources/ui/configpage/projectconfigpages.cpp index c1143cffa..f12df6866 100644 --- a/sources/ui/configpage/projectconfigpages.cpp +++ b/sources/ui/configpage/projectconfigpages.cpp @@ -396,17 +396,29 @@ void ProjectAutoNumConfigPage::buildConnections() //Conductor Tab connect(m_saw_conductor, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextConductor); connect(m_saw_conductor, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextConductor); - connect(m_saw_conductor->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextConductor); + #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(m_saw_conductor->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextConductor); + #else // TODO Qt6 only: remove, textActivated() always available + connect(m_saw_conductor->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextConductor(QString))); + #endif //Element Tab connect(m_saw_element, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextElement); connect(m_saw_element, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextElement); - connect(m_saw_element->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextElement); + #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(m_saw_element->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextElement); + #else // TODO Qt6 only: remove, textActivated() always available + connect(m_saw_element->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextElement(QString))); + #endif //Folio Tab connect(m_saw_folio, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextFolio); connect(m_saw_folio, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextFolio); - connect(m_saw_folio->contextComboBox(), &QComboBox::currentTextChanged, this, &ProjectAutoNumConfigPage::updateContextFolio); + #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + connect(m_saw_folio->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextFolio); + #else // TODO Qt6 only: remove, textActivated() always available + connect(m_saw_folio->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextFolio(QString))); + #endif // Auto Folio Numbering connect (m_faw, SIGNAL (applyPressed()), this, SLOT (applyAutoNum())); From ab61e00cdf85b641584fcc19e516b9c3d766188e Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Wed, 5 Aug 2026 10:29:31 +0200 Subject: [PATCH 013/350] Fix QSignalMapper connects silently broken under Qt6 (using the old string based system). QSignalMapper::mapped(int/QWidget*) was deprecated in Qt 5.15 and removed in Qt6, replaced by mappedInt/mappedWidget/mappedString. What was broken: * the logo-conflict rename dialog * the system tray show/hide toggle * the Window menu * export dialog's per-diagram preview controls Switched to the modern mappedInt/mappedWidget signals with pointer-to-member connect(), guarded for Qt < 5.15 until Qt5 can be dropped. --- sources/exportdialog.cpp | 19 ++++++++++++++----- sources/qetapp.cpp | 7 +++++-- sources/qetdiagrameditor.cpp | 4 ++++ sources/titleblock/templatelogomanager.cpp | 4 ++++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sources/exportdialog.cpp b/sources/exportdialog.cpp index 3298ad44c..b736aa240 100644 --- a/sources/exportdialog.cpp +++ b/sources/exportdialog.cpp @@ -140,12 +140,21 @@ QWidget *ExportDialog::initDiagramsListPart() reset_mapper_ = new QSignalMapper(this); clipboard_mapper_ = new QSignalMapper(this); - connect(preview_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_previewDiagram(int))); - connect(width_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctHeight(int))); - connect(height_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctWidth(int))); - connect(ratio_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_keepRatioChanged(int))); - connect(reset_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_resetSize(int))); + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect(preview_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_previewDiagram); + connect(width_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctHeight); + connect(height_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctWidth); + connect(ratio_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_keepRatioChanged); + connect(reset_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_resetSize); + connect(clipboard_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_exportToClipBoard); + #else // TODO Qt6 only: remove, mappedInt() always available + connect(preview_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_previewDiagram(int))); + connect(width_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctHeight(int))); + connect(height_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctWidth(int))); + connect(ratio_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_keepRatioChanged(int))); + connect(reset_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_resetSize(int))); connect(clipboard_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_exportToClipBoard(int))); + #endif diagrams_list_layout_ = new QGridLayout(); diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index 8545f99e7..26d0b4cd6 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -122,8 +122,11 @@ QETApp::QETApp() : initSplashScreen(); initSystemTray(); - connect(&signal_map, SIGNAL(mapped(QWidget *)), - this, SLOT(invertMainWindowVisibility(QWidget *))); + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect(&signal_map, &QSignalMapper::mappedObject, this, [this](QObject *object) { invertMainWindowVisibility(qobject_cast(object)); }); + #else // TODO Qt6 only: remove, mappedObject() always available + connect(&signal_map, SIGNAL(mapped(QWidget *)), this, SLOT(invertMainWindowVisibility(QWidget *))); + #endif qApp->setQuitOnLastWindowClosed(false); connect(qApp, &QApplication::lastWindowClosed, this, &QETApp::checkRemainingWindows); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 5b2ba6779..208d36817 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -107,7 +107,11 @@ QETDiagramEditor::QETDiagramEditor(const QStringList &files, QWidget *parent) : m_workspace.setTabsClosable(true); //Set the signal mapper + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect(&windowMapper, &QSignalMapper::mappedObject, this, [this](QObject *object) { activateWidget(qobject_cast(object)); }); + #else // TODO Qt6 only: remove, mappedObject() always available connect(&windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(activateWidget(QWidget *))); + #endif setWindowTitle(tr("QElectroTech", "window title")); setWindowIcon(QET::Icons::QETLogo); diff --git a/sources/titleblock/templatelogomanager.cpp b/sources/titleblock/templatelogomanager.cpp index 9cd08befb..8b4d04cd4 100644 --- a/sources/titleblock/templatelogomanager.cpp +++ b/sources/titleblock/templatelogomanager.cpp @@ -217,7 +217,11 @@ QString TitleBlockTemplateLogoManager::confirmLogoName(const QString &initial_na connect(replace_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); connect(rename_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); connect(cancel_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); + #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + connect(signal_mapper, &QSignalMapper::mappedInt, rename_dialog, &QDialog::done); + #else // TOD Qt6 only: remove, mappedInt() always available connect(signal_mapper, SIGNAL(mapped(int)), rename_dialog, SLOT(done(int))); + #endif } rd_label -> setText( QString(tr( From ee36073428b6f9a4e37012fa442baea4f01df803 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Wed, 5 Aug 2026 10:54:31 +0200 Subject: [PATCH 014/350] Fix DiagramView window title not updating (missed rename from 27dcd5e) 27dcd5e renamed BorderTitleBlock::diagramTitleChanged to informationChanged and updated diagram.cpp accordingly, but diagramview.cpp still used the old string-based SIGNAL()/SLOT() macro referencing the removed signal name, which failed silently at runtime instead of at compile time. The diagram/window title never refreshed after title block changes. Observed when going through the warnings. Updated the connect to use informationChanged with modern pointer-to-member syntax, matching diagram.cpp's own connect to the same signal. --- sources/diagramview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 3d82ca7f4..427ad0634 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -100,7 +100,7 @@ DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : connect(m_diagram, SIGNAL(showDiagram(Diagram*)), this, SIGNAL(showDiagram(Diagram*))); connect(m_diagram, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(adjustSceneRect())); - connect(&(m_diagram -> border_and_titleblock), SIGNAL(diagramTitleChanged(const QString &)), this, SLOT(updateWindowTitle())); + connect(&(m_diagram -> border_and_titleblock), &BorderTitleBlock::informationChanged, this, &DiagramView::updateWindowTitle); connect(diagram, SIGNAL(findElementRequired(ElementsLocation)), this, SIGNAL(findElementRequired(ElementsLocation))); QShortcut *edit_conductor_color_shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this); From 484ab9ed87faaae54535490f0f1027d20104630e Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Wed, 5 Aug 2026 12:17:49 +0200 Subject: [PATCH 015/350] Fix folio auto-num context not applying to the active diagram BorderTitleBlock::slot_setAutoPageNum was removed in 471f876 ("Remove unused signal", 2023-10-17) without noticing autonumberingdockwidget.cpp still referenced it via old-style SIGNAL()/SLOT() macros, which fail silently at runtime instead of producing a compile error. This has remained broken on master ever since; a fix (57572a2, "Fix two broken signal connections") exists on the unmerged qt6-cmake-elevatormind-merged branch but that one only commented the lines out without solving the underlying issue. Removed the dead code entirely and call BorderTitleBlock::importTitleBlock() directly on the active diagram in on_m_folio_cb_activated() instead. The same mechanism is already used elsewhere in the codebase (undo command, new-diagram creation, XML loading) to push TitleBlockProperties into a diagram and trigger a folio numbering recompute via needFolioData(). --- sources/autoNum/ui/autonumberingdockwidget.cpp | 12 +++--------- sources/autoNum/ui/autonumberingdockwidget.h | 2 -- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/sources/autoNum/ui/autonumberingdockwidget.cpp b/sources/autoNum/ui/autonumberingdockwidget.cpp index 664a00e90..a01cc538f 100644 --- a/sources/autoNum/ui/autonumberingdockwidget.cpp +++ b/sources/autoNum/ui/autonumberingdockwidget.cpp @@ -107,10 +107,6 @@ void AutoNumberingDockWidget::setProject(QETProject *project, this,SLOT(folioAutoNumChanged())); disconnect (m_project,SIGNAL(folioAutoNumAdded()), this,SLOT(folioAutoNumChanged())); - disconnect (this, - SIGNAL(folioAutoNumChanged(QString)), - &m_project_view->currentDiagram()->diagram()->border_and_titleblock, - SLOT (slot_setAutoPageNum(QString))); disconnect(m_project, SIGNAL(defaultTitleBlockPropertiesChanged()), this,SLOT(setActive())); @@ -146,10 +142,6 @@ void AutoNumberingDockWidget::setProject(QETProject *project, this,SLOT(folioAutoNumChanged())); connect (m_project,SIGNAL(folioAutoNumAdded()), this,SLOT(folioAutoNumChanged())); - connect (this, - SIGNAL(folioAutoNumChanged(QString)), - &m_project_view->currentDiagram()->diagram()->border_and_titleblock, - SLOT (slot_setAutoPageNum(QString))); connect(m_project, SIGNAL(defaultTitleBlockPropertiesChanged()), this,SLOT(setActive())); @@ -345,7 +337,9 @@ void AutoNumberingDockWidget::on_m_folio_cb_activated(int) { ip.folio = "%id/%total"; m_project->setDefaultTitleBlockProperties(ip); } - emit(folioAutoNumChanged(current_autonum)); + if (m_project_view && m_project_view->currentDiagram()) { + m_project_view->currentDiagram()->diagram()->border_and_titleblock.importTitleBlock(ip); + } refreshValueField(ui->m_folio_cb, ui->m_folio_value_le, AutoNumCategory::Folio); } diff --git a/sources/autoNum/ui/autonumberingdockwidget.h b/sources/autoNum/ui/autonumberingdockwidget.h index cdfb9f08e..0686a2989 100644 --- a/sources/autoNum/ui/autonumberingdockwidget.h +++ b/sources/autoNum/ui/autonumberingdockwidget.h @@ -66,8 +66,6 @@ class AutoNumberingDockWidget : public QDockWidget void on_m_element_value_le_editingFinished(); void on_m_folio_value_le_editingFinished(); - signals: - void folioAutoNumChanged(QString); private: enum class AutoNumCategory { Conductor, Element, Folio }; From 979df376d14420e393e183bb95a2f8b0eb8c44fa Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Thu, 6 Aug 2026 12:48:11 +0200 Subject: [PATCH 016/350] show terminalnames in export --- sources/diagram.cpp | 3 ++- sources/qetgraphicsitem/terminal.cpp | 26 ++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 9128eecac..ff3f44b4a 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -2397,9 +2397,10 @@ QPointF Diagram::snapToGrid(const QPointF &p) \~French true pour afficher les bornes, false sinon */ void Diagram::setDrawTerminals(bool dt) { + draw_terminals_ = dt; foreach(QGraphicsItem *qgi, items()) { if (Terminal *t = qgraphicsitem_cast(qgi)) { - t -> setVisible(dt); + t -> update(); } } } diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index ee041c632..00a9d65fc 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -199,19 +199,21 @@ void Terminal::paint( // dessin de la borne en rouge // draw the terminal in red - t.setColor(Qt::red); - painter -> setPen(t); - painter -> drawLine(c, e); + if (!diagram() || diagram()->drawTerminals()) { + t.setColor(Qt::red); + painter -> setPen(t); + painter -> drawLine(c, e); - // dessin du point d'amarrage au conducteur en bleu - // draw the docking point to the conductor in blue - t.setColor(m_hovered_color); - painter -> setPen(t); - painter -> setBrush(m_hovered_color); - if (m_hovered) { - painter -> setRenderHint(QPainter::Antialiasing, true); - painter -> drawEllipse(QRectF(c.x() - 2.5, c.y() - 2.5, 5.0, 5.0)); - } else painter -> drawPoint(c); + // dessin du point d'amarrage au conducteur en bleu + // draw the docking point to the conductor in blue + t.setColor(m_hovered_color); + painter -> setPen(t); + painter -> setBrush(m_hovered_color); + if (m_hovered) { + painter -> setRenderHint(QPainter::Antialiasing, true); + painter -> drawEllipse(QRectF(c.x() - 2.5, c.y() - 2.5, 5.0, 5.0)); + } else painter -> drawPoint(c); + } //Draw help line if needed, if (diagram() && m_draw_help_line) From b3a4a41ad953e10c88f8ebe1167b01571fa214da Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Thu, 6 Aug 2026 21:37:40 +0200 Subject: [PATCH 017/350] new Checkbox --- sources/diagram.cpp | 17 +++++++++++++++++ sources/diagram.h | 16 ++++++++++++++-- sources/exportproperties.cpp | 5 +++++ sources/exportproperties.h | 1 + sources/exportpropertieswidget.cpp | 11 +++++++++-- sources/exportpropertieswidget.h | 1 + sources/print/projectprintwindow.cpp | 3 +++ sources/print/projectprintwindow.h | 1 + sources/print/projectprintwindow.ui | 10 ++++++++++ sources/qetgraphicsitem/terminal.cpp | 5 +++-- 10 files changed, 64 insertions(+), 6 deletions(-) diff --git a/sources/diagram.cpp b/sources/diagram.cpp index ff3f44b4a..d0e3127fb 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -67,6 +67,7 @@ Diagram::Diagram(QETProject *project) : m_project (project), use_border_ (true), draw_terminals_ (true), + draw_terminal_names_ (true), draw_colored_conductors_ (true), m_event_interface (nullptr), m_freeze_new_elements (false), @@ -2319,6 +2320,7 @@ ExportProperties Diagram::applyProperties( old_properties.draw_border = border_and_titleblock.borderIsDisplayed(); old_properties.draw_titleblock = border_and_titleblock.titleBlockIsDisplayed(); old_properties.draw_terminals = drawTerminals(); + old_properties.draw_terminal_names = drawTerminalNames(); old_properties.draw_colored_conductors = drawColoredConductors(); old_properties.exported_area = useBorder() ? QET::BorderArea : QET::ElementsArea; @@ -2327,6 +2329,7 @@ ExportProperties Diagram::applyProperties( // applique les nouvelles options de rendu setUseBorder (new_properties.exported_area == QET::BorderArea); setDrawTerminals (new_properties.draw_terminals); + setDrawTerminalNames (new_properties.draw_terminal_names); setDrawColoredConductors (new_properties.draw_colored_conductors); setDisplayGrid (new_properties.draw_grid); setDisplayGuides (new_properties.draw_guides); @@ -2405,6 +2408,20 @@ void Diagram::setDrawTerminals(bool dt) { } } +/** + @brief Diagram::setDrawTerminalNames + Defines whether or not to display the terminal names/labels + @param dt : true to display the terminal names, false otherwise +*/ +void Diagram::setDrawTerminalNames(bool dt) { + draw_terminal_names_ = dt; + foreach(QGraphicsItem *qgi, items()) { + if (Terminal *t = qgraphicsitem_cast(qgi)) { + t -> update(); + } + } +} + /** @brief Diagram::setDrawColoredConductors Defines whether or not to respect the colors of the conductors. diff --git a/sources/diagram.h b/sources/diagram.h index 7a884f6de..360888186 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -126,8 +126,9 @@ class Diagram : public QGraphicsScene bool use_border_; bool draw_guides_; QList m_guides_list; - bool draw_terminals_; - bool draw_colored_conductors_; + bool draw_terminals_; + bool draw_terminal_names_; + bool draw_colored_conductors_; QString m_conductors_autonum_name; DiagramEventInterface *m_event_interface; @@ -226,6 +227,8 @@ class Diagram : public QGraphicsScene bool drawTerminals() const; void setDrawTerminals(bool); + bool drawTerminalNames() const; + void setDrawTerminalNames(bool); bool drawColoredConductors() const; void setDrawColoredConductors(bool); @@ -426,6 +429,15 @@ inline bool Diagram::drawTerminals() const return(draw_terminals_); } +/** + @brief Diagram::drawTerminalNames + @return true if terminal names are rendered, false otherwise +*/ +inline bool Diagram::drawTerminalNames() const +{ + return(draw_terminal_names_); +} + /** @brief Diagram::drawColoredConductors @return true if conductors colors are rendered, false otherwise. diff --git a/sources/exportproperties.cpp b/sources/exportproperties.cpp index 941f894b5..e13a5fb76 100644 --- a/sources/exportproperties.cpp +++ b/sources/exportproperties.cpp @@ -34,6 +34,7 @@ ExportProperties::ExportProperties() : draw_border(true), draw_titleblock(true), draw_terminals(false), + draw_terminal_names(true), draw_bg_transparent(false), draw_colored_conductors(true), exported_area(QET::BorderArea) @@ -70,6 +71,8 @@ void ExportProperties::toSettings(QSettings &settings, draw_titleblock); settings.setValue(prefix % "drawterminals", draw_terminals); + settings.setValue(prefix % "drawterminalnames", + draw_terminal_names); settings.setValue(prefix % "drawbgtransparent", draw_bg_transparent); settings.setValue(prefix % "drawcoloredconductors", @@ -105,6 +108,8 @@ void ExportProperties::fromSettings(QSettings &settings, true ).toBool(); draw_terminals = settings.value(prefix % "drawterminals", false).toBool(); + draw_terminal_names = settings.value(prefix % "drawterminalnames", + true).toBool(); draw_bg_transparent = settings.value(prefix % "drawbgtransparent", false).toBool(); draw_colored_conductors = settings.value( diff --git a/sources/exportproperties.h b/sources/exportproperties.h index f104a9c41..af34f6868 100644 --- a/sources/exportproperties.h +++ b/sources/exportproperties.h @@ -47,6 +47,7 @@ class ExportProperties { bool draw_border; ///< Whether to render the border (along with rows/columns headers) bool draw_titleblock; ///< Whether to render the title block bool draw_terminals; ///< Whether to render terminals + bool draw_terminal_names; ///< Whether to render terminal names/labels bool draw_bg_transparent; ///< Whether to use transparency for SVG-Export bool draw_colored_conductors; ///< Whether to render conductors colors QET::DiagramArea exported_area; ///< Area of diagrams to be rendered diff --git a/sources/exportpropertieswidget.cpp b/sources/exportpropertieswidget.cpp index aaa0966d0..2afbcbc09 100644 --- a/sources/exportpropertieswidget.cpp +++ b/sources/exportpropertieswidget.cpp @@ -63,6 +63,7 @@ ExportProperties ExportPropertiesWidget::exportProperties() const export_properties.draw_border = draw_border -> isChecked(); export_properties.draw_titleblock = draw_titleblock -> isChecked(); export_properties.draw_terminals = draw_terminals -> isChecked(); + export_properties.draw_terminal_names = draw_terminal_names -> isChecked(); export_properties.draw_bg_transparent = draw_bg_transparent -> isChecked(); export_properties.draw_colored_conductors = draw_colored_conductors -> isChecked(); export_properties.exported_area = export_border -> isChecked() ? QET::BorderArea : QET::ElementsArea; @@ -85,6 +86,7 @@ void ExportPropertiesWidget::setExportProperties(const ExportProperties &export_ draw_border -> setChecked(export_properties.draw_border); draw_titleblock -> setChecked(export_properties.draw_titleblock); draw_terminals -> setChecked(export_properties.draw_terminals); + draw_terminal_names -> setChecked(export_properties.draw_terminal_names); draw_bg_transparent -> setChecked(export_properties.draw_bg_transparent); draw_colored_conductors -> setChecked(export_properties.draw_colored_conductors); @@ -206,13 +208,17 @@ void ExportPropertiesWidget::build() draw_terminals = new QCheckBox(tr("Dessiner les bornes"), groupbox_options); optionshlayout -> addWidget(draw_terminals, 2, 1); + // dessiner les noms des bornes + draw_terminal_names = new QCheckBox(tr("Dessiner les noms des bornes"), groupbox_options); + optionshlayout -> addWidget(draw_terminal_names, 3, 0); + // conserver les couleurs des conducteurs draw_colored_conductors = new QCheckBox(tr("Conserver les couleurs des conducteurs"), groupbox_options); - optionshlayout -> addWidget(draw_colored_conductors, 3, 0); + optionshlayout -> addWidget(draw_colored_conductors, 3, 1); // use transparent background for SVG-Export draw_bg_transparent = new QCheckBox(tr("SVG: fond transparent"), groupbox_options); - optionshlayout -> addWidget(draw_bg_transparent, 3, 1); + optionshlayout -> addWidget(draw_bg_transparent, 4, 0); vboxLayout -> addWidget(groupbox_options); @@ -239,6 +245,7 @@ void ExportPropertiesWidget::build() connect(draw_border, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); connect(draw_titleblock, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); connect(draw_terminals, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); + connect(draw_terminal_names, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); connect(draw_bg_transparent, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); connect(draw_colored_conductors, SIGNAL(stateChanged(int)), this, SIGNAL(optionChanged())); } diff --git a/sources/exportpropertieswidget.h b/sources/exportpropertieswidget.h index f6de4e1ae..ae0c97acd 100644 --- a/sources/exportpropertieswidget.h +++ b/sources/exportpropertieswidget.h @@ -62,6 +62,7 @@ class ExportPropertiesWidget : public QWidget { QCheckBox *draw_border; QCheckBox *draw_titleblock; QCheckBox *draw_terminals; + QCheckBox *draw_terminal_names; QCheckBox *draw_bg_transparent; QCheckBox *draw_colored_conductors; QRadioButton *export_border; diff --git a/sources/print/projectprintwindow.cpp b/sources/print/projectprintwindow.cpp index 92ff56336..b115ad5b7 100644 --- a/sources/print/projectprintwindow.cpp +++ b/sources/print/projectprintwindow.cpp @@ -161,6 +161,7 @@ ProjectPrintWindow::ProjectPrintWindow(QETProject *project, QPrinter *printer, Q ui->m_draw_border_cb->setChecked(exp.draw_border); ui->m_draw_titleblock_cb->setChecked(exp.draw_titleblock); ui->m_draw_terminal_cb->setChecked(exp.draw_terminals); + ui->m_draw_terminal_names_cb->setChecked(exp.draw_terminal_names); ui->m_keep_conductor_color_cb->setChecked(exp.draw_colored_conductors); ui->m_date_cb->blockSignals(true); @@ -523,6 +524,7 @@ ExportProperties ProjectPrintWindow::exportProperties() const exp.draw_border = ui->m_draw_border_cb->isChecked(); exp.draw_titleblock = ui->m_draw_titleblock_cb->isChecked(); exp.draw_terminals = ui->m_draw_terminal_cb->isChecked(); + exp.draw_terminal_names = ui->m_draw_terminal_names_cb->isChecked(); exp.draw_colored_conductors = ui->m_keep_conductor_color_cb->isChecked(); exp.draw_grid = false; exp.draw_guides = false; @@ -796,6 +798,7 @@ void ProjectPrintWindow::on_m_draw_border_cb_clicked() { m_preview->upd void ProjectPrintWindow::on_m_draw_titleblock_cb_clicked() { m_preview->updatePreview(); } void ProjectPrintWindow::on_m_keep_conductor_color_cb_clicked() { m_preview->updatePreview(); } void ProjectPrintWindow::on_m_draw_terminal_cb_clicked() { m_preview->updatePreview(); } +void ProjectPrintWindow::on_m_draw_terminal_names_cb_clicked() { m_preview->updatePreview(); } void ProjectPrintWindow::on_m_fit_in_page_cb_clicked() { m_preview->updatePreview(); } void ProjectPrintWindow::on_m_use_full_page_cb_clicked() { diff --git a/sources/print/projectprintwindow.h b/sources/print/projectprintwindow.h index 8585c2091..f290ff4c2 100644 --- a/sources/print/projectprintwindow.h +++ b/sources/print/projectprintwindow.h @@ -55,6 +55,7 @@ class ProjectPrintWindow : public QMainWindow void on_m_draw_titleblock_cb_clicked(); void on_m_keep_conductor_color_cb_clicked(); void on_m_draw_terminal_cb_clicked(); + void on_m_draw_terminal_names_cb_clicked(); void on_m_fit_in_page_cb_clicked(); void on_m_use_full_page_cb_clicked(); void on_m_zoom_out_action_triggered(); diff --git a/sources/print/projectprintwindow.ui b/sources/print/projectprintwindow.ui index 99e1ea68e..0f3f9b204 100644 --- a/sources/print/projectprintwindow.ui +++ b/sources/print/projectprintwindow.ui @@ -183,6 +183,16 @@ + + + + Dessiner les noms des bornes + + + true + + + diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index 00a9d65fc..b838eb1ce 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -275,9 +275,10 @@ void Terminal::paint( m_help_line_a -> setLine(line); } - // Draw label if show_name is enabled + // Draw label if show_name is enabled and terminal names are allowed const QString display_name = name(); - if (d->m_show_name && !display_name.isEmpty()) { + if (d->m_show_name && !display_name.isEmpty() + && (!diagram() || diagram()->drawTerminalNames())) { painter->setRenderHint(QPainter::Antialiasing, true); painter->setRenderHint(QPainter::TextAntialiasing, true); painter->setFont(d->m_label_font); From 3cf5cb945eead2a8634f222ad15fabb702ba34da Mon Sep 17 00:00:00 2001 From: ispyisail Date: Fri, 7 Aug 2026 12:18:17 +1200 Subject: [PATCH 018/350] Keep group rotation on the grid Rotating a selection around the raw bounding-box centre moved grid-aligned elements off the grid permanently. sceneBoundingRect() comes from font metrics and pen widths, so the centre is almost never a round number: with a pivot of (132.67, 101.11), an element sitting at x=100 landed at x=133.78, and no further rotation brought it back. Positions are written with QString::number() (%.6g), which hides the floating-point noise but keeps the offset, so the diagram ends up subtly misaligned with no way to repair it from the UI. Snap the pivot with Diagram::snapToGrid(), which also follows the user's configured X/Y grid rather than assuming the 10 px default. Also compute the rotated offset exactly for multiples of 90 degrees instead of going through qCos()/qSin(). The rotate actions only ever pass right angles, and qCos(90 deg) is 6.12e-17 rather than 0, so the trig path added error for no benefit -- four 90 degree steps did not return a point to where it started. A quadrant is an axis swap, which is exact; trig is kept as the fallback for any other angle. With both, four 90 degree rotations of a grid-aligned element return it exactly to its original position and every intermediate step stays on the grid. Reported by plc-user, who hit the same problem rotating graphical primitives in the Element Editor -- discussion #618. --- .../undocommand/rotateselectioncommand.cpp | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/sources/undocommand/rotateselectioncommand.cpp b/sources/undocommand/rotateselectioncommand.cpp index f893c5510..341f01a2b 100644 --- a/sources/undocommand/rotateselectioncommand.cpp +++ b/sources/undocommand/rotateselectioncommand.cpp @@ -39,17 +39,32 @@ m_diagram(diagram) if(!m_diagram->isReadOnly()) { - //Shared pivot for group rotation: the bounding-box center of - //everything selected, computed once up front from the - //selection as a whole (not just the items that end up being - //individually repositioned below). + /* Shared pivot for group rotation: the bounding-box centre of + * the whole selection, computed once up front (not just from + * the items that end up being individually repositioned + * below), then snapped to the grid. + * + * The snap is not cosmetic. sceneBoundingRect() is derived + * from font metrics and pen widths, so the raw centre is + * almost never a round number, and rotating a grid-aligned + * element around a fractional pivot moves it off the grid for + * good -- an element at x=100 lands at x=133.78, and no + * further rotation brings it back. Positions are saved with + * QString::number() (%.6g), which hides the floating-point + * noise but preserves the offset, so the diagram is left + * subtly misaligned with no way to repair it from the UI. + * Reported by plc-user from the same problem in the Element + * Editor, discussion #618. + * + * snapToGrid() follows the user's configured X/Y grid rather + * than assuming the 10 px default. */ QPointF pivot; if (rotate_as_group) { QRectF bounding_rect; for (QGraphicsItem *item : m_diagram->selectedItems()) bounding_rect |= item->sceneBoundingRect(); - pivot = bounding_rect.center(); + pivot = Diagram::snapToGrid(bounding_rect.center()); } for (QGraphicsItem *item : m_diagram->selectedItems()) @@ -124,13 +139,35 @@ m_diagram(diagram) void RotateSelectionCommand::addGroupPositionUndo(QGraphicsItem *item, const QPointF &pivot, qreal angle) { const QPointF old_pos = item->pos(); - const qreal radians = qDegreesToRadians(angle); const QPointF delta = old_pos - pivot; - const QPointF new_pos( - pivot.x() + delta.x() * qCos(radians) - delta.y() * qSin(radians), - pivot.y() + delta.x() * qSin(radians) + delta.y() * qCos(radians) - ); - m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "pos", QVariant(old_pos), QVariant(new_pos), this); + + /* Exact arithmetic for the right angles instead of qCos()/qSin(). + * The rotate actions only ever pass multiples of 90 degrees, and + * at 90 qCos() returns 6.12e-17 rather than 0, so the generic trig + * path introduces error for no benefit: rotating a point through + * four 90 degree steps would not return it to where it started. + * A quadrant is just an axis swap, which is exact. */ + QPointF offset; + const int quadrant = qRound(angle / 90.0); + if (qFuzzyCompare(angle, quadrant * 90.0)) + { + switch (((quadrant % 4) + 4) % 4) + { + case 1: offset = QPointF(-delta.y(), delta.x()); break; + case 2: offset = QPointF(-delta.x(), -delta.y()); break; + case 3: offset = QPointF( delta.y(), -delta.x()); break; + default: offset = delta; break; + } + } + else + { + const qreal radians = qDegreesToRadians(angle); + offset = QPointF( + delta.x() * qCos(radians) - delta.y() * qSin(radians), + delta.x() * qSin(radians) + delta.y() * qCos(radians)); + } + + m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "pos", QVariant(old_pos), QVariant(pivot + offset), this); } /** From 43e4603c5576970f746f46311825f19cffc66e18 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Fri, 7 Aug 2026 07:59:39 +0200 Subject: [PATCH 019/350] Fixing minimum width calculation for title block which could lead to division by zero and subsequent program crash if opening a template with only relative sized columns. --- sources/titleblocktemplate.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/sources/titleblocktemplate.cpp b/sources/titleblocktemplate.cpp index 782b3b532..63a3631a6 100644 --- a/sources/titleblocktemplate.cpp +++ b/sources/titleblocktemplate.cpp @@ -26,6 +26,7 @@ #include #include +#include /** @brief TitleBlockTemplate::TitleBlockTemplate Constructor @@ -973,14 +974,20 @@ int TitleBlockTemplate::minimumWidth() // => (1 - (sum(REL)/100))TOT >= sum(ABS) // => TOT >= sum(ABS) / (1 - (sum(REL)/100)) // => TOT >= sum(ABS) / ((100 - sum(REL))/100)) - return( - qRound( - columnTypeTotal(QET::Absolute) - / - ((100.0 - columnTypeTotal(QET::RelativeToTotalLength)) - / 100.0) - ) - ); + int abs_total = columnTypeTotal(QET::Absolute); + qreal denominator = (100.0 - columnTypeTotal(QET::RelativeToTotalLength)) / 100.0; + + if (denominator <= 0.0) { + // The relative-to-total-length columns alone already consume + // 100% (or more) of the available width, so the formula above + // would divide by zero (or go negative). If there are no + // absolute-width columns, there is no meaningful minimum width + // to enforce; if there are, the template is asking for more + // than 100% of its own width, which cannot be satisfied. + return abs_total > 0 ? std::numeric_limits::max() : 0; + } + + return(qRound(abs_total / denominator)); } /** From 9891eef916b952153926028fd67dc5d84e3d5a44 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Fri, 7 Aug 2026 19:07:52 +1200 Subject: [PATCH 020/350] Add two orphaned actions to the menus, drop two dead members Both actions already exist and work; they were simply only reachable from a toolbar, and those toolbars are user-hideable via Configuration > Afficher, so hiding one made the feature unreachable entirely. - "Afficher les guides" (m_draw_guides) goes into the Affichage menu next to "Afficher la grille". The two are adjacent lines in the view toolbar and do the same kind of thing, but only the grid had a menu entry. - "Creation automatique de conducteur(s)" (m_auto_conductor) goes into the Projet menu. It writes a project setting via QETProject::setAutoConductor(), so the Projet menu is where a user would look for it; it is placed with the project properties, above a separator that keeps the folio operations grouped as before. Also removes conductor_default and m_project_folio_list from the header. Both are declared but never allocated and never referenced anywhere in the tree -- that the build still links is the proof they were dead. No new strings: both actions already carry translated text. Found while auditing every QAction against every menu, discussion #677. Co-Authored-By: Claude Opus 5 --- sources/qetdiagrameditor.cpp | 3 +++ sources/qetdiagrameditor.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 447af2b1d..655bcd0d4 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -882,6 +882,8 @@ void QETDiagramEditor::setUpMenu() // menu Projet menu_project -> addAction(m_project_edit_properties); + menu_project -> addAction(m_auto_conductor); + menu_project -> addSeparator(); menu_project -> addAction(m_project_add_diagram); menu_project -> addAction(m_remove_diagram_from_project); menu_project -> addAction(m_clean_project); @@ -917,6 +919,7 @@ void QETDiagramEditor::setUpMenu() menu_affichage -> addAction(m_mode_visualise); menu_affichage -> addSeparator(); menu_affichage -> addAction(m_draw_grid); + menu_affichage -> addAction(m_draw_guides); menu_affichage -> addAction(m_grey_background); menu_affichage -> addSeparator(); menu_affichage -> addActions(m_zoom_actions_group.actions()); diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index bdbf940f0..f5666f781 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -192,7 +192,6 @@ class QETDiagramEditor : public QETMainWindow *redo, ///< Redo the latest cancelled operation *m_paste, ///< Paste clipboard content on the current diagram *m_auto_conductor, ///< Enable/Disable the use of auto conductor - *conductor_default, ///< Show a dialog to edit default conductor properties *m_grey_background, ///< Switch the background color in white or grey *m_draw_grid, ///< Switch the background grid display or not *m_draw_guides = nullptr, ///< Switch the custom guides display or not @@ -200,7 +199,6 @@ class QETDiagramEditor : public QETMainWindow *m_project_add_diagram, ///< Add a diagram to the current project. *m_remove_diagram_from_project, ///< Delete a diagram from the current project *m_clean_project, ///< Clean the content of the current project by removing useless items - *m_project_folio_list, ///< Sommaire des schemas *m_csv_export, ///< generate nomenclature *m_add_nomenclature, ///< Add nomenclature graphics item; *m_add_summary, /// Date: Fri, 7 Aug 2026 21:10:46 +1200 Subject: [PATCH 021/350] Add optional precompiled headers behind QET_ENABLE_PCH (default OFF) Building QET is dominated by re-parsing Qt's headers. A 214-line source file expands to roughly 198,000 preprocessed lines, and compiling one translation unit costs ~4.1 s, of which only ~0.35 s is optimisation -- switching -O3 to -O0 saves just 8%, so the usual "build Debug for faster compiles" advice does not help here. A precompiled header caches the parsed header state, which is the part that actually costs. Measured on a 24-thread Xeon E5-2650 v4 with Qt 5.15.18 and GCC 15.2, same build tree, only the option differing: compile one translation unit 4.12 s -> 1.21 s edit one .cpp -> linked binary 5.22 s -> 1.65 s Deliberately OFF by default. A PCH satisfies includes that a source file neglected to make for itself, so code written with it enabled can fail to compile for everyone else. Leaving the default off keeps CI and contributors on the strict behaviour; only developers who opt in trade that away for the speed. Two details in the implementation are load-bearing: - The generator expressions are not decoration. This target also compiles the 18 C files of the bundled LZMA decoder, and an unguarded header list applies to every language in the target, so the Qt headers would be fed to the C compiler and fail with "unknown type name 'namespace'". $ is needed because a literal '>' would end the generator expression. - target_precompile_headers() requires CMake 3.16 while the project still declares a 3.5 minimum, so the block warns and skips rather than raising the project-wide requirement for an opt-in developer feature. Verified both ways: with the option off no PCH artefacts are generated and the build is byte-for-byte the previous behaviour; with it on, all 18 C files still compile, the generated PCH is C++-only (cmake_pch.hxx, with no cmake_pch.h), the C compile commands carry no PCH, and the resulting binary runs. Co-Authored-By: Claude Opus 5 --- CMakeLists.txt | 28 ++++++++++++++++++++++++++++ cmake/developer_options.cmake | 14 ++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 537c68ddd..45b539de4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,6 +145,34 @@ else() ) endif() +# Optional precompiled headers -- see QET_ENABLE_PCH in +# cmake/developer_options.cmake for what this trades away. +# +# target_precompile_headers() needs CMake 3.16; the project still declares a +# 3.5 minimum, so guard rather than raise it for an opt-in developer feature. +# +# The generator expressions are load-bearing, not decoration: this target also +# compiles the 18 C files of the bundled LZMA decoder +# (sources/import/edz/lzma/*.c), and an unguarded list applies to every +# language in the target, so the Qt headers would reach the C compiler and fail +# with "unknown type name 'namespace'". $ is required because a +# literal '>' would terminate the generator expression. +if(QET_ENABLE_PCH) + if(CMAKE_VERSION VERSION_LESS 3.16) + message(WARNING + "QET_ENABLE_PCH needs CMake 3.16 or newer (found ${CMAKE_VERSION}); " + "building without precompiled headers.") + else() + target_precompile_headers(${PROJECT_NAME} PRIVATE + "$<$:>" + "$<$:>" + "$<$:>" + "$<$:>" + ) + message(STATUS "QET_ENABLE_PCH: precompiled headers enabled") + endif() +endif() + target_link_libraries( ${PROJECT_NAME} PUBLIC diff --git a/cmake/developer_options.cmake b/cmake/developer_options.cmake index 04f002da4..cec095273 100644 --- a/cmake/developer_options.cmake +++ b/cmake/developer_options.cmake @@ -33,3 +33,17 @@ add_definitions(-DQT_MESSAGELOGCONTEXT) # Build with KF5 option(BUILD_WITH_KF5 "Build with KF5" ON) + +# Precompiled headers for the Qt umbrella headers. +# +# Off by default and intended for local development only. Building QET is +# dominated by re-parsing Qt's headers: a 214-line .cpp expands to ~198,000 +# preprocessed lines, and compiling one translation unit costs ~4.1 s of which +# only ~0.35 s is optimisation (-O0 instead of -O3 saves 8%). A PCH caches the +# parsed header state and takes that ~4.1 s down to ~1.2 s. +# +# It is deliberately NOT on by default: a PCH satisfies includes that a source +# file forgot to make itself, so code written with it enabled can fail to +# compile for everyone else. Leaving it off keeps CI and contributors on the +# strict behaviour, and only developers who opt in trade that for the speed. +option(QET_ENABLE_PCH "Use precompiled headers (developer build speed; may mask missing #includes)" OFF) From 99151b9c04b5ad730f34d3f6c998216da0cb3865 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Fri, 7 Aug 2026 11:39:08 +0200 Subject: [PATCH 022/350] Report "no constraint" (still needs the translations; to be added in the next translation round I guess) from minimumWidth() for a title template instead of an arbitrary value. Following up on the earlier division-by-zero fix: return -1 from the bad denominator branch of minimumWidth(), matching the "no constraint" convention maximumWidth() already uses, instead of std::numeric_limits::max() or 0. Update TitleBlockTemplateView::updateDisplayedMinMaxWidth() to skip the "Longueur minimale" line when minimumWidth() reports -1, mirroring its existing handling of maximumWidth() == -1. --- sources/titleblock/templateview.cpp | 18 ++++++++++++++++-- sources/titleblocktemplate.cpp | 10 ++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/sources/titleblock/templateview.cpp b/sources/titleblock/templateview.cpp index 096f96c0f..b41881d82 100644 --- a/sources/titleblock/templateview.cpp +++ b/sources/titleblock/templateview.cpp @@ -999,20 +999,34 @@ void TitleBlockTemplateView::updateDisplayedMinMaxWidth() int max_width = tbtemplate_ -> maximumWidth(); QString min_max_width_sentence; - if (max_width != -1) { + if (min_width != -1 && max_width != -1) { min_max_width_sentence = QString( tr( "Longueur minimale : %1px\nLongueur maximale : %2px\n", "tooltip showing the minimum and/or maximum width of the edited template" ) ).arg(min_width).arg(max_width); - } else { + } else if (min_width != -1) { min_max_width_sentence = QString( tr( "Longueur minimale : %1px\n", "tooltip showing the minimum width of the edited template" ) ).arg(min_width); + } else if (max_width != -1) { + min_max_width_sentence = QString( + tr( + "Longueur maximale : %1px\n", + "tooltip showing the maximum width of the edited template" + ) + ).arg(max_width); + } else { + min_max_width_sentence = QString( + tr( + "Longueur non contrainte.\n", + "tooltip shown when the edited template has neither a minimum nor a maximum width constraint" + ) + ); } // the tooltip may also display the split label for readability purpose diff --git a/sources/titleblocktemplate.cpp b/sources/titleblocktemplate.cpp index 63a3631a6..1e9b45a41 100644 --- a/sources/titleblocktemplate.cpp +++ b/sources/titleblocktemplate.cpp @@ -26,7 +26,6 @@ #include #include -#include /** @brief TitleBlockTemplate::TitleBlockTemplate Constructor @@ -980,11 +979,10 @@ int TitleBlockTemplate::minimumWidth() if (denominator <= 0.0) { // The relative-to-total-length columns alone already consume // 100% (or more) of the available width, so the formula above - // would divide by zero (or go negative). If there are no - // absolute-width columns, there is no meaningful minimum width - // to enforce; if there are, the template is asking for more - // than 100% of its own width, which cannot be satisfied. - return abs_total > 0 ? std::numeric_limits::max() : 0; + // would divide by zero (or go negative). There is no finite + // minimum width this formula can determine. Report "no + // constraint", the same convention maximumWidth() uses. + return -1; } return(qRound(abs_total / denominator)); From 97709bff6a286a80e59431f65783921313a434ee Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Fri, 7 Aug 2026 11:42:20 +0200 Subject: [PATCH 023/350] Save the default cross-reference properties to QSettings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NewDiagramPage::applyConf() writes every other default to QSettings — border, title block, conductors, folio reports and the guides — but the cross-reference branch only fetched the properties into a local hash and then dropped it on the floor. hash_xrp was never used. The result: changing the cross-reference defaults under Settings > New project has no effect. Nothing is written, no defaultxref* key ever appears in the configuration file, and XRefProperties::defaultProperties() keeps handing out the hardcoded fallbacks for every new project. Write each of the four types (coil, protection, commutator, plc) with the "diagrameditor/defaultxref" + key prefix that defaultProperties() already reads back. --- sources/ui/configpage/configpages.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sources/ui/configpage/configpages.cpp b/sources/ui/configpage/configpages.cpp index 1a01a343e..26711a18c 100644 --- a/sources/ui/configpage/configpages.cpp +++ b/sources/ui/configpage/configpages.cpp @@ -214,7 +214,11 @@ void NewDiagramPage::applyConf() rpw->toSettings(settings, "diagrameditor/defaultreport"); // default xref properties - QHash hash_xrp = xrefpw -> properties(); + const QHash hash_xrp = xrefpw->properties(); + for (auto it = hash_xrp.constBegin() ; it != hash_xrp.constEnd() ; ++it) { + it.value().toSettings(settings, + QStringLiteral("diagrameditor/defaultxref") % it.key()); + } // Global in QSettings speichern QList current_guides = m_gpw->guides(); From e3964fb24a048afc2b3b362161b27d1a9cd88a7b Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Fri, 7 Aug 2026 13:12:28 +0200 Subject: [PATCH 024/350] Update en and fr translations files --- lang/qet_en.qm | Bin 307943 -> 315401 bytes lang/qet_en.ts | 85 +++++++++++++++++++++++++------------------------ lang/qet_fr.qm | Bin 200672 -> 204494 bytes lang/qet_fr.ts | 78 ++++++++++++++++++++++----------------------- 4 files changed, 82 insertions(+), 81 deletions(-) diff --git a/lang/qet_en.qm b/lang/qet_en.qm index f69d72531c5364ad9ddeccbeb8f5abf713ba6bfa..9b01c5982f04b7edb023b79c7f02fbb70ddf5bcd 100644 GIT binary patch delta 25899 zcmaI82Urxz7XE#ztGg%9m@q4dVir+g%@Hvx=714lK$M^a1p}jE&Vq_LqnPt5m{3H; ztblnH#hi1%6~A}7_wK#_FFpIl zAr`(-p;%-TSc_dRAy#^{c--LLMAYk znJ>W@q6YTQ#gL5;X^(?g;zPoT#AIS+pA$(wj6LZMmH`;-R=8-r!FkC=@LgBIn5@R=q`3 z^)v~=cU4|TZ&YhWwCn>>bx#tmuSW+pA#vldQ-@g&@>t5B>NN7Q)}@q5$3 zUBr9!MaLze=l(>;btT%=8nmq;YK;fzwT8I$C{gc0M7~iflgBF*qwvArgNZyFftzrF z??inj<2y@L?wYTVKe-O3;&T`(-^Rp3@f|zk3Ka6E^%RQc6W{^jPc{(Q2G~D{uCUYQ zrjS3yL*TV&eg+ODF#^LeJf65Wz8IWA)X9k`;sCL#{S}HDbZI17R{{?bJ&1VcpG4zu zvjMQ7arMC+pgV}69oHB=J&S0(o%_i~pFb1(`2ph+NmR5y36X`k@JteB#*mP$S19&; zN8;T5#40UU$ltFeF(H%q1-xFGLR6(Ui7Ck>JQGRW9Y_3Pa}uw5gWE`ic?grAk$7Vs zhOv~&2K7|7+-_43`gc_6`%vZZ8Y;(^SGm+p<+7qGkF`_CSZ$T%#;UA%S*7!QmCaYH zw6<0`%30;u0+q9D^VEZRaVl4?P`T;7%KcqcX8iNToU+Pm9_y+yu8+$38&w{TP(A&Z^n^(1Ds6i8Nkqq8>WPtOR7Rntw_yiWyOH=DUEcyT;`wP3-8Pf> zf)l@_A*ogli6N^<@_ayIy{;sAClg;#j-);U@vGOtsl@Zokrb3mqJKY_QqmDDO6vG?}|dsC7wY>?xHe z-jn8{{c~}ot>!@7w;bt;+ro%X-AP6_iKtu`GWT{Per7Tif3%LMFqIstVvY+1RQgIP ziM`KJxzdTmjP+FBuT16cdy;6_M-?)b5U;$GoJzt!G=4!&qvsPp6iCi@evmjcg{mB> zN&M|U{Lq-H-ZYaiuPjxwc|{QO+(p&;l_54gjH;c%^t)1-s@I=F!ja`vW93`oiHoVG z4byAH3YBXM$X%ZYuUAE(@V*PV56mIjJB}KDcOlVsfttj_&mYrLlSgQ2cN?`V_<_$S zD-^!wQ=12!NvKkbY~ByxVi!u(?od0-=RVYa8iryCr}i_Z5v$vZ+NT{SS~)}^^EWBv zX$30Jr&9Y1(};ZXRIXe@9jbfbI@PE{ur~?!7g2}tct1o(9nwAEC+1T}D|))yZtA#H zOZ>=G8+FWr&+dJnI!VbyYZobGl`bk2UX4)5KTe@e-SK|<6Y4VTH<43Kl`eM`vgETW z_m@}5=hs#!#);G=7_;Ky4eB-*4(alF>b4XOtlU5$|6Tvn=_Z&Z2W zu|h7KR4B?5sOQXFVu3rTcU^a4>jmmP1gsIvyY+k$kf-ByHa)w9%d} z$^onLS|P95SY>b>mEUn5(~;UmtF(4iIkv7s7MHFvxu42I-4ybgK?=o|D`|lCG;VxL zW%gSdV88=dE7)lxTHH`M!D}w00W(G7rzg|kj+nnGmuT<@$r*kFZ;vXw<#p1lLKU7bOtOPosz$ z&Lq4(KoJ;n-eEaK?6*Y`ua-y=U%Ha;uq;Is!bm!trYJ;HcK9MiZz@m1Q?5`P5hEiNFj~0cWviZ3VCQSjYH3IpI0==%JF~_O?qM_7VtNS z?+xlllWjrXh{;1}GRVdzs!ZLaP}H}f_;ZIamJ?{MDHU38InA{$Mvsi6xf9+J+g6bl zcpQXBdrS%5>xsAbr9{~UV||qtPnZhL@Sc{`Y(%V6Us}@oJF$N4X=yVwxP47py1kI- zYbx26|2RQhcugxNU>dHPOe>DBAt9lG%Iz|(3_3t$9z<($KNJ6SfHpnuN_0DiHs=W> zILuc$;Xx@ zj#PQ0p+X^fH0`O~fyB;>X-{e~5(ckRnQ(&k+?z(s2l0P@i{3Df(R6UTl_=3hX(JPf ze|J(S`aGbtlo3Rw4k%=P28CjEcRKang(&m^o$hdu=#q}ktaK&zdm^2A4Hv#8h_c2; zk+5QQX~mo4RqyCFA{9MohZA14hhzql)VRCmDPrBx^whI zDBW-8Ni-pm9z^<*Sg9lB)rA$$O;ULxnjV(L1DCl#j|hTu>UqkKfRV{l=t)o-1V(*& zeiG4jemj*buhEO7rzFI$p^r_U5O?W8ANyS;8@r!Hzx^3e&Uwaav?7*OgE8-l#KVp% z6pLpuZS_x>RvnpkcRtb3cg(nVFtK{)nW=X!2{n(gqE#8Ov#VIqtq)1~oB}=~;Y$%P zAB+JXgL$mjj@QJ(+AHKI7T5{>$HubazEG(NMOX=ZfOimC$rLD;<4svP2k86{51Hcx z%;QbBnd98bBsl7rv%?aih9S(kLUZC%7BZJ1r-@baWHoiak;wdDb#7srhSz0o6`=bY zK4SH@VTgChtbRm)gmFLCu#qd#g@dfo6h<~1SFe^+5`uR?fy$Yz}r;LD$!V!bVpXhr^Fy^nq&HYJ|*K6anznU3|j z;7@|78tXsv2UPV*HlY0n60TilgGMz&Pd{cuY$^E|i}!5EH3XCHTbX|(;`X1FnEx*` z(XA(Jc%+ed-VYX%l1{=+9Sfc6Kw=*^78doASV$=r4voNz9A=|CmBlP*&m!`sA*cu} zQkP1?jg~C3z5@x9%CX2fzVP`|Skz_Y1QqtNvG)cdlbXY9F%NbTYc-L@w#9=Oh>gb+ z@^)9*_!!XpF^kiN5%b-~;s;J4b|aQeYl|GNX+1VA34S5$gUazeRmP{X>1W3gbB2}y z`6q!*zljttZZ72IVG^Vmw&OS$=bzfxk`J)*I9IlMH$-RUA#7d#5Mri& zY`wKO2|SE#K9WPMQ4HJi2J>~_Otx(vgvGggY}-*}zz00o?u}5pKUT6m=cAEMHDG%O z--P;|&-O(uA>nKs+jke)kExIy{PmdF=27g=e#k9`83_l8Ki=}1Cd^)nnu2y2RnzP595YK1NV~=~o5gmBPUMww1?0&35p~)xq;&3U9@pAUEC8q7- zsq9tbTq46s_BLY+@#`{smxGv4Wurp=eFJ;HC4fcU5$z1MM~Q4++)8MBSrj>B(Saaw_OFH;5!L(!c=ZqEy$_v=*AA(@a332tj)I%_O~ z$EF@o=g)-3MJf_oT~BCwZ6NX6SA}-5`$_P9By_Mr49{vVbP{J{64VnqcSWq*y;bOP z1(S^>3qDr^i1yzRdTttlpj$%dx4wjpgmIiLS(+j1+!FVz$*4(Lxh;sfB?!j`UM9Azzi?b1Mnr`Qg-6YV6Fml#7_Aphob63i@`{kIn@VEQ>Oy)J z3S~q03MYrvfFIiY=p{j)rBmd{UlE4BAoYvHP6{0TqqTd*?d{J5WAX$og`cu9{|Z&M7S0f zMQr4s!rc~#+KygAK9s#M-$8g{DN4eN1Q2@VrA>D||v?Y)9c2^a%SE zA^dh8f-Zl^X&`3J{)wC}yFs~?;?mnZ=#wWpE>uG?}NQn4nt#No+J znY^fbU*fsFdC|L=$6|l(aLof<@6Ah(!;oZM;N{}F5?P{oc~tNCX-Dojb^-~`leyzV z7;(Lx-04gJu^D9*3bg`xWmou<-bo5=wEGgTDmh?Yj_1|Or$Bdv^Xh+GCL!%EuU-8i z@wO{?Z4ZS1I;Xj7mGwl^iu1bdo)DYp%iUt{BPvJmdRqb@`yX=mYL|(pHR0|MT;k~G zyz!&{#2%F9%`eX;G4w9?T9Qe^P#@l=A(CU4%e>8kUdT`6HM~vXWfCp*dDpg=iEF-3uM48zNK4llnDxWN_T;T5G~(kmkH}a`SxpX~1rBg^I|*TFW5e&!iz zK15Eh_?epV#70-(XB{GmSFXsX44d<;>&n4d>-%=H2Mq7R0+OFe!m)ky5p z4^#@`P)hD)%*k{X| z`1!)9Qu#M6wCKX){QCe4343nyU&rBa)@%`ZhgR^EJHgh(OOye?vE0pE z5-w+pWNjO_PYF`^PA--6o;#cuV)h!fec z>Xzb|wNP%k`C_bm3PV*=q0n}^7`qukrpS76+#Wp0*%&cy3!-WP7bm4-XgnjtNvF|M zJyXPZ!wRCq?qd8xc*p^H;+Xcc2`vn*)C>n!Vm?&60eL|OiZXMUi}1hy|}f?lh4GQ zTd=85oy8k&{=}}?CMXAdexP`>EF{#MHsY<+C+O;jD#J#ojJGLd)@2GsDp2WW7Voz0 zO=87W;@ww;B;?H!A2pvw>@R2W`5DBPrGoe(#7aVoNb#j}HdcWC6kio&Kn(v7-*gJY z{4ZHoe0!lc>XRK6a%+J2(c6>QhRfo|-C-n5>mh!bjJRL4toXGA!tncU;#?Qk7M3T=V{vs&_qz7CB0_2E2x_a96oINUAfg1F=7aotm?;c~c>tAnK`-M63) zTU%;&9UVF8nbfjwCW-atNG+ESBVpcs$!i4s-nVqgYaa5VnH!|GT?ZobbeGz_hgRk;#mIDN#DI^)Z|;>s_PC>L>Z@}8e3hB0Qb?932_;8^HXMvxt)4h0N?}*v z=`Te};d3D)f?i0GNuQAE?UcsUg;$97Ryo;2AsgwgGOmq6{y0(^yBI_C)?11l3e$Yo zO^P!k)`^>>Nr|~c{y(Kj+YuRjze$sJVs1?EktW+Fd_mG*AjP{Qd4J&{#lMXv+E!ee zU9=^1Pdu22jIf_HcK|9(aWT^3i7=rcN;{l2sV zvzkVhQ^>l9NIM&b5s!T$?ShnLi&sgz&rd-*v(zT-*@s~0kSOgxg_Lnpq;%kzD+xt3 z(x3BviC>hYKR37%)9#f1JP$V!>LeY8!lVkZ(y;(Y%hu;WjJ1~|_z4^Xeg-c|>6Q`1 zZeEengWz^tswm`73RV7aQ7HDX<*Ek}q0-6rFR=(%PRcBTmb6|aon5wxxT(E#t~NZh zZ;HwolR}<$Ryyaqm$>so=}Ip=@OfA1>af$qbN-TYqNk9M;VI?Z-$lZ`X3`D&(pv4x zD#xuX%o@*=F(%sB9u9+NsrgVSZWWD zo`%GsMmI!yx^@}~+4ZGod3x0Dj!Q2(NSOBvRi;dlUe>@69`RL~@wfDP3x;fvD7_g9 z1!)VHzD_J4k*|{qE3H92Hf)h{APNJe-+dop@5L)w6t*In_LZf-krGaBB};{nh9h;d zwm8(mjVRgZfkon|2-)a~)G>8|Y<$}s8QyN$v^tB#G2dm=H#pY(_j1ve8xh^l$i-&w zA~Kefi~VX&0!xsKx5um)eo`*smt#X2Kx023VPdvIF>;jbP^EzQ@H29mf$-=)&E&GV za47wL%N6SmCUWc}J6(50DeRQ&j8Yg?3Xoko)g>V=U#|Lk2C;G_W!H^3-+qNcK5~Uz zx08fQW13typ(85Tixsl=A3+;70&rjDglP6r*|MMfhgT%A4)x>)C6l4fL*ynR>KIL* z$W6!R5N%y3H!D4ugx{UzX73!ZMP`oNq9SZ0yQtjap(pWj9px7JV3$a_^~+5pyjmiA ziDo=-pzKuuV|KhJw|j6O$^ALGy>0n^IE=4y`?HHNo%+ZfW_lBQK1A-=eH@AXv~tHC z^NH4fP{>>cshrnX<;uP)Pi#{te4D6Hl$)va<8qgm$s|`8B<1O=2xv_{sVfqVs!CVBlD#zr7Nz;fu`Y0z1u^?%$ zDJM=rbhMcp$%)tS#Z43C#oswmT9mxh1Vu)X^3v0=`iM31(tBYf%z~4#ol_?M$OD4$I5}Fbl^I5(g z57F)9CugrilVbQskWIGQ=y9oRbxdy2lhbcaSXr7rrXzZa}@l zQYhbWPlV*EA>Uk#X?MJvd@CXoD^pJLt@-td-+3e7T4(2M`F{OYBo4j>wnlNkqI~}& zB$cM7%4aj=2SqSc(SOJfb=kxt4k{E&ACjNTh_>V@zuN3d{9~&8+U5sORl2tP+Ro08 zRUWCPkl%EZU;9@?eWI5923sP80p9Yv@3V>aR+ZnkfJf^VD}Nd7jv9D~{AJv7Vzti7 z-|(8ZYbpPHvJn-Zb8=y~;z(5!HQHGlNf>lcqw9zU%{r_xjYuG&n@wZ0AMmmzG?uf| zh|b4piY&$l%Xin5UINc&&eBwPfEyH8H5ER=<8@r2ar&ks<~K-FS;jJG$H|(?o>(3o zIZ#tA0>%GJdo|UYTQUDVHFbC6K{uS$xD|)-E}E%wo3Ex`B!W}mJB>RepC~5UG#=ha z0S7(OG&*;Vgw4w|jh>G~Qv6ucWF1=2qq?T~`s3IXHbm2+-vZ+E`fJ+6q!P~>rD<>9 z0^_qw(>@;x$osygqlm;SwYJKaMKy|u?KEE@4>_UfawQl&nXBnF$xK44UMi>9N^AP` z^dO;sgvQr*2Js3_G{YMAhv#~!@o(OoXhwI9e>7b3s!UDzS9G}{T;*TEno*r_Px>1UtJVYZmVxO)M*3v*cSFq7UCSOO5#mYDX0cJ-sw`t!U$2 zZ)jG`yeey;|7{dT1>Y$9~BCXvQ*l7sXR4Lv#C)C30012HceiG zvf?F8N)2Bulj=3wHeW1 zVW-|Ce5|H9d_I?G`BH^!Ss9hb5)=wIR%+7fJRx4vrb(NHx<*1L&5<}1X!l*w9Myls zO3z!((cumx)VQkhPCw1@OFf9j9#=VKfXb=kHR(Ox5*1mZIWyEI5w&}V1B~5>FPaPC zD2h3(*IaD=p6Gj&=HdhRfyKd^%f7u)f(lj0{q|{c><{v|K$BbV9kImMD%U!Jzlkyu z6*BpOCf8d_%yp3_cPN6*+~1np;kchIRdc^`cdR6NX&%_b63DubX!1%&lh7wylXnAF zJr8`jkA$Stn#bkVA`xk!c~Y+@6wNb*eB@)5r%$WQanw8+3|V|&w&uBU2$9DO&C3Yr zi7rOXTVF>M<4AtIj^dD37?e*!qY7H?yaLm$okA98Q^%M$ZH41lD0b0m zN5h|V3RcKpH_$pP!K~VHTA>&kW7C#IBEUj(6be=SwbkTk1e@mC+OF6FDeu$Pk?*6H zU0+*g_Ar!`-fHV4Mk1)BYU|rwZvWp3g(J7L?&%vytftj^^f-<}?S7RRo?4IJR-#iD zZKGLMVgYNkUOS7Sd|9aVIy{Tm4cifI*J^M$6-Xf)b3h^YE7W$y&NAjIX?+GxCU)kA zw%ZdJ>B$n>9urX=Xql|-br6Che!RAqebw*5B5m)8OT@A}YkQxXf*oq>6$-WLtBjqm zkPlg^?H_OnQf!2FKri%=OO@6pH1WXyf`ipul3)#;t^Ste>ro zJA$YfxLiA_I3!xHVcJP|;KL{QX(w;T{BB%RWm9*B?BY>{+?=YNa??s;n{C<|0c%NY zpRJuOe?pL(q@9BehqQi!cJA7@i2r4uYUiaxjg~2nmUTeM4DD-+MG zu3cUREn2J9F5iZvGp(F|)nr$hM^^-{=p4$-cX5G!`A)oyf-z$!qbcJo@; zmL)>FIc+(1eFKV~nSOFbDplt>5Cw|Ha(L6=Fb7efS<~Ou^`XfI3$lAS0 zV@cT5QhTu7ZKCu6+QaT%BvfmvP0h!Rmz>k4We!HTU9LSkDVKzP7gR1Pr9J)`b<1#7jZZ0iwL+qh`Y`5>w#7SW!+n2q!{UVHv-90{$b zXs@h7!f&m`@ROI)$=6w|)+(HS;l0d-7q zov}K;&}^haaj2)x_z*2WAEPrx!l(*9>r8Xk5Z&CSvvm1LO!m@Q1|cRCnV>7u!I#+g zp1Pttq5Fq-(v@mj5i(rTIkqZ`sB62VbDWJ94SuC_N=8_9TcLA$1*;C4qH{Sjf<(s` zx~eW2C=VXfRkK85OWZJBwYs3sSY3@zIY=m4>1ykq5MAq|tKFv+(bH5&!A022{(0p-UXvN_Dk2_=`@k+E!}|p`ow>x z=mw8PwEOW+=a>8u>#1XO{?)G_$PEG?U_bVW9Xfy1wwY$Q%4ZjJ0r^-)9F(97{0<%P zW2G)=_4JUW`BpjVg7;#5Gpv>_ z_{dQbDp%Hx_>GoF-PDc54@hYAciqV85H5vvbs=45BK~*zLl?bk8u62}bQ8y5?ah2m z7axgjPnRa^re@Y9S`w(6mRtwxm3MTrmPptH*j+b!N^`6b71zzVwFEMIhHkD$1H=Z4 zZf?Oz5?deF&G+n$eGhMR^ADUuMP*M==!xwLKFxFs8%-mcsM9SfYHLlj zZ?|qql@3J7hjlAnp2i~E65XaeKUi%sT{7me7}Ha?c_CcpxmUU^L)VZPY1XBfBSCf4VX?$~@h z__-+E3ELnDhUa5->3t61#&31$_b{ze2I|s(WfB|FPvFuHCF5r3a?3&7_O$74 z@0m|*VY<$y9HcMN-93B=OUFNTdG}z1B^&CV=fZR4^j9b>oS~2x{Lnqm%O^_Nr+X!M z!KX**USI2t3)xhr57xb#d7gMonnKaBrtWk3ydA(q-gS9l#g zv~I6nj7UUW|Do6ITZ~_$)YR)Y)x&CEmfnE<57gm;-dOns3Bh&r#_)YaZJz5bb45S;g$4`W~5y2B)#L)Xc9+u&^vzHh^p3hy;Ge`;^Sfziq0+d&do8l zug~h8XJa}(>#cWQ)C`&rukBngQ{~yZdY2jK`r)tiZfmjpIJk(uelo=Dxm9}i7uPZW z8|_sNsL3{!{?!z6Q>xyhbWh@AODGg8==BZU;bM)G^o>NMQqOAZo8H1SI#*BM{P+@h zz`Y8ERk!smJ&O^$XVka3g&PgEDrD<_>N_qgPJHxpg<`4C`i}ds{Z(j@qVMv{fmruC z`tGP)3ekV-yMK&FOA8c=&e!!lFLP9@YUuk$|AuN!()U}m9D81V>iai2O8hTJeSc)b zLU=L#uq)_dw~{I+tWlYst+#G@OtiM6-nzqqsPq_xEWkk@lxRaKlqTqdE?9|UTpw&ngb~)(2RlI>FVyQtoUKTF{b>D&x1Pv)tLZ~(!_$Qns2o>WAqz7q%JrJqm_nM|A33RyyiLLT^3Z`+P-2OgL8lgCfPB7AH8jAHNu zx&r;oTKFxO>pcC;6?gDEEGPZk%^1o~zWRAhGVse5AN{hDP|@%D>21q8tislIfBot) zTZ!o}>emfQC1$Cr-}IL|@oxk4$wP~y>#pmQLl9h|P5Knf4qholpYjLTC0D;qa{#&C z8vV9%si=B?)^8gn5c~V4e%q4;Bs@H%-?0>)vE>kj%(;U??*CckXNyh0Q?lQ1pMIAs z#-({%dNvpOKw*h=d&Tfd&6~ zf~_SU`g0H=lz5v<`X_bjV_qNCKe6HcX7}|^z4D2_&(=SGdWVE73-xaa7nuHA|L!_k{2@vI z&2t9|887rdO6(#*^IQM3|1lDlWvjeYPX99%erC{Z{onhxVK3YoeIaP0itfsR*m|`7 zcg+%5*9_4A-hYSK*B%D){z1auC=R!Uh+L6q(EKeC5C5o8bkG>IzcJ>sZW?s4m_07V z40^|KVnf>*3p)kDf3%7M%cDUd!P83)b9XlcDm(C&WB<8C;(KAm-^| zs5(3vmC_Cdx1u`YZJQhFe}qSz+tlFc6NxHV4Z|NrVH- z=(KGdv5LWlMlV+2!ao&qe`iCJQn>N)LPN9PE+nk+HMC6cjY8rggE!U-$vw-^>2fsD z$DM}Gvp(U2M+`o-2NS)`F!XcBkUhU`=y$y=idgduzO!!=t9{B4sD&tfab6++dy^q3 z1Bu8l*)YP^3uD#&hau#)Gs5m>l_RgKJl4h#ItzQ(T-q7JuEB#X*lHNn98zmgMMI>B zXjm)85IgiSzIV?saa&JRP@)VI@4|-u+F+RYG8eXV*ARCbEnnBiFx8Ys?3~3geeGD{ z*XI~!G!H?I__D!fKM;JU8fHXB5TE(YFlTf=34L7+bN4(Tu||Pmex3eMv84}y3n}o7m4Qr!C zVjo)>)~#KJo$gCj?l9R5>u=?dIO3uqC1WcI{sD%q8C{7L4mWJCkW8Z6L&Ns$B}BU# z8FskN$70k>_tTYVKN!xMdfZxh6WS!`Ru`6S^XoJH!?O?dBg;7O)Fl5ii*c$H} z?z!h;EBr>oefODIn(1x0pZ6Db`<5`|ZHdG#pf(CwgQE(Cx>pT(DV34By;R8O3^P3R z%7n`;G(66@jNJs|3{M37WY%`Gtl>rZ(^zQ8HoP2*dH*}d@b)eqKpJCsZ-_*3sjA_9 z5l?KebTfSDRGCPhY4`x;LeusbK33wyN`KB$#XafvnQ%d-e#1aPbKbu+-TN7vdz7ra>Zw3 zktzp~7kp93=Dbn4qN|{W&PrqLTDWek z#aO#3{EFiXl`g%EwddP>G4BZnzQl)3Re3i>p{O?--Ini07Hl)R9jZap_n6ULlS{(e z9PkSYnG22X`=D-X>5QJ$e?e@{H+s%Ig^K4hV}qJ_eesO3$)Qcyu(iq9A|4NTql&Rr z>s`de!^YOdy-6%N!{}}608cb}gR%3P-VhAyRF3It>^5{72~MSq-Ryf_>)MRnYa;(& zvCPo|0P#=F{e7wE-or!2l+vS#5AZdnY_?)sVXQGF;~~}qsu;Ka;t;Qg6^hO?jXUsz zV?KDSLb303rqr5ZfCMApElVNh()484vikCL#W%@jyJdyo53B z!55-&rxo&he;CuZz#(Z0jTurNwxDGiGdDS+OCKv_uWl$5s(w&;tE2JUfW_D+ebtyH zWf67VY0NTir2%5cRmQB+vxwy_HfF6eV*#R%F$-JGsoQ6j8v~73R-hOi^{2{>O^jCx z>=!6%yxQ3TyY{vkuXe#~@UCvWRxJQqQ`Z}>>%6hiYGa~ftCF@_WW4w0B(Xhnj1N{E zKxsKy<*5b=x$j0}-XwVJ7G4V3+=dGIu+zpo`ww39tBuc4lxIhFsXYBjAs?{V_`Dqi zRHzVYM@;-MzE_ZHl8SUE z-r}uEer`jND|QnOz;{_HzxXK>o%WhEr=yW9PgKZ5qD;CUc)f49sZ^T)?2FKt%FVEc zoB&h#&=Blq9;s0DpJj3iLq*r&h{@?Ilwsm)Q>8f@;V18yYSs5;*rRwng+&{#X4kb)4=pZVuuS&L&C6F_H(9b zXkCO9r!bRWZUTf^y2=F?74q`KO~ax#pfugV@cz3u;K3FN8d8WttcK1HT>gHO(8(ikGF`s+ zf!OYB)74Q}-{50kDhFbP8>Z`pyRgH9Oxd$hbesFubfe2fD7b#68}?#aIh*PBv$sUE zUz+ZW*^RQ}dDER&`6OD_nC^~AMu9cV^jH00IOMjb2k>{o`vg;78CTRzcbf9L`XDQa zQF(HNLY95rPONW~cQifjkLX_gjp>OdlY|&Ym3J(rr+c$e5OGi_ma1iXQ3~o^|EK9? z_m>F98%^&9b|le9Fn!2Egm@<^6grhQeO#~+>z4(lPc<@$&3dOYZK&zXjCfQ7+)Uq^ zo<>dVw5i~O4W9YzKGV;N%Ta+HYx?_JbNupdrm1i-zPPEKLZL=8l`)xSHU?dM$=xi> z4j|TdkXh6reYp0ALOxeAYYv7%2Q@Mqo$C@M%`um-|8BL^ZL>ollJ%W!&86`_NTGVa z%@tcCNVoSlJKFZ@kgueeonlZ2Yfp*7}aR~~`A&9+t(f0NiP-P~$HDlzjovsc(E;tzkD+w|*AEO>{xZO$j+pVQ6l zf*pvvh~^HrKVq@0qq(yQiqEH}x${$ZWCNk*F8(g?BQq58yN}F1qvDBq4KjC2!z>ti zQe~`FA-~f}<*&ImwF%2L5Hd|X@=%&vzTc;mJMfkhfx*PMna;iCa04hkGgUn&YU`tiko5M>ZYZ%ki z9GPtF>R0- zy*zH7FtY;*r&pUNZe2q>a=t>b%yjeY1-*!E*<_w0w1l6+J;-`i?lJntYpdK>f7^00o*F7qBMGCH81Z3AOFX)#JU|y+U^Z9ZBs6&hyL%^w83;V$BEantR87bLvL~!Pe7N z&N^&P+mV5kJlcH31J|4IUgfcd<`cKzzj8~Mv+h+!2X-@`_q;=5|Ayv^wda#f*m%-> zDfI-x{4n#iA!~^3C~Ll+y^mO@JoC-NJ@EUGAoIP-&rz4DV!mI@0lSZ0njdwAsl5Mc zem=vd-+J6md0u;D^$KUivoAv(`Ud!&CRU5P!V4Dn56g*7J7e*H zY!Lguv3UN%4SzPZG=7AYrf07$O(%9FI(W;{`mbrwB|j`)XTpdxi^aPHB}^G$T~|~Tb>7Y8J@D(!#dUfYU$835>fcHrSF6|qW23e{`Ey7 z>vWYdUo6&3s6OOAwFHgHCRWeU5_Tk;#L6WsVJG0p9T!=`uA|!ULZeXdJEn5kQk56u zEa5f`O>TfCqE;-?=0J-r@+90sn`xHl1`zetuUp2f5unM7TgLoV3^{XO%a{i%knZ%g zj88@WWOlRIbRUR@MObFGLxPuj!7_6+-Y+m(7L;%&ZaipNupA+yjE_P#;(;Z>c>;=t zwN(b>sa$$WA*)!~rXGZ3tBiiDko$S53=UQ(MlZA^48&?fte<7^^#a^@sAbt$3A3iN zW!Yue&aqdP6)j<$0sG^tPnv}wj9zoM}dhfhbrMZ<7-v_k1s?^O3t=(aH(Hy^%Z(q#vViSZ_TxH9Pg3j0+@YwQp zssqxIR|;+HlubF{zAr6rQ+g8{T*LC|?QQ&iWP;`Mbx6j-rIydxc7C;d&H;bjuzb$7 zzy8DW?Ky6EYP97Sy91H@((mRh6iZ4M4V4~z;&%h3m+;Q_&c!PW>@4Z5jRtLUikuF;9L z!%FV|8rICi=0QF26zFf|!TvJ>!8jL$XA4IoqVR0~c-P)lqi`mIqW*o(D&Aoc)}Y|X zs0iE;j~U@NYE*bcl+xkBenDa3kx{|^%6;4X`!ceJ)&3cr2ni2r&g{c){`VnV(cAy+ z2J`=1-qlrY!2fZf#Jq{FEld3$r~Z3w<845gdUdzpzMq#|5f4cRID*$)%ptsU!a{ zZT)Y3o$#4J{5uZE5jeJ+pZywEyc?`ca&?MF*#k}URa&VIIr;{97I&lg4`|M|RfWgLeo&uNb%_Hg8ch!9KxNp(X- z2mDXXVwFewuQQw4Har5;0F&P@&_3P$f~-!B6(=4U9SnzqAT`cDOCy~E!o%R&;T6Kd zLx;htLJ`-P01_2D%Ic~P!qOis(smEi^xwFu^umAoU+wq*aV2=y-e$Y?+j~C@t+kJqJwE!Q z^;W!NA0_)p3{&3m#~FKcja5DqqH)s2>IJ>zva8?X_ zy5H%4mCXMs4(wew7M*C1ro;bfhu!$qxD=$w5qn$h-5I64vU^2)d&BXs-7M|j#w1AE z<0Dis*n`#Kj4O%s4d)&6`i~scBe|yCGkFHSE5!!5*7HIu{`Xs_SCfFVn zln#S43=Z>;P(y>g&Gyf#=I1mDr~Naw2G~Db-EN4Z{0y*Ld;lF~RcCrx{Xd=ogZ8gq zk>Cqlom77^wty{eulufa7dj$op+Rt{^`EI_cL;V@Yu6uk2N{mWI@w!~*AZws-bt*x z&B3IaT_n!HER#lz6RIV3>Mj(s+1;AzOzeGXzg86fwfDR#>Qu$`pWd~*nNjHTVYrj3 zc81}V{f_^mdj2Pv&-1eS2SbsCMJfFif(Z%9750DCb}hYa6=BqOoV2P%>o#_qHgT(I ziscl@6%T;~MF5t?pL|BcI6qH*h zyTILG3+ZDKK0w8y=9V!!jf!+=PG4Ki-lba zb4&R~L$gad7VUjb{4`>nQ8#Xh$t;VE%9M#gcM`pcn{*riQKvw&5#q}Vb zq|>Z>9+nu@RH;KJBA9;B#JzPDFymfCQG|@Momj4yksyP4!L)GOnz^;^Z-%;(D|%jQ zBakyQat-o>XtkzuqO<%#t+9=$hmm1vVMjj}#Av)ZrRnwVl>EWPouqqjVzHee+4&m5 z81w#)Al0?AM>Zegr*u=do8^k~Ru&oi zT272jn{+aHN-&^|_hU9&hHC@11R!LnIdC%ZbHH2&oT^!^|DenpjN-I^k}+;TX96Q@ zITWYPh(;(8Dg?X|x?FRLUDoC*atK<@707JVxL1_O2ULG+9d?pz$Q;B@HyFOHUY{37 z_E}F4+=SiX1^Ag#h1aIfx|!TYHNroiuzb5^93mpz!`kWBX8eCK!JUP?%IRh{$H%*WOdl?biF>eo9WF=a@uUA{O3@w1-U=GJ7p zozMEe@4b6Tr^h|JcXQz0okaU;Sfc6HFwmK$yF;M#?*NZ55eOyI z5>J3p(1k%U1T}NBeOAta-hHMam*C?~%Rnx6on5=w#jdm%g4gR1rsY}}qYU0*{D4QR zZeXk9p~ytzFNxHl|7wg5ZQmHFZ(kOZ(F2b7G#j6Y&8vkoR_ZWm-S7D4z`U+Gyr^oH z#Z>gm`(k$2%qsrqLWn|epu>&+WGRz+jG!_JLNdY}Mm3Y-=tnmbm#%z2qTanMGLJsB z2yAyf{F9iHpd^X-D084aSQWx~pdVKGsyGoPKNPof>Tgf%zn{P-p_-Rth0ePs=Pt4{ zM^GS`URf@vWEsDg3q4NyV)yJZ9~W{`yjUBCP(Y#N0iZO6X&v%U_FEQ`#fy zozF#jY^?PGyy_4vD>;|$P;XsFjQ_kX>^L+bkPVmx~_RzOm4JV%}~3evPQJ#3|JJPyHp7ZOuJsGJ%knIBV zHWH(gC8a`Zy{1({N5q{CK>qOB_96kk+^QWPG964M2T@)@Q`aftt&&iCA)5R{vhU3PEGoOsTeS>|sp{355&vNHBgABd_gZqf;jwaIOf6=7TGejj5yEKNi)VLvArSNX2@hi@6 z-cPJpUGO@w?%Onm;oNvFyc6;z~kyt@g z-Gz9f69%RkNqtj@>RXA16esEsPW<#4m6CN4QO8&k$t%IVBpUl+;36?{c(5LwiK2&s zQABO`Sd61xklsWjVh(yUBLlFPSId2PH+sLnMu^`x5gb99lRFlSs?!A zlt$#+l$d`*jgxMw6c<}*%)0^}!squB_09hrM#7$d5T;k(5En;k%=-ckBB`ebQ9w9} z8u(%$p4MXyQSc#RiTVbj$@p6@jMU@?;587V)f-PbxhX~( z4>%>C7^%;niM{VecGf3^s9+!BA%Ah=LB!`x!Vqs%DK+{-(xL=nrN*fg8GA^IOeL{z zJ4vhKFRGBoxsN76kQW91_xy~NNr=>wi4smLLcUI`Kh97wK(&vxBO zvdd$V9Qu*$9!Dai2FX1+i9=c7Y!Yd=N%qeqsr_)0*LEjXwyjF>a01EO5E~rQNKR;q z`47hz55Wk-yODeZMs{i+$tS{zb^1keGF+$q4vjsgXxw!`B`fz&@|Td;RR z5J22W*SaJaN;*7|XmEmbC(0AsXeAwPR5(YHE_E+)he8?$=W2|dMY_xRpKC?>Y7Qh? z)*wUSAQAz`$z0Da6P4;jR-bw#b}psDPd5{NUrr8HSHpaNQt@lYNNRGMN)=y0OfhJ@ zF`G&~av||PnaZTBBB47@<%`A=uUwbPk6S`w!+5HA{|8BKN2v1gnj~)ipP3z~>K!XQ zZ4Xs*4JPI|hpO3ommoHy9aTFI_d7eAsyCQLd~+?Tu_2el#2Bh+hkJE9uW?Ruaxx;= zI4)4hGai#uzYLsR3DkKfPN6o?!wi9nrv!{4cm&Mfj=MSQKCYAg_D7iiENZfLV z+#e&tPFPF!_KEG`&%>xg1m@0b)FJ5<(Hf?b^~+HyqV*d0rcsAW5k#Ha zXoyKtxF-Ffe58(y)|Zx(RlxtO3C4&MyK86lTwAm;ltE(?^&X)-qiC1lG6q7 z_dpNp%Axdo7KGHzh|7V=HUl(=`-xGPAdos~VO9tdj(jh&il zeE5@m;g00~K;z(X8bi9NWRuovj4GjVx1&m74OJ;s-a&o!=WyZY8WVq0UlVR%aBGcA z@8=Ww-x@`I=Sd{um(l=F`0wI@G~h8ZT6|F&o|QtpWI6KhmO`Sko%~<8k<`yXfnimU z4HGG-d`n^-TT{^79>l%M(^!lMyR@6eJ}gYcTG6=W$oqFnQE-il#Ba2tV9dFwvz>wy z#*;8@q2Mp}&csu9Q}ACHNu8S%8e5t;hAp2Ge00KW4Dqm@G-2Ks;w~99A%D(18>$rE zW}2Koq@LSV3h#+D86zf~e$Wg*LCotvnvvs2Y(NHx@Aa8NGyUC(Cd^XF#*L(zcD%v% z$m$y+w;P3DNW>g2phcEr(0JQvksnmd_6@XXYA&&u$F$V>Fd|tTMY?YxQ9FQEC{-}W z@w9U4Y$CtHw5nzkV(yN#s_l1T-OAJI7I@OyjcN6+zeFEr)4Ct0iNBam>!-r~W~GpQ z{i!J8lP;3VrE6(}{~;o4e~QZdOybU2ihb6ZC?lG-WpQHvnyTd8ernvjkG4PfN#ehe z6z_-|YAa5k(OR_2A`^W%ZKqugzY~p%0THRj zy`^10mJolOL%UbJgtGZSyHCSU+cr=sJR8&Az8i`5A5qDgx@t^cr;;xaw7<3oN%dlA z|FJ^E+g;We){XW*L}2sqql8vI#BSfD!@K;5mf9;&(#RDg9@bSUIlZH#_z^_K4yk0m z*(xP-8#?=;3egBo=R6J*rDf3h4Rwj-J)-k(5xO^5r}T;AiOa)i}J{GSJJ z)02|8(-N2HDGer?@s6^CVO-=(IsQo`p0%czXOKnb>NT#6q*rU66CZJr@|x$6Fbtx+ z-jLrnYtp}=jOf}b#%i=7c47fz?q#9>yIoWd#J4+4U;Ptt&k0PwFPo@;A!a@>fLN^< zX7R}+UL=qetjdTb{b2=nJRyFsDfkqO0ketUH-gW=U{+}NTVes_Rf?^fH0DIG!oCot zix09Q_`9f6h!u^W4gZhvWThOS>u-m!a#P{A(LY(aMU{x_53`C6t5A5{WEIP_Br!aS zRT+2=V${NF8vc=R)3G{t;hx=FuzF>n^GknV^><=!x23TL!B9<2#<0ds>Jpuw!J1ra zg5(peF~-1}H${3LlFV9Mvm7agYCZ1h=*f;o-N#feWhav`l^ZSWR4a_2hkcNCFnzPe{o`0l9nh zwaeLqQB{Z+uEQQJuS9I%e)jkPY{;V`dsf$vn0@9y_RI@;J7@!Y=7YeqzW{r+x+t+5 z_f_&LjoItgWl2nmWN(^g5}D4h+?4Gkjuc_nDYiD+0RhCU+6CTIWd*&RA?&uU41LDt1Z}{l_(0IedlZk zz7X}E^Pk^|2Q!U}9Jz9ADAC$WTvr)!;_!BE*pr`h7ID)JRLCw)+@h;bg5$*lOyT{r`Al+8vy|)x0KEzGqng`t1 z7(+bmGanR>r1U3}537m*v#~569*Tfc`91eH;DYDoa{qImiGmLCfFhlV-M!2MO%L(D zjt35#iU`+{k1mdp-1U(M9WF@xmoJE<^y?~EnE3CuJji|+7yf;OkDKO-DTwC5s9Y)R zEFT}5PJDJL9(E0{=g#F*rnn$mP2f|FjQEEmeCFb_#Ow9v;Zbn69ryX{H!FxWFV5#Z zjD*|H&^YmlN|AGe&;NirqTF4+b^!vGPYhp|Wh43)&+Y4ejz_+>aFsD(e8cmOB%UAR z8{fnbtM{5m_lqXJzAoRK2P^*eoyP=rL8GA_kKO1;;!+VF`xQ-w1+)2XZ-G8QL%!P& zIpcyC-~GNO(XR%4?=TkwQxiJ_v9xsTM?@{f}iYnmDuu<{FE_>i2kbN=dbb8-3E}iyD?C#UZq>X*UK45@)YHjkg3jes+6ug29g`Pl<2kj(099BiMZ9mKZcDf2yv4#o2G zI*7&2r+C`sND>_$YwR{juwPw|0~o`#0w8SR+8q9JsZ4Bt z5B~BP=JH>RNDvh%P_LPwlvP;X(_eh#8=l(0?59qTrU zf=<0i92+VMK4?Y!xgm_rxG`VPhh+y z*NRGY5ih#`(YP~LRFxgzb{j?Y((%w0?M3y5SKYpDbt`Wn zn%Ph|w$C9pv4N-;_6TX$Q`Fx+3_3nUI90n!BFaNJK}tzJUq#cWeV}l{M9ZrSNb-Iq zTvw$M?=VHUHAb~-n=IUx_8?NCgxg-~lIBzqsI(TBqOIs(Ul8=_nH zI8-d%M7K@rNvf7EdJYaJ@o0=f3s2|_#vLW!vitCKm0rEoS2l^6dg;um~s|b&UurVmWo)OkSk_~;7R8D zhz0Y}P-c#%wUkM$RgW}L#^cEk6 zi$k9uAxV9+i=#Ss48;U-VoU`7kS@;jae`6Z5-CYtQ1APR^EJbXjrbzc9751)sV&mH z5{Po`B7Ma(sO1=O5#<`s{VFbZL2IpkD{8niA^yZ} z?H7;wW)ekR6^{}slQhuoD6-@p#GAbn&jKqD`+7xu8SIM>mK5Lg5SimIi|>7H#8-_J ze@-EwtO<~WM;qebTY+uCU7#!RAH_g7FkCX;$X7OBCDZ&o;y$uuin>KSsJv8k7?Rb9 z^(w`V`%=*#C~EClU!qsp&z^G4_mD+wpBfEJ;$#oJ& zDs7A8z8fQ1%PO@S+XMPPtD@AUBHE$uZzOMT1dv^xlJ_B4chL;V$14?0q-K&IvLik2 zCi%~}OYHYyX=E>)SXm&AOe#kr^rIByjiR&t1!>IRd^vtx8e6Cv@d_KIapz!5Kh8_R z6(He4UZ|9uTS>vEZ^3vwOB15c+Tn+Lr7-0zhJ2z*?s!QG+lHj^d7m_SKW=2#9BKOY zB5=ck(u`zGMcG7Y#yN~oH>(tGT2GYFLkeGph}SAtiumkDtgENAXbsZw_d3#|-Dim> z2TF^3hmvsIBQ0M8TliB`TD1%|w`L}2cPGi~q_lb^ghl5FY4!2`c>P&gTX8G#GBMKH zsC#J7&_N21)xmVZ?e5miC3C|6e*lqhk-1Y|KoJ8^@{?t{KvSkdjzWI3yh# z6h~Biuf{-M$*#U(AFjT^1~{t}*|936!W*SyKfe(Dtf^8m&Xkhm%Bb6`OG(8sgp;qT zWFa@Cq_V4srhZV#CMKv9AMrWp2!3~ybliv$Ec~Bz+%$w(qnXli_ew}YMeWk@CrCb( z>Pg8Z5u-=7kdpIPJlZdpQj_48{aiK9dm^Q+g$f>+sZ!FtmeLoUMJM!*#{SPWrevsO zVShAkeyQ<@w@O~={|qRky}o15QV*nBk2Ja-lhR``C7pgq*Cwolg83_5{{&UMSZF-l zLCU!6gwBYsbi3YAV(0!-DT2pKcS;H*r`yuqV>uY&CmKgA)@YAW$p(&9DRT5GC3}(5 z(t~zBB=McngExPPrsvzt$tE;{sXt1)+9GH(6gD7brPc*53(7Qem@*_bwnK7>0pp3^*&vsgp5J`BCYPDp9fgZQE_(}l zz zmnmvLs*@Y+L{{DQQFgw9iSr2Tw^Fw!X&xzI)slyqvU4Z z+p&fkDYte^#e&H?x%IjsP-5d`*Aa+s53b7XI`>1VXp-B1K-~JzB70>)`yPyzJ9e%? zBCV?2u}dI{^PlC8qr4F?cXPSpC4_<2K^iyrRLRQRP{}{fRVh52G~PcgcbSe9aIvM_ zWyV$Fe>ciqt2huZ&_?zSK$ZWWzua>L%7txKjfcC+eKO7wpV&k8-B%bzb60ste129> zl>>UNv?I;`lmpNL7Kfk8fhZT)tZypC;aPGZZj7~FDv$8UA=YcO#+zv>`2&qoudDKi zzIh~$pO#1MM?iFm))-nr<4!MmRJsc^VHu6x(=~2cEeBn*Ba|PQDUVqMIndQX4q5XF z71>pJf+O62T!6-Dy;L$klg3GLpQ@@}kRaFjmLb09wPY$=|h7!d&%L@v&hJbMZSD~qf=deOfIE%_|vX^{hi7$!$h3)c@n7YJxgnZ;8!ocwF@=+*5 zDibE390o~P^)`sPtyTy81kMK0$*uN4PPUCebG)9M?2oWg_P0uL(X8=5CzVpeY>hpq z$Y(mdCaFpdIkf;Dpz2OJZEY;^kM{fWh1!U`Juhh-Ur(io%9Jno9w4E-m#_7xOMGv# ze0>Po|3}}*8KJX?Z%>mm9_>Xoz9!$!U*mEJ&^RPbV{Ep3yRkd*jv4aZ5$;GOf%4tC z|B=+Xqx_&kEYY@s@-x$NG)$7_$Zwt9vy)->vQspEF;l@$MP!= z8U9^Kl&E5y~i~s_Ltvo$5i#HCchg52{?3`{B_z-5-;}3e=9_xZyBgkJRc$d z>-7|SAl@hv-+@{;K#_kJLck12Rph^rcHLbRec=caNwXBQb61jj&rr-RDD9#uDCXRj zkP9aj%cgYfQ&1GkHw4Z{$CZMuw<2ptDTNm7B{G*%3U`2#>-tV9GB^X(c}Iy70F8P5RZ5kID-B&kh`Ab+Mn&U@ zC0|jRNhn2|c`41O*fWS?4=62)4{m*MbqOSHNlJ&bmGBm>c+7Jr_8?jD^qx#o^P-C9 z?j=N<3aMn}Tr@`fQatVW16x^Kdn3W5l0USm6tBHhO6~=fPOsyL7yP1hwndWUdr0XV z`3dV2bCs?`VI$7DO1I%J(XYI$l2;p|^oT^${K;9RM>>qOTO*|>I>Btq3#GTiGicv9 zjbE*b-FG@-a_1{bU;0dRWSi1&H{?RnZ)HH!SYn^KG9WJrE3Wrc^6a6?kV55&Z9S|E z8TkU%zee$o3qa3%t>XU+#50S1qs1 zXy!mn`k>5g`vn*Ns6-4${i2Ih=6o4XQiILP+#<-AUfPiS#5D5o+B%(&p8nHy{N2y7=*UtD`m~9RcOTcD(gpk zlIZb3qy6VAWrG7w^mc->Asii++bfif;Wdd4u2VMes*5c_F&dA5RmlPlYn=C69Y@w3CAr=38SB~vMT=0IX9Q%71m7I@Cwx*y;p>$W0vd|WswplqHHXrSWCCcel zSXlYkPf3omp`aSBoGFat6gO8%nSv1SR!O;53IXm}4dvP_G)zR;0_8?zb7EsJD>uU- zmZdSut<4Zhoo6Yx{>mgi)K@aP;l$^fDjA_ANXS+tBRvrPh-FG<|6w@sM9jlWZsm&y;^d7AQOTU`>j)0DS^5txeC*68J_@o=6> zalEDSc4%3&4Mr>PHb7svj#J)$Ux57$?UfI$5WqaWl`r;jFqXrAl`oUm5vvlde8X!| ztF!VeXDd1}x0SzL3!}E&qSMdcO5FX4&ftkB8hu`884*dm$vKUGE9z`%5k#pTx&kZl zIr)#S_$ov?{T5xB$2k9^Z@My{5a661>&kyK5bNurtE6DrvBL|Uy^_lbEh={VT*=9UI!-l$+TTY=}kf&?adnt)={yMiw$4Km%uIrG$)x_z9UDqKS z%Erx2=PC8T7dvTu_E4vaQjgCnMb|63PS*m7&n>3wF~dr{<~ogm8+ARqJ0pig>3n_X zl3*UXAx$AXK6~kgwroihK3+F86rp(49Nn0&7;?G2#_Jb#W4&TcEr z&yq>BJ^&&B`KM^yK3X^F7)KiYu9CZb)rFOZ=Bsi>r)s{3A9P_WtB`0@MHjZ$m8eLP zZgNvZyvQB8$$dClN6U0`E2B}e^qp?ruDK%-Bt2RR*n8MG;S}ai)}KBxHUi*J2MLUzwrZId<|c$OODm;+y*~w zwOzOKGI-QOr8rSTw<{XkheQY6!PW5FD_3-fZXk(Nbk!X#?}K&DW4fakGl^C;R>_v# z*SPa<^Qf0;_cA2gyY3d{l}qLU(D58@4w&=`OeYfT3-ryZjjbzs#h& z>g$6%e@mrsPu6ANMnt+^ms$Tku|<18I}X-7!2x#ToEo5#QKBx>T~Dlfpe}O|lFT@Z z?%o(&aLPm7qe|XbxpCD!mWmKdEv?Hc9!k8`1zpx{So63ix~$g+iBIpPdsZqM?Z=V2 zoci4%Tso-~UGg->-_&@tjxNVO0CIQVF5OG>K%xfkbgzRUAR2n>a(&AYpVCYB(H)^U za+U7u)h5J7zSn*4U`2!Uq3%~6B4nc`y5CU|*l-b`QndY{=T6sP6TkJme>U-oL-eBJ zdLq|7D%qr7DuvfajV}l4?MlBG^rW2i`ZDm-&xv~dI0O*qy(-0ZcfG?ZxKT`wO38bU zz9{rO^WUwK7qIE8DWSyX{?pg4Tam=;WPKgw5n9UA^>r2uLFebUzRn6rufO~B4e}#w z_d6>2<`H_Q7D=i5uLcNZ!+HxdrcBo@;J-6#;6ow@0+*Ci~K0@|{Ci7VqrJW_0Q4jbhFa4}Lek4^ts-HV7nxxuK^b3?vM4r#}3$Ine8gq(%QFJcq z{m=Tv$q=0-3h5W0!%!a^t6yF?j>Oo*`c-u+k=W5tzpexxD8f^}ZYOHTs6G1izR>+a zFZCPdKo>}$p#N9Y*Ke&DOx#pXzbzWZW$@H*OIk-fTIjbOcS9R7R=?}^ zdPKmxDn;JPyO(&LdRG;;|2l4PJD#gS>Dy3ly^-pS}A~GfFpNtw#bfdpMdl{_X zZG}qFah5&@J2qIVze=(3hyMAM9Abg-`WJpN#7ivKzk^$|V3Yns4S3VT$|||Xc8$|t z=N+l2<>EOh5zCK^oJuud7=&|t2P&sW{AQgU-On4jRu_s%g`7DW-=3^mv~F=J z95HwqFhWuNRSMds@!brSQtz{dPX2$P3ELaG{&dIwr!p$VdnZG8|5&Vhgc*9i4@5I7 z)6l2i_>cGCW1^&qhN0*=GuB$; zgW85+*;u`6v)M5GJM#VK;RgSJEpWpphJb8@>Je#%fX~iI*S`&c?Xl0j?Qk#{+-3;u zfNJnYYoj4_ zZv=_BHHK*u2=zdkAv^@zi7s?B%uaPATCO)l#MMD}znNkFDjBiAmRJydV_0~1 z6;yPBVUcqqSQqk_K)y#AXeKv9>hCeU{Ly8f@6M>=lXKKMdOk zMUm92v?0D;z8=_W*zsgF-d}ClT>)O>`d+2zSkJI~-(I4Zj)p@&?C-E$$YMA?b0`9g zr{P4HJ62qh3@4Z1&i5#W)BT|fvfCPxdmh4te;bk?!kxC1F(m&OZ;p@5CQ0H1c)0sn_);j1$p1UvP#K%*>Jtbba;)c;g&t-6SSPKA;T47 zad?6uvs54A&Bq(=?MGi={!EPtUkwkACZY~77_uH_68rbe@G=ttD=kSSpIB0*c&szL z%*w{D+*^h>+!Y~wmf`IUADpMP#)Q*`_wz22=yyS-BpMs+A9}hHtKZF#*A^$v?rr!q zKNStge}+$sQ5Q66VEFU`Z8KAM!#C#;bVL>yzO}pw{rG)gCNw79}Ist zts=I2v*GVejL^DZqZGV?=;S%0;owT5F`bOYScq1aJ4O?>7f^@#Msp=3HSa!lqj}6h z%uQ#bZ88Fk<7Z=mdEqFd7a0pIS&p>1)L58?5wCW|Shzg0;mgm)B1JJZTVENAOdL!i z`VI)8vAGI36bu2eUt#kZ(2v9x8#o;75Bh_vMM* z%bcG@y!aE1!`f?%t7Z0z#&X}b5_1SQmamga zV!#}glG52&u_dPVdZw}B0=VPT^2UnGTVUg)S>uFK8tuEz7^}?1&<{y5){Dk+V7unV z260fWDgH*MS2vNbi)n0HK;uA9l|0YO=v=%ziM|z8O02lCkrP6!d4{ox6iEEiDP!}y z@S?N7jV({DLIj+ul82Wvwst8*?AmCf+g%@QnCdrAJz(ok7(Le(CgJl{<8N;CJh%d_ znRmuce;kN;$wqH99{GUkM(@0EtX=6{2%9M^xOW7X#Gf|-);w#(-Ty({_l+bDAaa3(Yy1+6T zC$v+^{GX{5(O$;USK`o3+X~uoaEgqh|5;Hqeli9<{tIt-Y7Bl83rW`37*gjcR&u%; zLtKy*C(JR1)xuQyc^M~XPA0zbo^i_6m&6yJG)}FLf~9S|O15yeO5yq0XvYt4$jR9_ zb4mn~REBYGA;bZ3(>Slz3!>VejPva4?-TWMH7?qQxpWLLE^d}WqHcfV+M;l`Td$34 zJvO4{I?lLh!VYx3VvU>oA46UL*BJYs6V`eHjd6ntW8^*=<3=I51mzgx;T=MrY>aOR z*3UNX)Ey#fEg5%~Iz~Kxj&bK$4x!W7xHD%d@$()=`|i~UjV)7+`DCRls1zNz#=B*V zdt_YDu)w&tF6Pu_u`#hWjI=^I#A?>w-Q2+T6xl?!97=9=+- z$v6_RV~zLQHz!g3fib5}1Nie?V~!nvuU5(U+%=m-#uMYq=l6*ps%Xq5e1D|H`2HrW z{&o%HH<#VS+d3G3^*Kr0K3wC0J;qt62o= zjKhro67Cawm0%+GAH=iPnv{0XiZe1zy5BMyiKOv|gGv7nb3As0$q)u_sWi!CEH{Rj zZ#k36Gz%N0R+>z6N5E}2sFZZ^rlR|EQ2)PLVk*}0H5SFsno8}hOT14tQ<(|4a7H~- znHdndi3?2S3Qolw3RA^DFxHkvQ>Du}#Ols5ReAXX>zQU#)qqfRIzvtM3K~e%>}YC` zhln@#k;$b?2%1=pObrXd29`86HSPm>e%0I5_(TS==W9((&P~SpU-34kCa>1x#Di6e z_VrB7is8b?(oHS?RUtlmqp5W=1jC1Dle-=M-N4c0bv2ae-6T`T`JeE?`Pc$x{bUNt?|3ZqGL3BsDb=R7DMUiHtJ2jJHs~3?H_tR}XLl?S zE2e1=U@K?#o2I?agw4D%O}~dHUsudD+mb}=_*m1N=!qnbtTWARISMV__olga9PqaL zO>;wn(btnr3&&*>Z(Yf>Xg_`oXVsgQ)airR{nWJd6l%H-EltbxoG8cHw6YO&LZ`~6 z)e78p@juhL5QOBqcT5`=g%LY2TBYRG+7xa2M_l|gMTbhna$-!Iqu0WAYG_;*ZL)8< zn?X|N`=o%3F{z{d+go7z7z7k3@FO_1xuC1?5C#O2e<)wg6V?^or{GpOdkrk5Fgsl^wFylkulZu5yFIK z-ZJIg3?)&|X!?{5V+=l{aoR1@m#R&P6@6#=J{lENRx{K0iw0utj+lPl#SN6NYx-rx z6qbt7Xdgey^y?BrY`p%R5QPcZgL)z0FnUq9uEDhq-nwoOf_DbM5AcE9G8ktdwM~y~Ni})M9x4 z0f}~z8c!e5m|NOhZ{0prw^?QOaPSLuU__an4nnk6eqwg1{s$s5$?P)kEE<*v z&5df}^?}~zW{EJyKL^dN!f|8Q-<#XC-AnX$nYnFYcM?BWncY1QfJRO>cZ{<8KnQfi z0XSf?x$B?^;)WD+*ZeJ`HF}x7YoeZC(Z}q)Y7Dky3^DhtgA1>3Ywp>uEeZG1DkbN6 z=H7a&lx*K)_I+0Yy`kYCx?%i0SP3nis$gYsj=66*Lj2Ep=Kek51%JAm2iphiC80>> z!66aoNP4OimME`Vi|f!o2($(&q(k zUj8AKsDGq+b-AtB@91h?i_QoSSZrRGc9n$ZF7x{85$GMwP$_j;Z(jfV1R4~LRf?T$ z?ApPr4(9cLAr>31HE(!}C*82XytNaCs?Htr_Bs1Vs+nqzFFuY$s{nI+$`kbM+naa% z5s=&GRZ7Zg^X>&`G_;LSDK%SZ-kprsJ^VHPm~Gyjk^vhiZ$5;q%I5agxYGW_d}wG} zY;G%RJ`@hxx0{n5f5DI1UZ@nwZsz3eh~;n1<`g*#J0NjXW`>DZ7>_Ab8KLDXFH zHT-Op_j{^w{xtKopEyCsiRSAa9k3~GhxvLZSbvR%<{Q<9VTb2x^G$<0(U9}zJDzz& z`W*9};W%-j(&jrKG4wX8`Qf`W`0dIg^W*i0uwOvYczCT!(ei*fYsM_-{}wyc12+4I zO4077ISW4(5xKj}FVI$J`)nGI_E0HW#h72V_ao7GgZbr<2543%YYgqFapx!V%lr)q z!{(b`w?xGBo@;)czit?*S1G(!Y8=?s{BCIp^oB9RyXsH zcSE2R_o(FEBSHHR;+yfs_p=}-JVqeD`e<=o`h~di z$I|}8VKfrATRN1vO#E`N#l!6pnpEd4of^REeL^kX^O42_SF7YVPg=YozokKYEj4%t%PG!x|?HR4HhJWyts# zG?{x@hO)^RTCP$OlP$xZmqj32Z5dv8DE59evIH3L_ggb90r?eB>tIV@M?|_}$2Asz zXbGG!fcV?SmY`KtiC4B~TgHyQhSl!+mT^uP($ZTs`jI81;$Jj2|$TBThM)m7&nU&w+xOmI5IPeD= zk5w#-$95+EdbVY$P9|RXKg+V&35Yja8d+A1V%VqW26Av4D6nR$2PJTXWp)0EE{wHo zsOL<~>9-{ozwV=5?=A7(Fy5UDE%B3rNPKm+9BP0N9A8(ZRHU!vP`}?q0dX2buUQVA zJB)pQQ!Gb!Bbnumvm9?z0{Z{PdCLihGYBAx&n`eP}3-vfO`@P2$sT%YzAVXq^_Y zJVxZ>nUyVBCF-IR8ez%m+yy%$9%($`qLQW6QYom8L&RD+84M#z;+VZXWIdr*RSbly)h~AZK`BiouI;!g}zrVG_Z`S5n{;tIL zHtALJLa#Iq`e=R>^>Z;oKUPVr*fnxuPS{iaORJ`M>C75mtxc zD8HBAwH9Z!u`S2XTDENswBegs%N;PFFgao^KM8%oPK&J-3PytEtQF$W@4KM0R{94w zom-;?D3KKlV;YYH}+y-BGKC1 z(Gy*+tJda8C9v1Sup+ucQM>b1Yn!FeuKI3P*PxBCEsNEyw-2$Qv#sqiK9RV4)!IJL zfrO!u)#F|s*0h#dJ6dWWDK4{ieC~v8LXEARhE{>HE1^=H{$TAgHk?=s7i-rf*tq{Q zjiK{Yic@_wK3T8QF5W${_UMjWbuHD}hr?vde%5|3kqS0#QprkRQ^_CiS1FP|YP?t1 zIwTBEc5b=VuN7u!)_$ws9Q>0PPsQrD4_<8Xvj+A>TcKSmYfvGWjB%fJOmS2LV~beF zWJMEuvfMhZkPmX#ZHskWAXIqY?HcEGum)H0!FHh;*5KvnMVlk7&nFrhY_#ctgB1IwtkGUuJc0Vt~Yi?7tf;hYp1L+3lXR{w714J#el5V zTertQCF+}N-5-d7`WS9Kkc$~oHdqfCI}<&3vmVOV(#zeg$MTTcnh(%8E6kd-I|ah8 zwe`3&&NtzL#{KK8r|%*v9ouG2e^?1E@B!9~F84`l(aw71*lDs$HOE?S42(i1d0@SH z>mV`rqt-h|yAf;O%KEUUlrs0tdG zYSZVhjrokQ8TYS5KjgQ~b{tQz?>}3y7Dzos+u4duNA9fg*j8%zP!#dMY^6OgA|Zop z<<@nCvpd_$WpzQpHq}-!8tP+q4UGq~ZI!2_;yzZ{s*ejJaoX2bqYTco_Moj+kPCA6 zKbzw%bcR^;HCqD{qKHcio0H0|Hm8s4u;Vkz=8U8-wfJRo`GX5S_Ovy9ij|;CKW)vY zdEytdKWuIPi-5XFvbmlQBA&Cw=3aULiH-Yg?lBR#a95lA(@f&}Dz1j2T7A`{u6EytNG0q zbo>@cx{9`-)2=9gTG)baqFeAVKqdEhrO{qP%`R#=d0YDLrg=W+3pp*Rwr11Mf&LXM2{6_~dfc_UtN> z{GJvn+1k;zS1s{7@!I8WuVNvOhIg^O`q`1VX_+l|wgak)jv5bVsT3{0+j8T5s5k4) zY@c%PkyK-W?ek42zo)Ub&$qyA$@Vz|eDcipIWzx#H`}+DxZug=wmqJK{=Cm*|><)9T#wxC=z{@2z`^UbrHN`kDl(>p< zN46$R;^Wu&Dm*B$ou04kkT|&;zak}K1J@UxsO!%=@Wge)xI@u3#&qtsrt^AyZ{!r- zsY;@L3va6=7LMmvt0m6A&SjqX{3buh6YJmReF`T&c*W})5|4f6)k4-h_7%$95dk7` JM1U0S|3A-n-xvS@ diff --git a/lang/qet_en.ts b/lang/qet_en.ts index c48fe3636..d01c84aa9 100644 --- a/lang/qet_en.ts +++ b/lang/qet_en.ts @@ -512,14 +512,14 @@ Réinitialiser à la valeur de départ - + Reset to the default value Valeur actuelle du compteur. Saisir une nouvelle valeur et valider pour la modifier. - + Current meter reading. Enter a new value and press ‘Confirm’ to change it. @@ -1278,27 +1278,27 @@ Note: these options DO NOT allow or block auto numberings, only their update pol Enregistrer... - + Save... Enregistrer le rapport de diagnostic - + Save the diagnostic report Fichiers texte (*.txt);;Tous les fichiers (*) - + Text files (*.txt);;All files (*) Erreur - Error + Error Impossible d'écrire dans le fichier « %1 ». - + Unable to write to the file « %1 ». @@ -1993,7 +1993,7 @@ Note: these options DO NOT allow or block auto numberings, only their update pol Numéroter automatiquement un élément undo caption - + Automatically number an element @@ -2563,7 +2563,7 @@ The element's display name is edited separately in the element properties.< Coller depuis le presse-papiers - Paste from the clipboard + Paste from the clipboard @@ -2815,7 +2815,7 @@ The element's display name is edited separately in the element properties.< Automates (MAE/SPS) - + PLCs (MAE/SPS) @@ -3334,12 +3334,12 @@ By importing this file, you confirm that: Insérer un folio au-dessus - + Insert a folio number above Insérer un folio en dessous - + Insert a folio number below @@ -4976,12 +4976,12 @@ Please use the advanced editor for this. Atteindre un élément window title - + Navigate to an element Nom, label ou information de l'élément… - + Name, label or information about the element… @@ -5612,27 +5612,27 @@ Please use the advanced editor for this. Mettre à 0 pour un chiffre qui n'avance que par le report d'un chiffre cyclique suivant (ex: le "0" de "0.7") - + Set to 0 for a number that only increases by carrying over the next digit in the cycle (e.g. the ‘0’ in ‘0.7’) Valeur à laquelle ce chiffre revient à 0 en incrémentant le chiffre précédent (0 = pas de cycle) - + The value at which this figure returns to 0 when the previous figure is incremented (0 = no cycle) mod. - + mod. Format d'affichage : une suite de zéros donne le nombre minimum de chiffres (00 = 07, 000 = 007). Vide = largeur naturelle du type. - + Display format: a sequence of zeros specifies the minimum number of digits (00 = 07, 000 = 007). Blank = the natural width of the type. 0 - + 0 @@ -5668,7 +5668,7 @@ Please use the advanced editor for this. Cyclique (modulo) - + Cyclic (modulo) @@ -5677,7 +5677,7 @@ Please use the advanced editor for this. Alphabétique - + Alphabetical @@ -6712,23 +6712,24 @@ Do you want to save changes? Rapport de plantage - + Crash report QElectroTech ne s'est pas fermé correctement lors de sa dernière exécution. Voici les derniers messages enregistrés avant l'arrêt -- vous pouvez les enregistrer pour les joindre à un rapport de bug. - + QElectroTech did not close correctly the last time it was run. +Here are the last messages logged before it closed — you can save them to include them in a bug report. Rapport de diagnostic - + Diagnostic report Ceci contient les derniers messages de journalisation de cette session. Vérifiez le contenu avant de le joindre à un rapport de bug public. - + This contains the latest log entries for this session. Please check the contents before attaching it to a public bug report. @@ -7685,13 +7686,13 @@ Available options: Atteindre un élément - + Navigate to an element Recherche et sélectionne rapidement un élément du folio status bar tip - + Quickly search for and select an element in the folio @@ -7725,25 +7726,25 @@ Available options: %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content - - - + + %n font description written in a foreign or corrupted format have been restored. They will be rewritten in a stable format the next time the project is saved. + %n font descriptions written in a foreign or corrupted format have been restored. They will be rewritten in a stable format the next time the project is saved. %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content - - - + + %n font description could not be read; the default font will be used for these texts. + %n font descriptions could not be read; the default font will be used for these texts. Polices du projet message box title - + Project fonts @@ -7950,7 +7951,7 @@ Unbridge and/or remove the levels from the affected terminals so that they can b Exporter en SVG - + Export as SVG @@ -8430,23 +8431,23 @@ Unbridge and/or remove the levels from the affected terminals so that they can b Exporter en SVG dialog title - + Export as SVG Image SVG (*.svg) filetypes allowed when exporting an element to SVG - + SVG image (*.svg) Échec de l'export - + Export failed Impossible d'écrire dans le fichier « %1 ». - + Unable to write to the file « %1 ». @@ -8684,13 +8685,13 @@ the conditions are not valid Enregistrer un rapport de diagnostic... - + Save a diagnostic report... Génère un rapport avec les derniers messages de journalisation, pour l'inclure dans un rapport de bug status bar tip - + Generates a report containing the latest log entries, to be included in a bug report @@ -9817,7 +9818,7 @@ What do you wish to do ? Numéroter automatiquement un conducteur undo caption - + Automatically number a conductor diff --git a/lang/qet_fr.qm b/lang/qet_fr.qm index 4ba95bfa2307c324447285c9bb0331326c351049..4e36f8350619c3c57631d7bd4f659f47b91375fc 100644 GIT binary patch delta 22835 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 H)5HG(BimYH diff --git a/lang/qet_fr.ts b/lang/qet_fr.ts index 1c5910c5f..85668469f 100644 --- a/lang/qet_fr.ts +++ b/lang/qet_fr.ts @@ -512,14 +512,14 @@ Réinitialiser à la valeur de départ - + Valeur actuelle du compteur. Saisir une nouvelle valeur et valider pour la modifier. - + @@ -1276,27 +1276,27 @@ Remarque: Ces options n'autorisent ou bloquent l'auto numérotation, s Enregistrer... - + Enregistrer le rapport de diagnostic - + Fichiers texte (*.txt);;Tous les fichiers (*) - + Erreur - + Impossible d'écrire dans le fichier « %1 ». - + @@ -1990,7 +1990,7 @@ Remarque: Ces options n'autorisent ou bloquent l'auto numérotation, s Numéroter automatiquement un élément undo caption - + @@ -2559,7 +2559,7 @@ Le nom affiché de l'élément se modifie séparément dans les propriété Coller depuis le presse-papiers - + @@ -2800,7 +2800,7 @@ Le nom affiché de l'élément se modifie séparément dans les propriété Automates (MAE/SPS) - + @@ -3299,12 +3299,12 @@ En important ce fichier, vous confirmez que : Insérer un folio au-dessus - + Insérer un folio en dessous - + @@ -4945,12 +4945,12 @@ Veuillez utiliser l'éditeur avancé pour cela. Atteindre un élément window title - + Nom, label ou information de l'élément… - + @@ -5581,27 +5581,27 @@ Veuillez utiliser l'éditeur avancé pour cela. Mettre à 0 pour un chiffre qui n'avance que par le report d'un chiffre cyclique suivant (ex: le "0" de "0.7") - + Valeur à laquelle ce chiffre revient à 0 en incrémentant le chiffre précédent (0 = pas de cycle) - + mod. - + Format d'affichage : une suite de zéros donne le nombre minimum de chiffres (00 = 07, 000 = 007). Vide = largeur naturelle du type. - + 0 - + @@ -5637,7 +5637,7 @@ Veuillez utiliser l'éditeur avancé pour cela. Cyclique (modulo) - + @@ -5646,7 +5646,7 @@ Veuillez utiliser l'éditeur avancé pour cela. Alphabétique - + @@ -6748,23 +6748,23 @@ Voulez-vous enregistrer les modifications ? Rapport de plantage - + QElectroTech ne s'est pas fermé correctement lors de sa dernière exécution. Voici les derniers messages enregistrés avant l'arrêt -- vous pouvez les enregistrer pour les joindre à un rapport de bug. - + Rapport de diagnostic - + Ceci contient les derniers messages de journalisation de cette session. Vérifiez le contenu avant de le joindre à un rapport de bug public. - + @@ -7544,13 +7544,13 @@ Options disponibles : Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + @@ -7699,7 +7699,7 @@ Options disponibles : %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content - + @@ -7708,7 +7708,7 @@ Options disponibles : %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content - + @@ -7717,7 +7717,7 @@ Options disponibles : Polices du projet message box title - + @@ -7909,7 +7909,7 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Exporter en SVG - + @@ -8390,23 +8390,23 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Exporter en SVG dialog title - + Image SVG (*.svg) filetypes allowed when exporting an element to SVG - + Échec de l'export - + Impossible d'écrire dans le fichier « %1 ». - + @@ -8626,13 +8626,13 @@ les conditions requises ne sont pas valides Enregistrer un rapport de diagnostic... - + Génère un rapport avec les derniers messages de journalisation, pour l'inclure dans un rapport de bug status bar tip - + @@ -9341,7 +9341,7 @@ Que désirez vous faire ? Le fichier « %1 » est absent ou illisible : le nom traduit de ce dossier n'a pas pu être lu, son nom de dossier est affiché à la place. - + @@ -9370,7 +9370,7 @@ Que désirez vous faire ? Numéroter automatiquement un conducteur undo caption - + From 57d0b4b5a396fc1f3a173808ddfe68737cd7a178 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Fri, 7 Aug 2026 13:48:40 +0200 Subject: [PATCH 025/350] fix whitespace --- sources/diagram.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/diagram.h b/sources/diagram.h index 360888186..36b346463 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -126,9 +126,9 @@ class Diagram : public QGraphicsScene bool use_border_; bool draw_guides_; QList m_guides_list; - bool draw_terminals_; - bool draw_terminal_names_; - bool draw_colored_conductors_; + bool draw_terminals_; + bool draw_terminal_names_; + bool draw_colored_conductors_; QString m_conductors_autonum_name; DiagramEventInterface *m_event_interface; From cc8be46c6ee4c55ba88347ddc5808dd0a83cb113 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Fri, 7 Aug 2026 14:16:20 +0200 Subject: [PATCH 026/350] For the richtext widget the compiled uic was check in since QT4(?) times although it was declared to the AUTOUIC. Removed the pre-compiled version and it still works. --- cmake/qet_compilation_vars.cmake | 1 - sources/richtext/ui_addlinkdialog.h | 117 ---------------------------- 2 files changed, 118 deletions(-) delete mode 100644 sources/richtext/ui_addlinkdialog.h diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake index 469d5a90e..5aa0433ba 100644 --- a/cmake/qet_compilation_vars.cmake +++ b/cmake/qet_compilation_vars.cmake @@ -540,7 +540,6 @@ set(QET_SRC_FILES ${QET_DIR}/sources/richtext/richtexteditor.cpp ${QET_DIR}/sources/richtext/richtexteditor_p.h - ${QET_DIR}/sources/richtext/ui_addlinkdialog.h ${QET_DIR}/sources/SearchAndReplace/searchandreplaceworker.cpp ${QET_DIR}/sources/SearchAndReplace/searchandreplaceworker.h diff --git a/sources/richtext/ui_addlinkdialog.h b/sources/richtext/ui_addlinkdialog.h deleted file mode 100644 index c1134fd98..000000000 --- a/sources/richtext/ui_addlinkdialog.h +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'addlinkdialog.ui' -** -** Created: Thu 4. Apr 17:13:59 2013 -** by: Qt User Interface Compiler version 4.8.4 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_ADDLINKDIALOG_H -#define UI_ADDLINKDIALOG_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Ui_AddLinkDialog -{ -public: - QVBoxLayout *verticalLayout; - QFormLayout *formLayout; - QLabel *label; - QLineEdit *titleInput; - QLabel *label_2; - QLineEdit *urlInput; - QSpacerItem *verticalSpacer; - QFrame *line; - QDialogButtonBox *buttonBox; - - void setupUi(QDialog *AddLinkDialog) - { - if (AddLinkDialog->objectName().isEmpty()) - AddLinkDialog->setObjectName(QString::fromUtf8("AddLinkDialog")); - AddLinkDialog->setSizeGripEnabled(false); - AddLinkDialog->setModal(true); - verticalLayout = new QVBoxLayout(AddLinkDialog); - verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); - formLayout = new QFormLayout(); - formLayout->setObjectName(QString::fromUtf8("formLayout")); - label = new QLabel(AddLinkDialog); - label->setObjectName(QString::fromUtf8("label")); - - formLayout->setWidget(0, QFormLayout::LabelRole, label); - - titleInput = new QLineEdit(AddLinkDialog); - titleInput->setObjectName(QString::fromUtf8("titleInput")); - titleInput->setMinimumSize(QSize(337, 0)); - - formLayout->setWidget(0, QFormLayout::FieldRole, titleInput); - - label_2 = new QLabel(AddLinkDialog); - label_2->setObjectName(QString::fromUtf8("label_2")); - - formLayout->setWidget(1, QFormLayout::LabelRole, label_2); - - urlInput = new QLineEdit(AddLinkDialog); - urlInput->setObjectName(QString::fromUtf8("urlInput")); - - formLayout->setWidget(1, QFormLayout::FieldRole, urlInput); - - - verticalLayout->addLayout(formLayout); - - verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - - verticalLayout->addItem(verticalSpacer); - - line = new QFrame(AddLinkDialog); - line->setObjectName(QString::fromUtf8("line")); - line->setFrameShape(QFrame::HLine); - line->setFrameShadow(QFrame::Sunken); - - verticalLayout->addWidget(line); - - buttonBox = new QDialogButtonBox(AddLinkDialog); - buttonBox->setObjectName(QString::fromUtf8("buttonBox")); - buttonBox->setOrientation(Qt::Horizontal); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - - verticalLayout->addWidget(buttonBox); - - - retranslateUi(AddLinkDialog); - QObject::connect(buttonBox, SIGNAL(accepted()), AddLinkDialog, SLOT(accept())); - QObject::connect(buttonBox, SIGNAL(rejected()), AddLinkDialog, SLOT(reject())); - - QMetaObject::connectSlotsByName(AddLinkDialog); - } // setupUi - - void retranslateUi(QDialog *AddLinkDialog) - { - AddLinkDialog->setWindowTitle(QApplication::translate("AddLinkDialog", "Insert Link", nullptr)); - label->setText(QApplication::translate("AddLinkDialog", "Title:", nullptr)); - label_2->setText(QApplication::translate("AddLinkDialog", "URL:", nullptr)); - } // retranslateUi - -}; - -namespace Ui { - class AddLinkDialog: public Ui_AddLinkDialog {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_ADDLINKDIALOG_H From 905afc1bbc27347e514c409d462295e5c47f1581 Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Fri, 7 Aug 2026 16:25:06 +0200 Subject: [PATCH 027/350] Revert "Auto-break conductor" --- .../diagramevent/diagrameventaddelement.cpp | 246 +----------------- sources/qetdiagrameditor.cpp | 21 -- sources/qetdiagrameditor.h | 2 - sources/qetproject.cpp | 28 -- sources/qetproject.h | 4 - 5 files changed, 8 insertions(+), 293 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index 9949c54d8..dee2834c0 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -20,44 +20,11 @@ #include "../conductorautonumerotation.h" #include "../diagram.h" #include "../undocommand/addgraphicsobjectcommand.h" -#include "../undocommand/deleteqgraphicsitemcommand.h" #include "../factory/elementfactory.h" #include "../qetapp.h" #include "../qetdiagrameditor.h" #include "../qetgraphicsitem/element.h" #include "../qetgraphicsitem/conductor.h" -#include "../qetgraphicsitem/terminal.h" -#include "../qet.h" -#include -#include - -namespace { - /** - @brief distanceToSegment - @param point : point to measure from - @param segment : the finite segment (not the infinite line through it) - @return the distance from @a point to the closest point actually on - @a segment. Unlike QET::orthogonalProjection(), which reports a hit - for any point on the segment's infinite extension, this clamps the - projection to the segment itself: a point collinear with a wire but - past its actual drawn end is correctly reported as far away, not "on" - the wire. - */ - qreal distanceToSegment(const QPointF &point, const QLineF &segment) - { - const QPointF a = segment.p1(); - const QPointF b = segment.p2(); - const QPointF ab = b - a; - const qreal len2 = QPointF::dotProduct(ab, ab); - - if (len2 <= 0.0) - return QLineF(point, a).length(); - - qreal t = QPointF::dotProduct(point - a, ab) / len2; - t = qBound(0.0, t, 1.0); - return QLineF(point, a + t * ab).length(); - } -} /** @brief DiagramEventAddElement::DiagramEventAddElement @@ -281,213 +248,16 @@ void DiagramEventAddElement::addElement() QUndoCommand *undo_object = new QUndoCommand(tr("Ajouter %1").arg(element->name())); new AddGraphicsObjectCommand(element, m_diagram, m_element -> pos(), undo_object); - //When we search for free aligned terminal we temporally remove m_element to - //avoid any interaction with the function Element::AlignedFreeTerminals - //This is useful when an element has two (or more) terminals on opposite sides, - //because m_element is exactly at the same pos of the new element - //added to the scene so new conductor are created between terminal of the new element - //and the opposite terminal of m_element. + //When we search for free aligned terminal we temporally remove m_element to + //avoid any interaction with the function Element::AlignedFreeTerminals + //This is useful when an element has two (or more) terminals on opposite sides, + //because m_element is exactly at the same pos of the new element + //added to the scene so new conductor are created between terminal of the new element + //and the opposite terminal of m_element. m_diagram->removeItem(m_element); - - //Auto break conductor: if a terminal of the new element lies on an existing - //conductor, break the conductor and reconnect through the new element's terminal. - //Track the endpoints of broken conductors so auto-connect doesn't create duplicates. - QSet broken_endpoints; - - if (m_diagram->project()->autoBreakConductor()) + while (!element -> AlignedFreeTerminals().isEmpty() && m_diagram -> project() -> autoConductor()) { - //Track which conductors we already handled for this element - QList conductors_handled; - //Track which terminals of the new element are already used (by break or other-connect) - QSet used_terminals; - - foreach (Terminal *t, element->terminals()) - { - //Skip terminals already used by a previous break+reconnect (other_terminal) - if (used_terminals.contains(t)) - continue; - - QPointF t_dock = t->dockConductor(); - - //Collect all conductors that pass through this dock point. - struct ConductorMatch { - Conductor *conductor; - Terminal *connect_to; //endpoint "before" the dock point (based on orientation) - Terminal *other; //endpoint "after" the dock point - }; - QList all_matches; - - foreach (Conductor *c, m_diagram->conductors()) - { - //Skip conductors we already handled or connected to the new element - if (conductors_handled.contains(c) || - c->terminal1->parentElement() == element || - c->terminal2->parentElement() == element) - continue; - - //Check if dock point lies on the conductor path. Distance is - //measured to the segment itself (clamped), not the infinite - //line through it -- see distanceToSegment(). - QPointF local_dock = c->mapFromScene(t_dock); - bool point_on_conductor = false; - QPainterPath path = c->path(); - for (int i = 0; i < path.elementCount() - 1; ++i) - { - const QPainterPath::Element &e1 = path.elementAt(i); - const QPainterPath::Element &e2 = path.elementAt(i + 1); - QLineF segment(QPointF(e1.x, e1.y), QPointF(e2.x, e2.y)); - if (distanceToSegment(local_dock, segment) < 5.0) - { - point_on_conductor = true; - break; - } - } - - if (!point_on_conductor) - continue; - - Terminal *c1 = c->terminal1; - Terminal *c2 = c->terminal2; - QPointF c1_dock = c1->dockConductor(); - QPointF c2_dock = c2->dockConductor(); - - Terminal *connect_to = nullptr; - Terminal *other = nullptr; - - switch (t->orientation()) { - case Qet::North: - if (c1_dock.y() < t_dock.y()) { connect_to = c1; other = c2; } - else if (c2_dock.y() < t_dock.y()) { connect_to = c2; other = c1; } - break; - case Qet::South: - if (c1_dock.y() > t_dock.y()) { connect_to = c1; other = c2; } - else if (c2_dock.y() > t_dock.y()) { connect_to = c2; other = c1; } - break; - case Qet::East: - if (c1_dock.x() > t_dock.x()) { connect_to = c1; other = c2; } - else if (c2_dock.x() > t_dock.x()) { connect_to = c2; other = c1; } - break; - case Qet::West: - if (c1_dock.x() < t_dock.x()) { connect_to = c1; other = c2; } - else if (c2_dock.x() < t_dock.x()) { connect_to = c2; other = c1; } - break; - } - - if (!connect_to) { - qreal d1 = QLineF(t_dock, c1_dock).length(); - qreal d2 = QLineF(t_dock, c2_dock).length(); - if (d1 <= d2) { connect_to = c1; other = c2; } - else { connect_to = c2; other = c1; } - } - - all_matches.append({c, connect_to, other}); - } - - if (all_matches.isEmpty()) - continue; - - //Group matches by their "other" endpoint and find the largest group. - //This ensures that when multiple independent circuits cross at the - //same dock point, the group with the most conductors gets priority, - //not whichever happens to have the nearest connect_to endpoint. - QMap> groups; - for (const auto &m : all_matches) { - groups[m.other].append(m); - } - Terminal *best_other = nullptr; - int best_count = 0; - for (auto it = groups.constBegin(); it != groups.constEnd(); ++it) { - if (it.value().size() > best_count) { - best_count = it.value().size(); - best_other = it.key(); - } - } - - //Only break conductors in the largest group (same "other" endpoint). - //This prevents bridging independent nets: if two unrelated conductors - //cross at a dock point, only the larger group gets broken. - const QList &matches = groups[best_other]; - - //Mark terminal as used - used_terminals.insert(t); - - //Delete all matched conductors in one batch - DiagramContent content; - for (const auto &m : matches) { - content.m_other_conductors.append(m.conductor); - conductors_handled.append(m.conductor); - } - new DeleteQGraphicsItemCommand(m_diagram, content, undo_object); - - //Create new conductors from each connect_to endpoint to this terminal. - //This creates junctions at the terminal when multiple conductors - //from the same circuit pass through the dock point (e.g. left and - //right conductors going to the same terminal strip terminal). - for (const auto &m : matches) { - Conductor *new_c = new Conductor(m.connect_to, t); - new AddGraphicsObjectCommand(new_c, m_diagram, QPointF(), undo_object); - ConductorAutoNumerotation can(new_c, m_diagram, undo_object); - can.numerate(); - if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) - new_c->setFreezeLabel(true); - - broken_endpoints.insert(m.connect_to); - } - - //Connect the shared "other" endpoint to the nearest free terminal - //with matching orientation. - QPointF other_dock = best_other->dockConductor(); - Terminal *other_terminal = nullptr; - qreal best_dist = std::numeric_limits::max(); - foreach (Terminal *ot, element->terminals()) - { - if (used_terminals.contains(ot)) - continue; - - //Check that the other_dock approaches from the correct direction - //relative to the candidate terminal's orientation. - QPointF ot_dock = ot->dockConductor(); - bool orientation_ok = false; - switch (ot->orientation()) { - case Qet::North: orientation_ok = other_dock.y() < ot_dock.y(); break; - case Qet::South: orientation_ok = other_dock.y() > ot_dock.y(); break; - case Qet::East: orientation_ok = other_dock.x() > ot_dock.x(); break; - case Qet::West: orientation_ok = other_dock.x() < ot_dock.x(); break; - } - if (!orientation_ok) - continue; - - qreal dist = QLineF(ot_dock, other_dock).length(); - if (dist < best_dist) { - best_dist = dist; - other_terminal = ot; - } - } - - if (other_terminal) { - Conductor *new_c2 = new Conductor(best_other, other_terminal); - new AddGraphicsObjectCommand(new_c2, m_diagram, QPointF(), undo_object); - ConductorAutoNumerotation can2(new_c2, m_diagram, undo_object); - can2.numerate(); - if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) - new_c2->setFreezeLabel(true); - - broken_endpoints.insert(best_other); - used_terminals.insert(other_terminal); - } - } - } - - //Auto-connect: collect all aligned pairs first, then filter and process. - QList> aligned_pairs; - if (m_diagram->project()->autoConductor()) - aligned_pairs = element->AlignedFreeTerminals(); - - for (const QPair &pair : aligned_pairs) - { - //Skip if the other terminal was an endpoint of a broken conductor - if (broken_endpoints.contains(pair.second)) - continue; + QPair pair = element -> AlignedFreeTerminals().takeFirst(); Conductor *conductor = new Conductor(pair.first, pair.second); new AddGraphicsObjectCommand(conductor, m_diagram, QPointF(), undo_object); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 1ae771162..655bcd0d4 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -370,21 +370,6 @@ void QETDiagramEditor::setUpActions() pv->project()->setAutoConductor(ac); }); - //AutoBreakConductor - m_auto_break_conductor = new QAction (QET::Icons::Conductor, tr("Coupure automatique de conducteur(s)","Tool tip of auto break conductor"), this); - m_auto_break_conductor->setStatusTip (tr("Couper automatiquement les conducteurs existants lors du placement d'un élément", "Status tip of auto break conductor")); - m_auto_break_conductor->setCheckable (true); - { - QSettings settings; - m_auto_break_conductor->setChecked(settings.value("diagrameditor/auto_break_conductor", false).toBool()); - } - connect(m_auto_break_conductor, &QAction::triggered, [this](bool abc) { - QSettings settings; - settings.setValue("diagrameditor/auto_break_conductor", abc); - if (ProjectView *pv = currentProjectView()) - pv->project()->setAutoBreakConductor(abc); - }); - //Switch background color m_grey_background = new QAction (QET::Icons::DiagramBg, tr("Couleur de fond blanc/gris","Tool tip of white/grey background button"), this); m_grey_background -> setStatusTip (tr("Affiche la couleur de fond du folio en blanc ou en gris", "Status tip of white/grey background button")); @@ -824,7 +809,6 @@ void QETDiagramEditor::setUpToolBar() diagram_tool_bar -> addAction (m_edit_diagram_properties); diagram_tool_bar -> addAction (m_conductor_reset); diagram_tool_bar -> addAction (m_auto_conductor); - diagram_tool_bar -> addAction (m_auto_break_conductor); m_add_item_tool_bar = new QToolBar(tr("Ajouter"), this); m_add_item_tool_bar->setObjectName("adding"); @@ -1912,14 +1896,9 @@ void QETDiagramEditor::slot_updateModeActions() { m_auto_conductor -> setEnabled (true); m_auto_conductor -> setChecked (pv -> project() -> autoConductor()); - m_auto_break_conductor -> setEnabled (true); - m_auto_break_conductor -> setChecked (pv -> project() -> autoBreakConductor()); } else - { m_auto_conductor -> setDisabled(true); - m_auto_break_conductor -> setDisabled(true); - } } /** diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 21df421f7..f5666f781 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -192,8 +192,6 @@ class QETDiagramEditor : public QETMainWindow *redo, ///< Redo the latest cancelled operation *m_paste, ///< Paste clipboard content on the current diagram *m_auto_conductor, ///< Enable/Disable the use of auto conductor - *m_auto_break_conductor, ///< Enable/Disable the use of auto break conductor - *conductor_default, ///< Show a dialog to edit default conductor properties *m_grey_background, ///< Switch the background color in white or grey *m_draw_grid, ///< Switch the background grid display or not *m_draw_guides = nullptr, ///< Switch the custom guides display or not diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 31dfb6365..9b115458d 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -69,10 +69,6 @@ m_project_properties_handler{this} init(); QSettings settings; - - //Read auto break conductor default from global settings - m_auto_break_conductor = settings.value(QStringLiteral("diagrameditor/auto_break_conductor"), false).toBool(); - int size = settings.beginReadArray(QStringLiteral("diagrameditor/defaultguides")); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); @@ -931,28 +927,6 @@ void QETProject::setAutoConductor(bool ac) m_auto_conductor = ac; } -/** - @brief QETProject::autoBreakConductor - @return true if use of auto break conductor is authorized. - See also Q_PROPERTY autoBreakConductor -*/ -bool QETProject::autoBreakConductor() const -{ - return m_auto_break_conductor; -} - -/** - @brief QETProject::setAutoBreakConductor - @param abc - Enable the use of auto break conductor if true - See also Q_PROPERTY autoBreakConductor -*/ -void QETProject::setAutoBreakConductor(bool abc) -{ - if (abc != m_auto_break_conductor) - m_auto_break_conductor = abc; -} - /** @brief QETProject::autoFolioNumberingNewFolios emit Signal to add new Diagram with autonum @@ -1761,7 +1735,6 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project) { m_current_conductor_autonum = conds_autonums.attribute(QStringLiteral("current_autonum")); m_freeze_new_conductors = conds_autonums.attribute(QStringLiteral("freeze_new_conductors")) == QLatin1String("true"); - m_auto_break_conductor = conds_autonums.attribute(QStringLiteral("auto_break_conductors")) == QLatin1String("true"); for (auto elmt : QET::findInDomElement(conds_autonums, QStringLiteral("conductor_autonum"))) { NumerotationContext nc; @@ -1888,7 +1861,6 @@ void QETProject::writeDefaultPropertiesXml(QDomElement &xml_element) QDomElement conductor_autonums = xml_document.createElement("conductors_autonums"); conductor_autonums.setAttribute("current_autonum", m_current_conductor_autonum); conductor_autonums.setAttribute("freeze_new_conductors", m_freeze_new_conductors ? "true" : "false"); - conductor_autonums.setAttribute("auto_break_conductors", m_auto_break_conductor ? "true" : "false"); foreach (QString key, conductorAutoNum().keys()) { QDomElement conductor_autonum = conductorAutoNum(key).toXml(xml_document, "conductor_autonum"); if (key != "" && conductorAutoNumFormula(key) != "") { diff --git a/sources/qetproject.h b/sources/qetproject.h index b08e2b5b4..61427ca72 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -90,7 +90,6 @@ class QETProject : public QObject }; Q_PROPERTY(bool autoConductor READ autoConductor WRITE setAutoConductor) - Q_PROPERTY(bool autoBreakConductor READ autoBreakConductor WRITE setAutoBreakConductor) // constructors, destructor public: @@ -182,11 +181,9 @@ class QETProject : public QObject void setFreezeNewConductors(bool); bool autoConductor () const; - bool autoBreakConductor () const; bool autoElement () const; bool autoFolio () const; void setAutoConductor (bool ac); - void setAutoBreakConductor (bool abc); void setAutoElement (bool ae); void autoFolioNumberingNewFolios (); void autoFolioNumberingSelectedFolios(int, int, const QString&); @@ -321,7 +318,6 @@ class QETProject : public QObject QHash m_element_autonum; //Title and NumContext hash QString m_current_element_autonum; bool m_auto_conductor = true; - bool m_auto_break_conductor = false; XmlElementCollection *m_elements_collection = nullptr; bool m_freeze_new_elements = false; bool m_freeze_new_conductors = false; From e7cbb8f50e9472f7aca0bc55761230f03c15cbd6 Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Fri, 7 Aug 2026 17:20:45 +0200 Subject: [PATCH 028/350] Reading prefixes from company collection Added a reading for company collection prefixes which are overwritten by user collection prefixes --- sources/autoNum/assignvariables.cpp | 137 +++++++++++----------------- 1 file changed, 54 insertions(+), 83 deletions(-) diff --git a/sources/autoNum/assignvariables.cpp b/sources/autoNum/assignvariables.cpp index 8e2d465ec..b39e1d361 100644 --- a/sources/autoNum/assignvariables.cpp +++ b/sources/autoNum/assignvariables.cpp @@ -703,6 +703,46 @@ namespace autonum return formula; } + /** + @brief prefixFromLabelFile + Look up a prefix for @a path in the qet_labels.xml at @a filepath. + @return the prefix, or a null QString if the file cannot be read + or holds no matching entry. + */ + static QString prefixFromLabelFile(const QString &filepath, const QString path[10], int i, int dirLevel) + { + QFile file(filepath); + if (!file.open(QFile::ReadOnly | QFile::Text)) + return QString(); + + QXmlStreamReader rxml; + rxml.setDevice(&file); + rxml.readNext(); + + while (!rxml.atEnd()) { + if (rxml.attributes().value("name").toString() == path[i]) { + rxml.readNext(); + i = i - 1; + + if (i == 0) { + for (int j = i ; j <= dirLevel ; ++j) { + + if (rxml.name().toString() == "prefix") { + return rxml.readElementText(); + } else { + while (rxml.readNextStartElement() && rxml.name().toString() != "prefix") { + rxml.skipCurrentElement(); + rxml.readNext(); + } + } + } + } + } + rxml.readNext(); + } + return QString(); + } + /** @brief elementPrefixForLocation @param location @@ -716,7 +756,6 @@ namespace autonum if (!location.isProject()) return QString(); - QXmlStreamReader rxml; QString path[10]; int i = -1; ElementsLocation current_location = location; @@ -739,91 +778,23 @@ namespace autonum dirLevel = 0; } - // Create Custom labels if qet_labels.xml exits in customElementsDir - if (current_location.fileName() != "10_electric"){ - QString custom_labels = "qet_labels.xml"; - QString customfilepath = QETApp::customElementsDir().append(custom_labels); - - QFile file(customfilepath); - file.isReadable(); - if (!file.open(QFile::ReadOnly | QFile::Text)) - return QString(); - rxml.setDevice(&file); - rxml.readNext(); - - while(!rxml.atEnd()) - { - if (rxml.attributes().value("name").toString() == path[i]) - { - rxml.readNext(); - i=i-1; - //reached element directory - if (i==0) - { - for (int j=i; j<= dirLevel; j = j +1) - { - //if there is a prefix available apply prefix - if(rxml.name().toString()=="prefix") - { - return rxml.readElementText(); - } - //if there isn't a prefix available, find parent prefix in parent folder - else - { - while (rxml.readNextStartElement() && rxml.name().toString()!="prefix") - { - rxml.skipCurrentElement(); - rxml.readNext(); - } - } - } - } - } - rxml.readNext(); - } + if (current_location.fileName() == "10_electric") { + return prefixFromLabelFile( + QETApp::commonElementsDir() + "10_electric/qet_labels.xml", + path, i, dirLevel); } - else - { - QString qet_labels = "10_electric/qet_labels.xml"; - QString filepath = QETApp::commonElementsDir().append(qet_labels); - QFile file(filepath); - file.isReadable(); - if (!file.open(QFile::ReadOnly | QFile::Text)) - return QString(); - - rxml.setDevice(&file); - rxml.readNext(); - while(!rxml.atEnd()) - { - if (rxml.attributes().value("name").toString() == path[i]) - { - rxml.readNext(); - i=i-1; - //reached element directory - if (i==0) - { - for (int j=i; j<= dirLevel; j = j +1) - { - //if there is a prefix available apply prefix - if(rxml.name().toString()=="prefix") - { - return rxml.readElementText(); - } - //if there isn't a prefix available, find parent prefix in parent folder - else - { - while (rxml.readNextStartElement() && rxml.name().toString()!="prefix") - { - rxml.skipCurrentElement(); - rxml.readNext(); - } - } - } - } + //Look in the custom collection first, then in the company + //collection, so a user override wins over the shared one. + const QStringList candidates = { + QETApp::customElementsDir() + "qet_labels.xml", + QETApp::companyElementsDir() + "qet_labels.xml" + }; + for (const QString &candidate : candidates) { + const QString prefix = prefixFromLabelFile(candidate, path, i, dirLevel); + if (!prefix.isNull()) { + return prefix; } - rxml.readNext(); - } } return QString(); } From eab9603d8a382aabb6f6fe7f1fb70545029d18db Mon Sep 17 00:00:00 2001 From: Levi Jetzer Date: Fri, 7 Aug 2026 21:52:40 +0200 Subject: [PATCH 029/350] Fixed saving coil master Removed "isVisible" check on max_slave_checkbox before saving because isVisible is maybe not true, when the ok button is pressed Then the value -1 is written and so on not saved to the elements xml --- sources/editor/ui/elementpropertieseditorwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index 202cc23a5..55bcbc947 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -371,7 +371,7 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted() m_data.m_master_type = ui->m_master_type_cb->currentData().value(); //If the checkbox is checked, save the number; otherwise, -1 (infinity) - if (ui->max_slaves_checkbox->isVisible() && ui->max_slaves_checkbox->isChecked()) { + if (ui->max_slaves_checkbox->isChecked()) { m_data.m_max_slaves = ui->max_slaves_spinbox->value(); } else { m_data.m_max_slaves = -1; From b6e43f78d0ef01bf7837cbb056139193c0af5ded Mon Sep 17 00:00:00 2001 From: plc-user <74435298+plc-user@users.noreply.github.com> Date: Fri, 7 Aug 2026 22:09:06 +0200 Subject: [PATCH 030/350] fix whitespace --- sources/ui/configpage/generalconfigurationpage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sources/ui/configpage/generalconfigurationpage.cpp b/sources/ui/configpage/generalconfigurationpage.cpp index 000b1c547..2a7b48ae1 100644 --- a/sources/ui/configpage/generalconfigurationpage.cpp +++ b/sources/ui/configpage/generalconfigurationpage.cpp @@ -393,7 +393,7 @@ void GeneralConfigurationPage::fillLang() ui->m_lang_cb->addItem(QET::Icons::hr, tr("Croate"), "hr"); ui->m_lang_cb->addItem(QET::Icons::it, tr("Italien"), "it"); ui->m_lang_cb->addItem(QET::Icons::jp, tr("Japonais"), "ja"); - ui->m_lang_cb->addItem(QET::Icons::ko, tr("Coréen"), "ko"); + ui->m_lang_cb->addItem(QET::Icons::ko, tr("Coréen"), "ko"); ui->m_lang_cb->addItem(QET::Icons::pl, tr("Polonais"), "pl"); ui->m_lang_cb->addItem(QET::Icons::pt, tr("Portugais"), "pt"); ui->m_lang_cb->addItem(QET::Icons::ro, tr("Roumains"), "ro"); @@ -405,9 +405,9 @@ void GeneralConfigurationPage::fillLang() ui->m_lang_cb->addItem(QET::Icons::tr, tr("Turc"), "tr"); ui->m_lang_cb->addItem(QET::Icons::hu, tr("Hongrois"), "hu"); ui->m_lang_cb->addItem(QET::Icons::mn, tr("Mongol"), "mn"); - ui->m_lang_cb->addItem(QET::Icons::uk, tr("Ukrainien"), "uk"); - ui->m_lang_cb->addItem(QET::Icons::zh, tr("Chinois"), "zh"); - ui->m_lang_cb->addItem(QET::Icons::se, tr("Suédois"), "sv"); + ui->m_lang_cb->addItem(QET::Icons::uk, tr("Ukrainien"), "uk"); + ui->m_lang_cb->addItem(QET::Icons::zh, tr("Chinois"), "zh"); + ui->m_lang_cb->addItem(QET::Icons::se, tr("Suédois"), "sv"); //set current index to the lang found in setting file //if lang doesn't exist set to system QSettings settings; From 41e83bbc09f2aa4dcd2dd03871abbc732421c140 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sat, 8 Aug 2026 09:40:25 +1200 Subject: [PATCH 031/350] Keep group rotation on-grid when X and Y grid sizes differ Raised by plc-user in discussion #618: the diagram editor allows moving elements by as little as 1px, and asked that rotation not undershoot that. Checking the actual constraint (Settings -> DiagramEditor_xGrid_sb / _yGrid_sb, both independently configurable, minimum 1, maximum 30) turned up a real, verified gap this PR's existing fractional-pivot fix doesn't cover: an ASYMMETRIC grid (xGrid != yGrid). Swapping X/Y deltas for a 90-degree turn -- the exact-arithmetic path already in this file -- only stays on the configured grid if xGrid == yGrid. With an asymmetric grid, a delta that was a clean multiple of xGrid lands on the Y axis after the swap, where the grid unit is yGrid, and one is not generally a multiple of the other. Verified on a real build (not just derived): two elements at (100,210) and (150,420), both on-grid under xGrid=10/yGrid=7, selected and group-rotated 90 degrees via a temporary local CLI harness. before this change: (242,292) and (32,342) -- off-grid on both axes after this change: (240,294) and ( 30,343) -- exactly on-grid Confirmed the same drift is present without this change too (i.e. not something introduced elsewhere) and that xGrid==yGrid, the common case, is unaffected: snapping an already-on-grid point is a no-op. Fix: re-snap the final computed position to Diagram::snapToGrid(), not just the shared pivot, for the exact-90-degree path. Left the arbitrary-angle trig fallback alone -- it has no caller today (the diagram editor only ever passes multiples of 90) and "on-grid" doesn't have a clean meaning for an arbitrary angle regardless of grid shape. Does not attempt to fix a separate, pre-existing property surfaced while testing this: four consecutive 90-degree turns do not reliably return a selection to its exact starting position, even on a symmetric grid, because each RotateSelectionCommand recomputes the pivot fresh from the selection's current sceneBoundingRect(), and an item whose bounding box isn't rotationally symmetric reports a different box (and therefore a different centre) at 0 and 90 degrees. Verified this drift is identical with and without this change, so it is not a regression -- just a different, harder guarantee this change does not attempt. Co-Authored-By: Claude Opus 5 --- .../undocommand/rotateselectioncommand.cpp | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/sources/undocommand/rotateselectioncommand.cpp b/sources/undocommand/rotateselectioncommand.cpp index 341f01a2b..089d022ac 100644 --- a/sources/undocommand/rotateselectioncommand.cpp +++ b/sources/undocommand/rotateselectioncommand.cpp @@ -149,7 +149,8 @@ void RotateSelectionCommand::addGroupPositionUndo(QGraphicsItem *item, const QPo * A quadrant is just an axis swap, which is exact. */ QPointF offset; const int quadrant = qRound(angle / 90.0); - if (qFuzzyCompare(angle, quadrant * 90.0)) + bool exact_quadrant = qFuzzyCompare(angle, quadrant * 90.0); + if (exact_quadrant) { switch (((quadrant % 4) + 4) % 4) { @@ -167,7 +168,40 @@ void RotateSelectionCommand::addGroupPositionUndo(QGraphicsItem *item, const QPo delta.x() * qSin(radians) + delta.y() * qCos(radians)); } - m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "pos", QVariant(old_pos), QVariant(pivot + offset), this); + QPointF new_pos = pivot + offset; + if (exact_quadrant) + { + /* Swapping X/Y deltas for a 90/270 turn only stays on the + * user's configured grid if xGrid == yGrid. With an + * asymmetric grid (both independently configurable, 1-30 px, + * in Settings) a delta that was a clean multiple of xGrid + * lands on the Y axis after the swap, where the grid unit is + * yGrid -- and 10 is not a multiple of 7. Verified this + * drifts a grid-aligned point off-grid without this snap + * (e.g. xGrid=10/yGrid=7: (100,210) rotates to (225,295), + * x%10==5), and that adding it corrects exactly that case on + * a real build (same inputs land on x%10==0, y%7==0). + * + * For xGrid == yGrid, snapping an already-on-grid point is a + * no-op, so this leaves that case's arithmetic unchanged. + * It does NOT, on its own, guarantee that four consecutive + * 90-degree turns return a selection to its exact starting + * position even on a symmetric grid: each RotateSelectionCommand + * recomputes the pivot fresh from the selection's CURRENT + * sceneBoundingRect(), and an item whose bounding box isn't + * rotationally symmetric (e.g. a wide text label) reports a + * different box, and therefore a different box centre, at 0 + * and 90 degrees. That drift is pre-existing -- verified + * identical with and without this change -- and a separate + * problem from the one this fixes: staying on-grid after + * every individual turn is the property that matters day to + * day; bit-exact round-tripping through several consecutive + * rotations is a different, harder guarantee this change + * does not attempt. */ + new_pos = Diagram::snapToGrid(new_pos); + } + + m_undo << new QPropertyUndoCommand(item->toGraphicsObject(), "pos", QVariant(old_pos), QVariant(new_pos), this); } /** From 62ad49a6d36a88ef7ba897033b6d22e4ccdb0f19 Mon Sep 17 00:00:00 2001 From: Andre Rummler Date: Wed, 5 Aug 2026 23:33:54 +0200 Subject: [PATCH 032/350] Update old fashioned SIGNAL/SLOT to point-to-member. Only simple and clear cases. --- .../autoNum/ui/autonumberingdockwidget.cpp | 50 ++++++----------- sources/configdialog.cpp | 7 ++- sources/diagramview.cpp | 2 +- sources/editor/elementscene.cpp | 17 +++--- sources/editor/elementview.cpp | 4 +- sources/editor/graphicspart/parttext.cpp | 8 +-- .../ui/elementpropertieseditorwidget.cpp | 2 +- sources/elementscategoryeditor.cpp | 6 +-- sources/elementspanelwidget.cpp | 2 +- sources/exportdialog.cpp | 28 +++++----- sources/exportpropertieswidget.cpp | 2 +- sources/projectview.cpp | 14 ++--- sources/qetapp.cpp | 8 +-- sources/qetdiagrameditor.cpp | 53 +++++++------------ sources/qetgraphicsitem/crossrefitem.cpp | 6 +-- sources/qetmainwindow.cpp | 2 +- sources/qetproject.cpp | 2 +- sources/qfilenameedit.cpp | 2 +- sources/qtextorientationspinboxwidget.cpp | 7 ++- sources/richtext/richtexteditor.cpp | 15 +++--- sources/titleblock/dimensionwidget.cpp | 4 +- .../integrationmovetemplateshandler.cpp | 8 +-- sources/titleblock/qettemplateeditor.cpp | 46 ++++++++-------- sources/titleblock/templatecellwidget.cpp | 6 +-- sources/titleblock/templatelogomanager.cpp | 17 +++--- sources/titleblock/templatescollection.cpp | 2 +- sources/titleblock/templateview.cpp | 22 +++----- sources/ui/configpage/configpages.cpp | 4 +- sources/ui/configpage/projectconfigpages.cpp | 28 +++++----- sources/ui/diagramcontextwidget.cpp | 2 +- sources/ui/diagrampropertiesdialog.cpp | 6 +-- .../ui/diagrampropertieseditordockwidget.cpp | 12 ++--- sources/ui/linksingleelementwidget.cpp | 6 +-- sources/ui/masterpropertieswidget.cpp | 12 ++--- sources/ui/projectpropertiesdialog.cpp | 4 +- sources/ui/xrefpropertieswidget.cpp | 4 +- 36 files changed, 182 insertions(+), 238 deletions(-) diff --git a/sources/autoNum/ui/autonumberingdockwidget.cpp b/sources/autoNum/ui/autonumberingdockwidget.cpp index a01cc538f..1681cb57a 100644 --- a/sources/autoNum/ui/autonumberingdockwidget.cpp +++ b/sources/autoNum/ui/autonumberingdockwidget.cpp @@ -86,29 +86,21 @@ void AutoNumberingDockWidget::setProject(QETProject *project, //Disconnect previous project if (m_project && m_project_view) { - //Conductor Signals - disconnect(m_project, SIGNAL(conductorAutoNumChanged()), - this,SLOT(conductorAutoNumChanged())); - disconnect (m_project,SIGNAL(conductorAutoNumRemoved()), - this,SLOT(conductorAutoNumChanged())); - disconnect (m_project,SIGNAL(conductorAutoNumAdded()), - this,SLOT(conductorAutoNumChanged())); - disconnect(m_project_view,SIGNAL(diagramActivated(DiagramView*)), - this,SLOT(setConductorActive(DiagramView*))); - - //Element Signals - disconnect (m_project,SIGNAL(elementAutoNumRemoved(QString)), - this,SLOT(elementAutoNumChanged())); - disconnect (m_project,SIGNAL(elementAutoNumAdded(QString)), - this,SLOT(elementAutoNumChanged())); + disconnect(m_project, &QETProject::conductorAutoNumChanged, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + disconnect(m_project, &QETProject::conductorAutoNumRemoved, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + disconnect(m_project, &QETProject::conductorAutoNumAdded, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + disconnect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::setConductorActive); + + //Element Signals + disconnect(m_project, &QETProject::elementAutoNumRemoved, this, &AutoNumberingDockWidget::elementAutoNumChanged); + disconnect(m_project, &QETProject::elementAutoNumAdded, this, &AutoNumberingDockWidget::elementAutoNumChanged); //Folio Signals disconnect (m_project,SIGNAL(folioAutoNumRemoved()), this,SLOT(folioAutoNumChanged())); disconnect (m_project,SIGNAL(folioAutoNumAdded()), this,SLOT(folioAutoNumChanged())); - disconnect(m_project, SIGNAL(defaultTitleBlockPropertiesChanged()), - this,SLOT(setActive())); + disconnect(m_project, &QETProject::defaultTitleBlockPropertiesChanged, this, &AutoNumberingDockWidget::setActive); //Conductor, Element and Folio Signals disconnect(m_project, &QETProject::autoNumContextUpdated, @@ -121,29 +113,21 @@ void AutoNumberingDockWidget::setProject(QETProject *project, m_project_view = projectview; this->setEnabled(true); - //Conductor Signals - connect(m_project, SIGNAL(conductorAutoNumChanged()), - this,SLOT(conductorAutoNumChanged())); - connect(m_project,SIGNAL(conductorAutoNumRemoved()), - this,SLOT(conductorAutoNumChanged())); - connect(m_project,SIGNAL(conductorAutoNumAdded()), - this,SLOT(conductorAutoNumChanged())); - connect(m_project_view,SIGNAL(diagramActivated(DiagramView*)), - this,SLOT(setConductorActive(DiagramView*))); + connect(m_project, &QETProject::conductorAutoNumChanged, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + connect(m_project, &QETProject::conductorAutoNumRemoved, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + connect(m_project, &QETProject::conductorAutoNumAdded, this, &AutoNumberingDockWidget::conductorAutoNumChanged); + connect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::setConductorActive); - //Element Signals - connect (m_project,SIGNAL(elementAutoNumRemoved(QString)), - this,SLOT(elementAutoNumChanged())); - connect (m_project,SIGNAL(elementAutoNumAdded(QString)), - this,SLOT(elementAutoNumChanged())); + //Element Signals + connect(m_project, &QETProject::elementAutoNumRemoved, this, &AutoNumberingDockWidget::elementAutoNumChanged); + connect(m_project, &QETProject::elementAutoNumAdded, this, &AutoNumberingDockWidget::elementAutoNumChanged); //Folio Signals connect (m_project,SIGNAL(folioAutoNumRemoved()), this,SLOT(folioAutoNumChanged())); connect (m_project,SIGNAL(folioAutoNumAdded()), this,SLOT(folioAutoNumChanged())); - connect(m_project, SIGNAL(defaultTitleBlockPropertiesChanged()), - this,SLOT(setActive())); + connect(m_project, &QETProject::defaultTitleBlockPropertiesChanged, this, &AutoNumberingDockWidget::setActive); //Conductor, Element and Folio Signals connect(m_project, &QETProject::autoNumContextUpdated, diff --git a/sources/configdialog.cpp b/sources/configdialog.cpp index b737ca7c2..10a0d0e0e 100644 --- a/sources/configdialog.cpp +++ b/sources/configdialog.cpp @@ -74,10 +74,9 @@ ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) { setLayout(dialog_layout); // connexion signaux / slots - connect(buttons, SIGNAL(accepted()), this, SLOT(applyConf())); - connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); - connect(pages_list, SIGNAL(currentRowChanged(int)), - pages_widget, SLOT(setCurrentIndex(int))); + connect(buttons, &QDialogButtonBox::accepted, this, &ConfigDialog::applyConf); + connect(buttons, &QDialogButtonBox::rejected, this, &ConfigDialog::reject); + connect(pages_list, &QListWidget::currentRowChanged, pages_widget, &QStackedWidget::setCurrentIndex); // set maximum a bit smaller than available size = (screen-size - Task-Bar): setMaximumSize((int)(0.94 * MachineInfo::instance()->i_max_available_width()), diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 427ad0634..1eea4f80e 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -99,7 +99,7 @@ DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : } connect(m_diagram, SIGNAL(showDiagram(Diagram*)), this, SIGNAL(showDiagram(Diagram*))); - connect(m_diagram, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(adjustSceneRect())); + connect(m_diagram, &QGraphicsScene::sceneRectChanged, this, &DiagramView::adjustSceneRect); connect(&(m_diagram -> border_and_titleblock), &BorderTitleBlock::informationChanged, this, &DiagramView::updateWindowTitle); connect(diagram, SIGNAL(findElementRequired(ElementsLocation)), this, SIGNAL(findElementRequired(ElementsLocation))); diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index a2c8146d3..1692e2dbb 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -69,10 +69,8 @@ ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) : initPasteArea(); m_undo_stack.setClean(); m_decorator_lock = new QMutex(); - connect(&m_undo_stack, SIGNAL(indexChanged(int)), - this, SLOT(managePrimitivesGroups())); - connect(this, SIGNAL(selectionChanged()), - this, SLOT(managePrimitivesGroups())); + connect(&m_undo_stack, &QUndoStack::indexChanged, this, &ElementScene::managePrimitivesGroups); + connect(this, &ElementScene::selectionChanged, this, &ElementScene::managePrimitivesGroups); } /** @@ -102,8 +100,7 @@ void ElementScene::setElementData(ElementData data) ElementScene::~ElementScene() { //Disconnect to avoid crash, see bug report N° 122. - disconnect(&m_undo_stack, SIGNAL(indexChanged(int)), - this, SLOT(managePrimitivesGroups())); + disconnect(&m_undo_stack, &QUndoStack::indexChanged, this, &ElementScene::managePrimitivesGroups); delete m_decorator_lock; if (m_event_interface) @@ -907,8 +904,8 @@ void ElementScene::slot_editAuthorInformations() QDialogButtonBox::Ok | QDialogButtonBox::Cancel); dialog_layout -> addWidget(dialog_buttons); - connect(dialog_buttons, SIGNAL(accepted()),&dialog_author, SLOT(accept())); - connect(dialog_buttons, SIGNAL(rejected()),&dialog_author, SLOT(reject())); + connect(dialog_buttons, &QDialogButtonBox::accepted, &dialog_author, &QDialog::accept); + connect(dialog_buttons, &QDialogButtonBox::rejected, &dialog_author, &QDialog::reject); // start the dialogue // lance le dialogue @@ -1399,9 +1396,7 @@ void ElementScene::managePrimitivesGroups() if (!m_decorator) { m_decorator = new ElementPrimitiveDecorator(); - connect(m_decorator, - SIGNAL(actionFinished(ElementEditionCommand*)), - this, SLOT(stackAction(ElementEditionCommand *))); + connect(m_decorator, &ElementPrimitiveDecorator::actionFinished, this, &ElementScene::stackAction); addItem(m_decorator); m_decorator -> hide(); } diff --git a/sources/editor/elementview.cpp b/sources/editor/elementview.cpp index a2cc8af58..fe7d515b0 100644 --- a/sources/editor/elementview.cpp +++ b/sources/editor/elementview.cpp @@ -37,8 +37,8 @@ ElementView::ElementView(ElementScene *scene, QWidget *parent) : setResizeAnchor(QGraphicsView::AnchorUnderMouse); setTransformationAnchor(QGraphicsView::AnchorUnderMouse); zoomReset(); - connect(m_scene, SIGNAL(pasteAreaDefined(const QRectF &)), this, SLOT(pasteAreaDefined(const QRectF &))); - connect(m_scene, SIGNAL(needZoomFit()), this, SLOT(zoomFit())); + connect(m_scene, &ElementScene::pasteAreaDefined, this, &ElementView::pasteAreaDefined); + connect(m_scene, &ElementScene::needZoomFit, this, &ElementView::zoomFit); } /// Destructeur diff --git a/sources/editor/graphicspart/parttext.cpp b/sources/editor/graphicspart/parttext.cpp index 7f4112d86..2154603f4 100644 --- a/sources/editor/graphicspart/parttext.cpp +++ b/sources/editor/graphicspart/parttext.cpp @@ -50,10 +50,10 @@ PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent) : adjustItemPosition(1); // adjust textfield position after line additions/deletions - connect(document(), - SIGNAL(blockCountChanged(int)), - this, - SLOT(adjustItemPosition(int))); + connect(document(), + &QTextDocument::blockCountChanged, + this, + &PartText::adjustItemPosition); connect(document(), SIGNAL(contentsChanged()), this, diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index 4500a1734..b5fbdc2bc 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -222,7 +222,7 @@ void ElementPropertiesEditorWidget::setUpInterface() ui->m_tree->setItemDelegate(new EditorDelegate(this)); // NEU: Checkbox mit der Zahlenbox verbinden (Aktivieren/Deaktivieren) - connect(ui->max_slaves_checkbox, SIGNAL(toggled(bool)), ui->max_slaves_spinbox, SLOT(setEnabled(bool))); + connect(ui->max_slaves_checkbox, &QCheckBox::toggled, ui->max_slaves_spinbox, &QWidget::setEnabled); connect(ui->max_slaves_spinbox, QOverload::of(&QSpinBox::valueChanged), [this](int) { if (ui->m_slave_groups_checkbox->isChecked()) { populateSlaveGroupsTable(); diff --git a/sources/elementscategoryeditor.cpp b/sources/elementscategoryeditor.cpp index 1a3f223a5..600b7e28e 100644 --- a/sources/elementscategoryeditor.cpp +++ b/sources/elementscategoryeditor.cpp @@ -58,14 +58,14 @@ ElementsCategoryEditor::ElementsCategoryEditor(const ElementsLocation &location, if (m_edit_mode) { setWindowTitle(tr("Éditer une catégorie", "window title")); - connect(m_buttons, SIGNAL(accepted()), this, SLOT(acceptUpdate())); + connect(m_buttons, &QDialogButtonBox::accepted, this, &ElementsCategoryEditor::acceptUpdate); m_names_list -> setNames(m_location.nameList()); m_file_line_edit -> setText(m_location.fileSystemPath()); m_file_line_edit -> setReadOnly(true); } else { setWindowTitle(tr("Créer une nouvelle catégorie", "window title")); - connect(m_buttons, SIGNAL(accepted()), this, SLOT(acceptCreation())); + connect(m_buttons, &QDialogButtonBox::accepted, this, &ElementsCategoryEditor::acceptCreation); NamesList cat_names; cat_names.addName(QLocale::system().name().left(2), tr("Nom de la nouvelle catégorie", "default name when creating a new category")); @@ -114,7 +114,7 @@ void ElementsCategoryEditor::setUpWidget() m_file_line_edit = new QFileNameEdit(); m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(m_buttons, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_buttons, &QDialogButtonBox::rejected, this, &ElementsCategoryEditor::reject); QHBoxLayout *internal_name_layout = new QHBoxLayout(); internal_name_layout -> addWidget(m_file_name); diff --git a/sources/elementspanelwidget.cpp b/sources/elementspanelwidget.cpp index 7baf0afbe..10d07d45e 100644 --- a/sources/elementspanelwidget.cpp +++ b/sources/elementspanelwidget.cpp @@ -117,7 +117,7 @@ ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) { connect(filter_textfield, SIGNAL(textChanged(const QString &)), this, SLOT(filterEdited(const QString &))); connect(elements_panel, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(updateButtons())); - connect(elements_panel, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(handleContextMenu(const QPoint &))); + connect(elements_panel, &ElementsPanel::customContextMenuRequested, this, &ElementsPanelWidget::handleContextMenu); connect( elements_panel, SIGNAL(requestForTitleBlockTemplate(const TitleBlockTemplateLocation &)), diff --git a/sources/exportdialog.cpp b/sources/exportdialog.cpp index b736aa240..860b6ce6d 100644 --- a/sources/exportdialog.cpp +++ b/sources/exportdialog.cpp @@ -99,9 +99,9 @@ ExportDialog::ExportDialog( // connexions signaux/slots connect(epw, SIGNAL(formatChanged()), this, SLOT(slot_changeFilesExtension())); - connect(epw, SIGNAL(exportedAreaChanged()), this, SLOT(slot_changeUseBorder())); - connect(buttons, SIGNAL(accepted()), this, SLOT(slot_export())); - connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); + connect(epw, &ExportPropertiesWidget::exportedAreaChanged, this, &ExportDialog::slot_changeUseBorder); + connect(buttons, &QDialogButtonBox::accepted, this, &ExportDialog::slot_export); + connect(buttons, &QDialogButtonBox::rejected, this, &ExportDialog::reject); // ajustement des extensions des fichiers slot_changeFilesExtension(true); @@ -140,21 +140,21 @@ QWidget *ExportDialog::initDiagramsListPart() reset_mapper_ = new QSignalMapper(this); clipboard_mapper_ = new QSignalMapper(this); - #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - connect(preview_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_previewDiagram); - connect(width_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctHeight); - connect(height_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctWidth); - connect(ratio_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_keepRatioChanged); - connect(reset_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_resetSize); - connect(clipboard_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_exportToClipBoard); - #else // TODO Qt6 only: remove, mappedInt() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // TODO Qt6 only: remove, mappedInt() always available connect(preview_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_previewDiagram(int))); connect(width_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctHeight(int))); connect(height_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_correctWidth(int))); connect(ratio_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_keepRatioChanged(int))); connect(reset_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_resetSize(int))); connect(clipboard_mapper_, SIGNAL(mapped(int)), this, SLOT(slot_exportToClipBoard(int))); - #endif +#else + connect(preview_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_previewDiagram); + connect(width_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctHeight); + connect(height_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_correctWidth); + connect(ratio_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_keepRatioChanged); + connect(reset_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_resetSize); + connect(clipboard_mapper_, &QSignalMapper::mappedInt, this, &ExportDialog::slot_exportToClipBoard); +#endif diagrams_list_layout_ = new QGridLayout(); @@ -174,7 +174,7 @@ QWidget *ExportDialog::initDiagramsListPart() diagrams_list_layout_ -> addLayout(diagram_line -> sizeLayout(), line_count, 3); // si on decoche tous les schemas, on desactive le bouton "Exporter" - connect(diagram_line -> must_export, SIGNAL(toggled(bool)), this, SLOT(slot_checkDiagramsCount())); + connect(diagram_line -> must_export, &QCheckBox::toggled, this, &ExportDialog::slot_checkDiagramsCount); // mappings et signaux pour la gestion des dimensions du schema width_mapper_ -> setMapping(diagram_line -> width, line_count); @@ -939,7 +939,7 @@ void ExportDialog::slot_previewDiagram(int diagram_id) { QGraphicsView *preview_view = new QGraphicsView(preview_scene); preview_view -> setDragMode(QGraphicsView::ScrollHandDrag); QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok); - connect(buttons, SIGNAL(accepted()), &preview_dialog, SLOT(accept())); + connect(buttons, &QDialogButtonBox::accepted, &preview_dialog, &QDialog::accept); QVBoxLayout *vboxlayout1 = new QVBoxLayout(); vboxlayout1 -> addWidget(preview_view); diff --git a/sources/exportpropertieswidget.cpp b/sources/exportpropertieswidget.cpp index aaa0966d0..b31dd3813 100644 --- a/sources/exportpropertieswidget.cpp +++ b/sources/exportpropertieswidget.cpp @@ -230,7 +230,7 @@ void ExportPropertiesWidget::build() setTabOrder(draw_colored_conductors, draw_bg_transparent); // connexion du bouton permettant le choix du repertoire - connect(button_browse, SIGNAL(released()), this, SLOT(slot_chooseADirectory())); + connect(button_browse, &QPushButton::released, this, &ExportPropertiesWidget::slot_chooseADirectory); // emission de signaux lors du changement de format et lors du changement de zone exportee connect(format, SIGNAL(currentIndexChanged(int)), this, SIGNAL(formatChanged())); diff --git a/sources/projectview.cpp b/sources/projectview.cpp index 2978d9745..4fee66bb6 100644 --- a/sources/projectview.cpp +++ b/sources/projectview.cpp @@ -763,8 +763,8 @@ int ProjectView::cleanProject() clean_dialog_layout -> addWidget(buttons); clean_dialog.setLayout(clean_dialog_layout); - connect(buttons, SIGNAL(accepted()), &clean_dialog, SLOT(accept())); - connect(buttons, SIGNAL(rejected()), &clean_dialog, SLOT(reject())); + connect(buttons, &QDialogButtonBox::accepted, &clean_dialog, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, &clean_dialog, &QDialog::reject); int clean_count = 0; if (clean_dialog.exec() == QDialog::Accepted) @@ -888,9 +888,9 @@ void ProjectView::initWidgets() m_tab -> setCornerWidget(tabwidgetLeft, Qt::TopLeftCorner); // manage signals - connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); - connect(m_tab, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(tabDoubleClicked(int))); - connect(m_tab->tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int)), Qt::QueuedConnection); + connect(m_tab, &QTabWidget::currentChanged, this, &ProjectView::tabChanged); + connect(m_tab, &QTabWidget::tabBarDoubleClicked, this, &ProjectView::tabDoubleClicked); + connect(m_tab->tabBar(), &QTabBar::tabMoved, this, &ProjectView::tabMoved, Qt::QueuedConnection); fallback_widget_ -> setVisible(false); m_tab -> setVisible(false); @@ -1119,9 +1119,9 @@ void ProjectView::setDiagramPosition(Diagram *diagram, int new_position) if (current_position < 0) return; - disconnect(m_tab->tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int))); + disconnect(m_tab->tabBar(), &QTabBar::tabMoved, this, &ProjectView::tabMoved); m_tab->tabBar()->moveTab(current_position, new_position); - connect(m_tab->tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int)), Qt::QueuedConnection); + connect(m_tab->tabBar(), &QTabBar::tabMoved, this, &ProjectView::tabMoved, Qt::QueuedConnection); rebuildDiagramsMap(); diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index 26d0b4cd6..7a7912fa7 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -122,11 +122,11 @@ QETApp::QETApp() : initSplashScreen(); initSystemTray(); - #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - connect(&signal_map, &QSignalMapper::mappedObject, this, [this](QObject *object) { invertMainWindowVisibility(qobject_cast(object)); }); - #else // TODO Qt6 only: remove, mappedObject() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // TODO Qt6 only: remove, mappedObject() always available connect(&signal_map, SIGNAL(mapped(QWidget *)), this, SLOT(invertMainWindowVisibility(QWidget *))); - #endif +#else + connect(&signal_map, &QSignalMapper::mappedObject, this, [this](QObject *object) { invertMainWindowVisibility(qobject_cast(object)); }); +#endif qApp->setQuitOnLastWindowClosed(false); connect(qApp, &QApplication::lastWindowClosed, this, &QETApp::checkRemainingWindows); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 208d36817..68d5bdd3b 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -107,11 +107,11 @@ QETDiagramEditor::QETDiagramEditor(const QStringList &files, QWidget *parent) : m_workspace.setTabsClosable(true); //Set the signal mapper - #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - connect(&windowMapper, &QSignalMapper::mappedObject, this, [this](QObject *object) { activateWidget(qobject_cast(object)); }); - #else // TODO Qt6 only: remove, mappedObject() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // TODO Qt6 only: remove, mappedObject() always available connect(&windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(activateWidget(QWidget *))); - #endif +#else + connect(&windowMapper, &QSignalMapper::mappedObject, this, [this](QObject *object) { activateWidget(qobject_cast(object)); }); +#endif setWindowTitle(tr("QElectroTech", "window title")); setWindowIcon(QET::Icons::QETLogo); @@ -133,14 +133,8 @@ QETDiagramEditor::QETDiagramEditor(const QStringList &files, QWidget *parent) : setMinimumSize(QSize(500, 350)); setWindowState(Qt::WindowMaximized); - connect (&m_workspace, - SIGNAL(subWindowActivated(QMdiSubWindow *)), - this, - SLOT(subWindowActivated(QMdiSubWindow*))); - connect (QApplication::clipboard(), - SIGNAL(dataChanged()), - this, - SLOT(slot_updatePasteAction())); + connect(&m_workspace, &QMdiArea::subWindowActivated, this, &QETDiagramEditor::subWindowActivated); + connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &QETDiagramEditor::slot_updatePasteAction); readSettings(); show(); @@ -188,16 +182,16 @@ void QETDiagramEditor::setUpElementsPanel() connect(pa, SIGNAL(requestForProject (QETProject *)), this, SLOT(activateProject(QETProject *))); connect(pa, SIGNAL(requestForProjectClosing (QETProject *)), this, SLOT(closeProject(QETProject *))); connect(pa, SIGNAL(requestForProjectPropertiesEdition (QETProject *)), this, SLOT(editProjectProperties(QETProject *))); - connect(pa, SIGNAL(requestForNewDiagram (QETProject *)), this, SLOT(addDiagramToProject(QETProject *))); + connect(pa, &ElementsPanelWidget::requestForNewDiagram, this, &QETDiagramEditor::addDiagramToProject); connect(pa, SIGNAL(requestForDiagramPropertiesEdition (Diagram *)), this, SLOT(editDiagramProperties(Diagram *))); - connect(pa, SIGNAL(requestForDiagramsDeletion (const QList &)), this, SLOT(removeDiagrams(const QList &))); - connect(pa, SIGNAL(requestForDiagramMoveUp (const QList &)), this, SLOT(moveDiagramUp(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveDown (const QList &)), this, SLOT(moveDiagramDown(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveUpTop (const QList &)), this, SLOT(moveDiagramUpTop(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveUpx10 (const QList &)), this, SLOT(moveDiagramUpx10(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveDownx10 (const QList &)), this, SLOT(moveDiagramDownx10(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveUpx100 (const QList &)), this, SLOT(moveDiagramUpx100(const QList&))); - connect(pa, SIGNAL(requestForDiagramMoveDownx100 (const QList &)), this, SLOT(moveDiagramDownx100(const QList&))); + connect(pa, &ElementsPanelWidget::requestForDiagramsDeletion, this, &QETDiagramEditor::removeDiagrams); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveUp, this, &QETDiagramEditor::moveDiagramUp); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveDown, this, &QETDiagramEditor::moveDiagramDown); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveUpTop, this, &QETDiagramEditor::moveDiagramUpTop); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveUpx10, this, &QETDiagramEditor::moveDiagramUpx10); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveDownx10, this, &QETDiagramEditor::moveDiagramDownx10); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveUpx100, this, &QETDiagramEditor::moveDiagramUpx100); + connect(pa, &ElementsPanelWidget::requestForDiagramMoveDownx100, this, &QETDiagramEditor::moveDiagramDownx100); } /** @@ -850,8 +844,7 @@ void QETDiagramEditor::setUpMenu() // File menu QMenu *recentfile = menu_fichier -> addMenu(QET::Icons::DocumentOpenRecent, tr("&Récemment ouverts")); recentfile->addActions(QETApp::projectsRecentFiles()->menu()->actions()); - connect(QETApp::projectsRecentFiles(), SIGNAL(fileOpeningRequested(const QString &)), - this, SLOT(openRecentFile(const QString &))); + connect(QETApp::projectsRecentFiles(), &RecentFiles::fileOpeningRequested, this, &QETDiagramEditor::openRecentFile); menu_fichier -> addActions(m_file_actions_group.actions()); menu_fichier -> addSeparator(); //menu_fichier -> addAction(import_diagram); @@ -1928,15 +1921,12 @@ void QETDiagramEditor::addProjectView(ProjectView *project_view) diagramWasAdded(dv); //Manage the close event of project - connect(project_view, SIGNAL(projectClosed(ProjectView*)), - this, SLOT(projectWasClosed(ProjectView *))); + connect(project_view, &ProjectView::projectClosed, this, &QETDiagramEditor::projectWasClosed); //Manage the adding of diagram - connect(project_view, SIGNAL(diagramAdded(DiagramView *)), - this, SLOT(diagramWasAdded(DiagramView *))); + connect(project_view, &ProjectView::diagramAdded, this, &QETDiagramEditor::diagramWasAdded); if (QETProject *project = project_view -> project()) - connect(project, SIGNAL(readOnlyChanged(QETProject *, bool)), - this, SLOT(slot_updateActions())); + connect(project, &QETProject::readOnlyChanged, this, &QETDiagramEditor::slot_updateActions); //Manage request for edit or find element and titleblock connect (project_view, &ProjectView::findElementRequired, @@ -2510,10 +2500,7 @@ void QETDiagramEditor::diagramWasAdded(DiagramView *dv) this, &QETDiagramEditor::selectionChanged, Qt::DirectConnection); - connect(dv, - SIGNAL(modeChanged()), - this, - SLOT(slot_updateModeActions())); + connect(dv, &DiagramView::modeChanged, this, &QETDiagramEditor::slot_updateModeActions); } /** diff --git a/sources/qetgraphicsitem/crossrefitem.cpp b/sources/qetgraphicsitem/crossrefitem.cpp index 4f00b6b53..847342238 100644 --- a/sources/qetgraphicsitem/crossrefitem.cpp +++ b/sources/qetgraphicsitem/crossrefitem.cpp @@ -113,10 +113,8 @@ void CrossRefItem::setUpConnection() set=true; else if(m_properties.snapTo() == XRefProperties::Bottom && !m_text && !m_group) //Snap to bottom of element and parent is the element itself { - m_update_connection << connect(m_element, SIGNAL(yChanged()), - this, SLOT(autoPos())); - m_update_connection << connect(m_element, SIGNAL(rotationChanged()), - this, SLOT(autoPos())); + m_update_connection << connect(m_element, &Element::yChanged, this, &CrossRefItem::autoPos); + m_update_connection << connect(m_element, &Element::rotationChanged, this, &CrossRefItem::autoPos); set=true; } diff --git a/sources/qetmainwindow.cpp b/sources/qetmainwindow.cpp index 6061e99d8..58e17713b 100644 --- a/sources/qetmainwindow.cpp +++ b/sources/qetmainwindow.cpp @@ -146,7 +146,7 @@ void QETMainWindow::initCommonMenus() settings_menu_ = new QMenu(tr("&Configuration", "window menu"), this); settings_menu_ -> addAction(fullscreen_action_); settings_menu_ -> addAction(configure_action_); - connect(settings_menu_, SIGNAL(aboutToShow()), this, SLOT(checkToolbarsmenu())); + connect(settings_menu_, &QMenu::aboutToShow, this, &QETMainWindow::checkToolbarsmenu); help_menu_ = new QMenu(tr("&Aide", "window menu"), this); help_menu_ -> addAction(whatsthis_action_); diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 9b115458d..1f323cc95 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -199,7 +199,7 @@ void QETProject::init() connect(&m_titleblocks_collection, &TitleBlockTemplatesCollection::aboutToRemove, this, &QETProject::removeDiagramsTitleBlockTemplate); m_undo_stack = new QUndoStack(this); - connect(m_undo_stack, SIGNAL(cleanChanged(bool)), this, SLOT(undoStackChanged(bool))); + connect(m_undo_stack, &QUndoStack::cleanChanged, this, &QETProject::undoStackChanged); m_save_backup_timer.setInterval(BACKUP_INTERVAL); connect(&m_save_backup_timer, &QTimer::timeout, this, &QETProject::writeBackup); diff --git a/sources/qfilenameedit.cpp b/sources/qfilenameedit.cpp index d81a86344..38bfa28c6 100644 --- a/sources/qfilenameedit.cpp +++ b/sources/qfilenameedit.cpp @@ -82,7 +82,7 @@ void QFileNameEdit::init() "tooltip content when editing a filename" ) ); - connect(validator_, SIGNAL(validationFailed()), this, SLOT(validationFailed())); + connect(validator_, &QETRegExpValidator::validationFailed, this, &QFileNameEdit::validationFailed); } /** diff --git a/sources/qtextorientationspinboxwidget.cpp b/sources/qtextorientationspinboxwidget.cpp index 0ca18d56b..14eefbb17 100644 --- a/sources/qtextorientationspinboxwidget.cpp +++ b/sources/qtextorientationspinboxwidget.cpp @@ -122,9 +122,9 @@ void QTextOrientationSpinBoxWidget::build() orientation_widget_, SLOT(setOrientation(double))); connect(orientation_widget_, - SIGNAL(orientationChanged(double)), + &QTextOrientationWidget::orientationChanged, spin_box_, - SLOT(setValue(double))); + &QDoubleSpinBox::setValue); // cliquer sur un des carres du QTextOrientationWidget revient a finir une saisie dans le SpinBox connect(orientation_widget_, @@ -134,8 +134,7 @@ void QTextOrientationSpinBoxWidget::build() // lorsque l'utilisateur a change l'orientation, // on emet un signal avec la valeur de la nouvelle orientation - connect(spin_box_, SIGNAL(editingFinished()), - this, SLOT(emitChangeSignals())); + connect(spin_box_, &QDoubleSpinBox::editingFinished, this, &QTextOrientationSpinBoxWidget::emitChangeSignals); // dispose les widgets : le QTextOrientationWidget a gauche, le SpinBox a droite QHBoxLayout *main_layout = new QHBoxLayout(); diff --git a/sources/richtext/richtexteditor.cpp b/sources/richtext/richtexteditor.cpp index 20afb4cc0..41515d02b 100644 --- a/sources/richtext/richtexteditor.cpp +++ b/sources/richtext/richtexteditor.cpp @@ -540,8 +540,7 @@ RichTextEditorToolBar::RichTextEditorToolBar(RichTextEditor *editor, addSeparator(); // Text color button - connect(m_color_action, SIGNAL(colorChanged(QColor)), - this, SLOT(colorChanged(QColor))); + connect(m_color_action, &ColorAction::colorChanged, this, &RichTextEditorToolBar::colorChanged); addAction(m_color_action); @@ -550,8 +549,7 @@ RichTextEditorToolBar::RichTextEditorToolBar(RichTextEditor *editor, QIcon(":/ico/32x32/simplifyrichtext.png"), tr("Simplify Rich Text"), editor, SLOT(setSimplifyRichText(bool)),this); m_simplify_richtext_action->setChecked(editor->simplifyRichText()); - connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), - m_simplify_richtext_action, SLOT(setChecked(bool))); + connect(m_editor, &RichTextEditor::simplifyRichTextChanged, m_simplify_richtext_action, &QAction::setChecked); addAction(m_simplify_richtext_action); connect(editor, SIGNAL(textChanged()), this, SLOT(updateActions())); @@ -779,7 +777,7 @@ RichTextEditorDialog::RichTextEditorDialog(QWidget *parent) : m_text_edit->setAcceptRichText(false); connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged())); - connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), this, SLOT(richTextChanged())); + connect(m_editor, &RichTextEditor::simplifyRichTextChanged, this, &RichTextEditorDialog::richTextChanged); connect(m_text_edit, SIGNAL(textChanged()), this, SLOT(sourceChanged())); // The toolbar needs to be created after the RichTextEditor @@ -798,16 +796,15 @@ RichTextEditorDialog::RichTextEditorDialog(QWidget *parent) : m_tab_widget->setTabPosition(QTabWidget::South); m_tab_widget->addTab(rich_edit, tr("Rich Text")); m_tab_widget->addTab(plain_edit, tr("Source")); - connect(m_tab_widget, SIGNAL(currentChanged(int)), - SLOT(tabIndexChanged(int))); + connect(m_tab_widget, &QTabWidget::currentChanged, this, &RichTextEditorDialog::tabIndexChanged); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); QPushButton *ok_button = buttonBox->button(QDialogButtonBox::Ok); ok_button->setText(tr("&OK")); ok_button->setDefault(true); buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("&Cancel")); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, &QDialogButtonBox::accepted, this, &RichTextEditorDialog::on_buttonBox_accepted); + connect(buttonBox, &QDialogButtonBox::rejected, this, &RichTextEditorDialog::reject); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(m_tab_widget); diff --git a/sources/titleblock/dimensionwidget.cpp b/sources/titleblock/dimensionwidget.cpp index 4d9a154fd..62d20df56 100644 --- a/sources/titleblock/dimensionwidget.cpp +++ b/sources/titleblock/dimensionwidget.cpp @@ -150,8 +150,8 @@ void TitleBlockDimensionWidget::initWidgets() // buttons, for the user to validate its input buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(buttons_, SIGNAL(accepted()), this, SLOT(accept())); - connect(buttons_, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttons_, &QDialogButtonBox::accepted, this, &TitleBlockDimensionWidget::accept); + connect(buttons_, &QDialogButtonBox::rejected, this, &TitleBlockDimensionWidget::reject); } /** diff --git a/sources/titleblock/integrationmovetemplateshandler.cpp b/sources/titleblock/integrationmovetemplateshandler.cpp index 4589a72f7..dd324466f 100644 --- a/sources/titleblock/integrationmovetemplateshandler.cpp +++ b/sources/titleblock/integrationmovetemplateshandler.cpp @@ -226,10 +226,10 @@ void IntegrationMoveTitleBlockTemplatesHandler::initDialog() dialog_vlayout_ -> addLayout(dialog_glayout); dialog_vlayout_ -> addWidget(buttons_); - connect(use_existing_template_, SIGNAL(toggled(bool)), this, SLOT(correctRadioButtons())); - connect(integrate_new_template_, SIGNAL(toggled(bool)), this, SLOT(correctRadioButtons())); - connect(buttons_, SIGNAL(accepted()), integ_dialog_, SLOT(accept())); - connect(buttons_, SIGNAL(rejected()), integ_dialog_, SLOT(reject())); + connect(use_existing_template_, &QRadioButton::toggled, this, &IntegrationMoveTitleBlockTemplatesHandler::correctRadioButtons); + connect(integrate_new_template_, &QRadioButton::toggled, this, &IntegrationMoveTitleBlockTemplatesHandler::correctRadioButtons); + connect(buttons_, &QDialogButtonBox::accepted, integ_dialog_, &QDialog::accept); + connect(buttons_, &QDialogButtonBox::rejected, integ_dialog_, &QDialog::reject); } /** diff --git a/sources/titleblock/qettemplateeditor.cpp b/sources/titleblock/qettemplateeditor.cpp index 9f41c88d2..65d06cbfc 100644 --- a/sources/titleblock/qettemplateeditor.cpp +++ b/sources/titleblock/qettemplateeditor.cpp @@ -342,7 +342,7 @@ void QETTitleBlockTemplateEditor::editLogos() QDialog d(this); d.setWindowTitle(logo_manager_ -> windowTitle()); d.setLayout(vlayout0); - connect(buttons, SIGNAL(rejected()), &d, SLOT(reject())); + connect(buttons, &QDialogButtonBox::rejected, &d, &QDialog::reject); d.exec(); // prevent the logo manager from being deleted along with the dialog @@ -553,35 +553,37 @@ void QETTitleBlockTemplateEditor::initWidgets() template_cell_editor_widget_ -> setVisible(false); connect( - template_edition_area_view_, - SIGNAL(selectedCellsChanged(QList)), - this, - SLOT(selectedCellsChanged(QList)) + template_edition_area_view_, + &TitleBlockTemplateView::selectedCellsChanged, + this, + &QETTitleBlockTemplateEditor::selectedCellsChanged + ); + connect( + template_cell_editor_widget_, + &TitleBlockTemplateCellWidget::logoEditionRequested, + this, + &QETTitleBlockTemplateEditor::editLogos ); - connect(template_cell_editor_widget_, SIGNAL(logoEditionRequested()), - this, SLOT(editLogos())); connect( template_cell_editor_widget_, - SIGNAL(cellModified(ModifyTitleBlockCellCommand *)), + &TitleBlockTemplateCellWidget::cellModified, this, - SLOT(pushCellUndoCommand(ModifyTitleBlockCellCommand *)) + &QETTitleBlockTemplateEditor::pushCellUndoCommand ); connect( template_edition_area_view_, - SIGNAL(gridModificationRequested(TitleBlockTemplateCommand *)), + &TitleBlockTemplateView::gridModificationRequested, this, - SLOT(pushGridUndoCommand(TitleBlockTemplateCommand *)) + &QETTitleBlockTemplateEditor::pushGridUndoCommand ); connect( template_edition_area_view_, - SIGNAL(previewWidthChanged(int,int)), + &TitleBlockTemplateView::previewWidthChanged, this, - SLOT(savePreviewWidthToApplicationSettings(int, int)) + &QETTitleBlockTemplateEditor::savePreviewWidthToApplicationSettings ); - connect(undo_stack_, SIGNAL(cleanChanged(bool)), - this, SLOT(updateEditorTitle())); - connect(QApplication::clipboard(), SIGNAL(dataChanged()), - this, SLOT(updateActions())); + connect(undo_stack_, &QUndoStack::cleanChanged, this, &QETTitleBlockTemplateEditor::updateEditorTitle); + connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &QETTitleBlockTemplateEditor::updateActions); } /** @@ -960,8 +962,8 @@ TitleBlockTemplateLocation QETTitleBlockTemplateEditor::getTitleBlockTemplateLoc dialog.setWindowTitle(title); dialog.setLayout(dialog_layout); - connect(buttons, SIGNAL(accepted()), &dialog, SLOT(accept())); - connect(buttons, SIGNAL(rejected()), &dialog, SLOT(reject())); + connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); if (dialog.exec() == QDialog::Accepted) { return(widget -> location()); @@ -1027,10 +1029,8 @@ void QETTitleBlockTemplateEditor::editTemplateInformation() : QDialogButtonBox::Ok | QDialogButtonBox::Cancel); dialog_layout -> addWidget(dialog_buttons); - connect(dialog_buttons, SIGNAL(accepted()), - &dialog_author, SLOT(accept())); - connect(dialog_buttons, SIGNAL(rejected()), - &dialog_author, SLOT(reject())); + connect(dialog_buttons, &QDialogButtonBox::accepted, &dialog_author, &QDialog::accept); + connect(dialog_buttons, &QDialogButtonBox::rejected, &dialog_author, &QDialog::reject); // run the dialog if (dialog_author.exec() == QDialog::Accepted && !read_only_) { diff --git a/sources/titleblock/templatecellwidget.cpp b/sources/titleblock/templatecellwidget.cpp index b98759aca..2cbb6fbd2 100644 --- a/sources/titleblock/templatecellwidget.cpp +++ b/sources/titleblock/templatecellwidget.cpp @@ -150,10 +150,10 @@ void TitleBlockTemplateCellWidget::initWidgets() // handle cell modifications connect(cell_type_input_, SIGNAL(activated(int)), this, SLOT(updateFormType(int))); connect(cell_type_input_, SIGNAL(activated(int)), this, SLOT(editType())); - connect(name_input_, SIGNAL(editingFinished()), this, SLOT(editName())); + connect(name_input_, &QLineEdit::editingFinished, this, &TitleBlockTemplateCellWidget::editName); connect(label_checkbox_, SIGNAL(clicked(bool)), this, SLOT(editLabelDisplayed())); - connect(label_edit_, SIGNAL(released()), this, SLOT(editLabel())); - connect(value_edit_, SIGNAL(released()), this, SLOT(editValue())); + connect(label_edit_, &QPushButton::released, this, &TitleBlockTemplateCellWidget::editLabel); + connect(value_edit_, &QPushButton::released, this, &TitleBlockTemplateCellWidget::editValue); connect(horiz_align_input_, SIGNAL(activated(int)), this, SLOT(editAlignment())); connect(vert_align_input_, SIGNAL(activated(int)), this, SLOT(editAlignment())); connect(font_size_input_, SIGNAL(valueChanged(int)), this, SLOT(editFontSize())); diff --git a/sources/titleblock/templatelogomanager.cpp b/sources/titleblock/templatelogomanager.cpp index 8b4d04cd4..c9ca7a36b 100644 --- a/sources/titleblock/templatelogomanager.cpp +++ b/sources/titleblock/templatelogomanager.cpp @@ -129,10 +129,10 @@ void TitleBlockTemplateLogoManager::initWidgets() this, SLOT(updateLogoInformations(QListWidgetItem *, QListWidgetItem *)) ); - connect(add_button_, SIGNAL(released()), this, SLOT(addLogo())); - connect(export_button_, SIGNAL(released()), this, SLOT(exportLogo())); - connect(delete_button_, SIGNAL(released()), this, SLOT(removeLogo())); - connect(rename_button_, SIGNAL(released()), this, SLOT(renameLogo())); + connect(add_button_, &QPushButton::released, this, &TitleBlockTemplateLogoManager::addLogo); + connect(export_button_, &QPushButton::released, this, &TitleBlockTemplateLogoManager::exportLogo); + connect(delete_button_, &QPushButton::released, this, &TitleBlockTemplateLogoManager::removeLogo); + connect(rename_button_, &QPushButton::released, this, &TitleBlockTemplateLogoManager::renameLogo); } /** @@ -217,11 +217,12 @@ QString TitleBlockTemplateLogoManager::confirmLogoName(const QString &initial_na connect(replace_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); connect(rename_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); connect(cancel_button, SIGNAL(clicked()), signal_mapper, SLOT(map())); - #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - connect(signal_mapper, &QSignalMapper::mappedInt, rename_dialog, &QDialog::done); - #else // TOD Qt6 only: remove, mappedInt() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // TODO Qt6 only: remove, mappedInt() always available connect(signal_mapper, SIGNAL(mapped(int)), rename_dialog, SLOT(done(int))); - #endif + +#else + connect(signal_mapper, &QSignalMapper::mappedInt, rename_dialog, &QDialog::done); +#endif } rd_label -> setText( QString(tr( diff --git a/sources/titleblock/templatescollection.cpp b/sources/titleblock/templatescollection.cpp index 5ffc44caf..e26646c70 100644 --- a/sources/titleblock/templatescollection.cpp +++ b/sources/titleblock/templatescollection.cpp @@ -383,7 +383,7 @@ TitleBlockTemplatesFilesCollection::TitleBlockTemplatesFilesCollection(const QSt if (dir_.exists()) { watcher_.addPath(dir_.canonicalPath()); } - connect(&watcher_, SIGNAL(directoryChanged(const QString &)), this, SLOT(fileSystemChanged(const QString &))); + connect(&watcher_, &QFileSystemWatcher::directoryChanged, this, &TitleBlockTemplatesFilesCollection::fileSystemChanged); } /** diff --git a/sources/titleblock/templateview.cpp b/sources/titleblock/templateview.cpp index 096f96c0f..ca5f5421b 100644 --- a/sources/titleblock/templateview.cpp +++ b/sources/titleblock/templateview.cpp @@ -597,7 +597,7 @@ void TitleBlockTemplateView::init() setTransformationAnchor(QGraphicsView::AnchorUnderMouse); setBackgroundBrush(QBrush(QColor(248, 255, 160))); - connect(scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); + connect(scene(), &QGraphicsScene::selectionChanged, this, &TitleBlockTemplateView::selectionChanged); } /** @@ -626,7 +626,7 @@ void TitleBlockTemplateView::applyColumnsWidths(bool animate) { animation -> setStartValue(QVariant(tbgrid_ -> columnMinimumWidth(COL_OFFSET + i))); animation -> setEndValue(QVariant(1.0 * applied_width)); animation -> setDuration(500); - connect(animation, SIGNAL(finished()), this, SLOT(updateColumnsHelperCells())); + connect(animation, &GridLayoutAnimation::finished, this, &TitleBlockTemplateView::updateColumnsHelperCells); animation -> start(QAbstractAnimation::DeleteWhenStopped); } total_applied_width += applied_width; @@ -747,10 +747,8 @@ void TitleBlockTemplateView::addCells() updateTotalWidthLabel(); total_width_helper_cell_ -> orientation = Qt::Horizontal; total_width_helper_cell_ -> setActions(QList() << change_preview_width_); - connect(total_width_helper_cell_, SIGNAL(contextMenuTriggered(HelperCell *)), - this, SLOT(updateLastContextMenuCell(HelperCell *))); - connect(total_width_helper_cell_, SIGNAL(doubleClicked(HelperCell*)), - this, SLOT(changePreviewWidth())); + connect(total_width_helper_cell_, &HelperCell::contextMenuTriggered, this, &TitleBlockTemplateView::updateLastContextMenuCell); + connect(total_width_helper_cell_, &HelperCell::doubleClicked, this, &TitleBlockTemplateView::changePreviewWidth); tbgrid_ -> addItem(total_width_helper_cell_, 0, COL_OFFSET, 1, col_count); // we also initialize an extra helper cells that shows the preview width is @@ -767,10 +765,8 @@ void TitleBlockTemplateView::addCells() current_col_cell -> setActions(columnsActions()); current_col_cell -> orientation = Qt::Horizontal; current_col_cell -> index = i; - connect(current_col_cell, SIGNAL(contextMenuTriggered(HelperCell *)), - this, SLOT(updateLastContextMenuCell(HelperCell *))); - connect(current_col_cell, SIGNAL(doubleClicked(HelperCell*)), - this, SLOT(editColumn(HelperCell *))); + connect(current_col_cell, &HelperCell::contextMenuTriggered, this, &TitleBlockTemplateView::updateLastContextMenuCell); + connect(current_col_cell, &HelperCell::doubleClicked, this, &TitleBlockTemplateView::editColumn); tbgrid_ -> addItem(current_col_cell, 1, COL_OFFSET + i, 1, 1); } @@ -783,10 +779,8 @@ void TitleBlockTemplateView::addCells() current_row_cell -> orientation = Qt::Vertical; current_row_cell -> index = i; current_row_cell -> setActions(rowsActions()); - connect(current_row_cell, SIGNAL(contextMenuTriggered(HelperCell *)), - this, SLOT(updateLastContextMenuCell(HelperCell *))); - connect(current_row_cell, SIGNAL(doubleClicked(HelperCell*)), - this, SLOT(editRow(HelperCell *))); + connect(current_row_cell, &HelperCell::contextMenuTriggered, this, &TitleBlockTemplateView::updateLastContextMenuCell); + connect(current_row_cell, &HelperCell::doubleClicked, this, &TitleBlockTemplateView::editRow); tbgrid_ -> addItem(current_row_cell, ROW_OFFSET + i, 0, 1, 1); } diff --git a/sources/ui/configpage/configpages.cpp b/sources/ui/configpage/configpages.cpp index 1a01a343e..25da62af2 100644 --- a/sources/ui/configpage/configpages.cpp +++ b/sources/ui/configpage/configpages.cpp @@ -110,7 +110,7 @@ NewDiagramPage::NewDiagramPage(QETProject *project, xrefpw -> setProperties (m_project -> defaultXRefProperties()); } - connect(ipw,SIGNAL(openAutoNumFolioEditor(QString)),this,SLOT(changeToAutoFolioTab())); + connect(ipw, &TitleBlockPropertiesWidget::openAutoNumFolioEditor, this, &NewDiagramPage::changeToAutoFolioTab); // main tab widget QTabWidget *tab_widget = new QTabWidget(this); @@ -138,7 +138,7 @@ NewDiagramPage::NewDiagramPage(QETProject *project, */ NewDiagramPage::~NewDiagramPage() { - disconnect(ipw,SIGNAL(openAutoNumFolioEditor(QString)),this,SLOT(changeToAutoFolioTab())); + disconnect(ipw, &TitleBlockPropertiesWidget::openAutoNumFolioEditor, this, &NewDiagramPage::changeToAutoFolioTab); } /** diff --git a/sources/ui/configpage/projectconfigpages.cpp b/sources/ui/configpage/projectconfigpages.cpp index f12df6866..22da41ebe 100644 --- a/sources/ui/configpage/projectconfigpages.cpp +++ b/sources/ui/configpage/projectconfigpages.cpp @@ -391,37 +391,37 @@ void ProjectAutoNumConfigPage::adjustReadOnly() void ProjectAutoNumConfigPage::buildConnections() { //Management Tab - connect (m_amw, SIGNAL(applyPressed()), this, SLOT(applyManagement())); + connect(m_amw, &AutoNumberingManagementW::applyPressed, this, &ProjectAutoNumConfigPage::applyManagement); //Conductor Tab connect(m_saw_conductor, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextConductor); connect(m_saw_conductor, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextConductor); - #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - connect(m_saw_conductor->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextConductor); - #else // TODO Qt6 only: remove, textActivated() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // TODO Qt6 only: remove, textActivated() always available connect(m_saw_conductor->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextConductor(QString))); - #endif +#else + connect(m_saw_conductor->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextConductor); +#endif //Element Tab connect(m_saw_element, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextElement); connect(m_saw_element, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextElement); - #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - connect(m_saw_element->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextElement); - #else // TODO Qt6 only: remove, textActivated() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // TODO Qt6 only: remove, textActivated() always available connect(m_saw_element->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextElement(QString))); - #endif +#else + connect(m_saw_element->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextElement); +#endif //Folio Tab connect(m_saw_folio, &SelectAutonumW::applyPressed, this, &ProjectAutoNumConfigPage::saveContextFolio); connect(m_saw_folio, &SelectAutonumW::removeClicked, this, &ProjectAutoNumConfigPage::removeContextFolio); - #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) - connect(m_saw_folio->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextFolio); - #else // TODO Qt6 only: remove, textActivated() always available +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // TODO Qt6 only: remove, textActivated() always available connect(m_saw_folio->contextComboBox(), SIGNAL(activated(QString)), this, SLOT(updateContextFolio(QString))); - #endif +#else + connect(m_saw_folio->contextComboBox(), &QComboBox::textActivated, this, &ProjectAutoNumConfigPage::updateContextFolio); +#endif // Auto Folio Numbering - connect (m_faw, SIGNAL (applyPressed()), this, SLOT (applyAutoNum())); + connect(m_faw, &FolioAutonumberingW::applyPressed, this, &ProjectAutoNumConfigPage::applyAutoNum); } /** diff --git a/sources/ui/diagramcontextwidget.cpp b/sources/ui/diagramcontextwidget.cpp index 9cacb2685..396c89b2e 100644 --- a/sources/ui/diagramcontextwidget.cpp +++ b/sources/ui/diagramcontextwidget.cpp @@ -25,7 +25,7 @@ DiagramContextWidget::DiagramContextWidget(QWidget *parent) : ui(new Ui::DiagramContextWidget) { ui->setupUi(this); - connect(ui->m_table, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(checkTableRows())); + connect(ui->m_table, &QTableWidget::itemChanged, this, &DiagramContextWidget::checkTableRows); } DiagramContextWidget::~DiagramContextWidget() diff --git a/sources/ui/diagrampropertiesdialog.cpp b/sources/ui/diagrampropertiesdialog.cpp index 3496fcdae..e07de4a6a 100644 --- a/sources/ui/diagrampropertiesdialog.cpp +++ b/sources/ui/diagrampropertiesdialog.cpp @@ -62,7 +62,7 @@ DiagramPropertiesDialog::DiagramPropertiesDialog(Diagram *diagram, QWidget *pare titleblock_infos = new TitleBlockPropertiesWidget(titleblock, false, diagram->project(), this); titleblock_infos -> setReadOnly(diagram_is_read_only); - connect(titleblock_infos,SIGNAL(openAutoNumFolioEditor(QString)),this,SLOT(editAutoFolioNum())); + connect(titleblock_infos, &TitleBlockPropertiesWidget::openAutoNumFolioEditor, this, &DiagramPropertiesDialog::editAutoFolioNum); //titleblock_infos->setMinimumSize(590,480); //Minimum Size needed for correct display //Conductor widget @@ -77,8 +77,8 @@ DiagramPropertiesDialog::DiagramPropertiesDialog(Diagram *diagram, QWidget *pare // Buttons QDialogButtonBox boutons(diagram_is_read_only ? QDialogButtonBox::Ok : QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - connect(&boutons, SIGNAL(accepted()), this, SLOT(accept())); - connect(&boutons, SIGNAL(rejected()), this, SLOT(reject())); + connect(&boutons, &QDialogButtonBox::accepted, this, &DiagramPropertiesDialog::accept); + connect(&boutons, &QDialogButtonBox::rejected, this, &DiagramPropertiesDialog::reject); QGridLayout *glayout = new QGridLayout; glayout->addWidget(border_infos,0,0); diff --git a/sources/ui/diagrampropertieseditordockwidget.cpp b/sources/ui/diagrampropertieseditordockwidget.cpp index 21ca88f13..13be007f8 100644 --- a/sources/ui/diagrampropertieseditordockwidget.cpp +++ b/sources/ui/diagrampropertieseditordockwidget.cpp @@ -45,19 +45,15 @@ void DiagramPropertiesEditorDockWidget::setDiagram(Diagram *diagram) if (m_diagram) { - disconnect(m_diagram, SIGNAL(selectionChanged()), - this, SLOT(selectionChanged())); - disconnect(m_diagram, SIGNAL(destroyed()), - this, SLOT(diagramWasDeleted())); + disconnect(m_diagram, &Diagram::selectionChanged, this, &DiagramPropertiesEditorDockWidget::selectionChanged); + disconnect(m_diagram, &QObject::destroyed, this, &DiagramPropertiesEditorDockWidget::diagramWasDeleted); } if (diagram) { m_diagram = diagram; - connect(m_diagram, SIGNAL(selectionChanged()), - this, SLOT(selectionChanged()), Qt::QueuedConnection); - connect(m_diagram, SIGNAL(destroyed()), - this, SLOT(diagramWasDeleted())); + connect(m_diagram, &Diagram::selectionChanged, this, &DiagramPropertiesEditorDockWidget::selectionChanged, Qt::QueuedConnection); + connect(m_diagram, &QObject::destroyed, this, &DiagramPropertiesEditorDockWidget::diagramWasDeleted); selectionChanged(); } else diff --git a/sources/ui/linksingleelementwidget.cpp b/sources/ui/linksingleelementwidget.cpp index 528a20e8a..08c65cc55 100644 --- a/sources/ui/linksingleelementwidget.cpp +++ b/sources/ui/linksingleelementwidget.cpp @@ -717,8 +717,7 @@ void LinkSingleElementWidget::on_m_tree_widget_itemDoubleClicked( if (m_showed_element) { - disconnect(m_showed_element, SIGNAL(destroyed()), - this, SLOT(showedElementWasDeleted())); + disconnect(m_showed_element, &QObject::destroyed, this, &LinkSingleElementWidget::showedElementWasDeleted); m_showed_element->setHighlighted(false); } @@ -726,8 +725,7 @@ void LinkSingleElementWidget::on_m_tree_widget_itemDoubleClicked( elmt->diagram()->showMe(); elmt->setHighlighted(true); m_showed_element = elmt; - connect(m_showed_element, SIGNAL(destroyed()), - this, SLOT(showedElementWasDeleted())); + connect(m_showed_element, &QObject::destroyed, this, &LinkSingleElementWidget::showedElementWasDeleted); } diff --git a/sources/ui/masterpropertieswidget.cpp b/sources/ui/masterpropertieswidget.cpp index e5952a5e5..813ac95cb 100644 --- a/sources/ui/masterpropertieswidget.cpp +++ b/sources/ui/masterpropertieswidget.cpp @@ -154,14 +154,12 @@ void MasterPropertiesWidget::setElement(Element *element) m_element->setHighlighted(false); if (m_project) - disconnect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)), - this, SLOT(diagramWasdeletedFromProject())); + disconnect(m_project, &QETProject::diagramRemoved, this, &MasterPropertiesWidget::diagramWasdeletedFromProject); if(Q_LIKELY(element->diagram() && element->diagram()->project())) { m_project = element->diagram()->project(); - connect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)), - this, SLOT(diagramWasdeletedFromProject())); + connect(m_project, &QETProject::diagramRemoved, this, &MasterPropertiesWidget::diagramWasdeletedFromProject); } else m_project = nullptr; @@ -397,8 +395,7 @@ void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int colum Q_UNUSED(column); if (m_showed_element) { - disconnect(m_showed_element, SIGNAL(destroyed()), - this, SLOT(showedElementWasDeleted())); + disconnect(m_showed_element, &QObject::destroyed, this, &MasterPropertiesWidget::showedElementWasDeleted); m_showed_element -> setHighlighted(false); } if (m_element) @@ -407,8 +404,7 @@ void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int colum m_showed_element = m_qtwi_hash[qtwi]; m_showed_element->diagram()->showMe(); m_showed_element->setHighlighted(true); - connect(m_showed_element, SIGNAL(destroyed()), - this, SLOT(showedElementWasDeleted())); + connect(m_showed_element, &QObject::destroyed, this, &MasterPropertiesWidget::showedElementWasDeleted); } /** diff --git a/sources/ui/projectpropertiesdialog.cpp b/sources/ui/projectpropertiesdialog.cpp index b9bea1c71..28dfc07c0 100644 --- a/sources/ui/projectpropertiesdialog.cpp +++ b/sources/ui/projectpropertiesdialog.cpp @@ -45,8 +45,8 @@ ProjectPropertiesDialog::ProjectPropertiesDialog(QETProject *project, QWidget *p m_properties_dialog->addPage(new TerminalStripProjectConfigPage { project, parent }); connect(projectAutoNumConfigPage,SIGNAL(setAutoNum(QString)),newDiagramPage,SLOT(setFolioAutonum(QString))); - connect(projectAutoNumConfigPage,SIGNAL(saveCurrentTbp()),newDiagramPage,SLOT(saveCurrentTbp())); - connect(projectAutoNumConfigPage,SIGNAL(loadSavedTbp()),newDiagramPage,SLOT(loadSavedTbp())); + connect(projectAutoNumConfigPage, &ProjectAutoNumConfigPage::saveCurrentTbp, newDiagramPage, &NewDiagramPage::saveCurrentTbp); + connect(projectAutoNumConfigPage, &ProjectAutoNumConfigPage::loadSavedTbp, newDiagramPage, &NewDiagramPage::loadSavedTbp); } /** diff --git a/sources/ui/xrefpropertieswidget.cpp b/sources/ui/xrefpropertieswidget.cpp index 94c03a72a..7909c44df 100644 --- a/sources/ui/xrefpropertieswidget.cpp +++ b/sources/ui/xrefpropertieswidget.cpp @@ -37,7 +37,7 @@ XRefPropertiesWidget::XRefPropertiesWidget(QHash prope { ui->setupUi(this); buildUi(); - connect(ui->m_display_has_cross_rb, SIGNAL(toggled(bool)), ui->m_cross_properties_gb, SLOT(setEnabled(bool))); + connect(ui->m_display_has_cross_rb, &QRadioButton::toggled, ui->m_cross_properties_gb, &QWidget::setEnabled); connect(ui->m_type_cb, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged())); connect(ui->m_snap_to_cb, SIGNAL(currentIndexChanged(int)), this, SLOT(enableOffsetSB(int))); updateDisplay(); @@ -49,7 +49,7 @@ XRefPropertiesWidget::XRefPropertiesWidget(QHash prope */ XRefPropertiesWidget::~XRefPropertiesWidget() { - disconnect(ui->m_display_has_cross_rb, SIGNAL(toggled(bool)), ui->m_cross_properties_gb, SLOT(setEnabled(bool))); + disconnect(ui->m_display_has_cross_rb, &QRadioButton::toggled, ui->m_cross_properties_gb, &QWidget::setEnabled); disconnect(ui->m_type_cb, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged())); disconnect(ui->m_snap_to_cb, SIGNAL(currentIndexChanged(int)), this, SLOT(enableOffsetSB(int))); delete ui; From e8f80697f3cfe7278df49624073a8c9725f7d376 Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Sat, 8 Aug 2026 07:03:50 +0200 Subject: [PATCH 033/350] Reapply "Auto-break conductor" This reverts commit 905afc1bbc27347e514c409d462295e5c47f1581. --- .../diagramevent/diagrameventaddelement.cpp | 246 +++++++++++++++++- sources/qetdiagrameditor.cpp | 21 ++ sources/qetdiagrameditor.h | 2 + sources/qetproject.cpp | 28 ++ sources/qetproject.h | 4 + 5 files changed, 293 insertions(+), 8 deletions(-) diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index dee2834c0..9949c54d8 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -20,11 +20,44 @@ #include "../conductorautonumerotation.h" #include "../diagram.h" #include "../undocommand/addgraphicsobjectcommand.h" +#include "../undocommand/deleteqgraphicsitemcommand.h" #include "../factory/elementfactory.h" #include "../qetapp.h" #include "../qetdiagrameditor.h" #include "../qetgraphicsitem/element.h" #include "../qetgraphicsitem/conductor.h" +#include "../qetgraphicsitem/terminal.h" +#include "../qet.h" +#include +#include + +namespace { + /** + @brief distanceToSegment + @param point : point to measure from + @param segment : the finite segment (not the infinite line through it) + @return the distance from @a point to the closest point actually on + @a segment. Unlike QET::orthogonalProjection(), which reports a hit + for any point on the segment's infinite extension, this clamps the + projection to the segment itself: a point collinear with a wire but + past its actual drawn end is correctly reported as far away, not "on" + the wire. + */ + qreal distanceToSegment(const QPointF &point, const QLineF &segment) + { + const QPointF a = segment.p1(); + const QPointF b = segment.p2(); + const QPointF ab = b - a; + const qreal len2 = QPointF::dotProduct(ab, ab); + + if (len2 <= 0.0) + return QLineF(point, a).length(); + + qreal t = QPointF::dotProduct(point - a, ab) / len2; + t = qBound(0.0, t, 1.0); + return QLineF(point, a + t * ab).length(); + } +} /** @brief DiagramEventAddElement::DiagramEventAddElement @@ -248,16 +281,213 @@ void DiagramEventAddElement::addElement() QUndoCommand *undo_object = new QUndoCommand(tr("Ajouter %1").arg(element->name())); new AddGraphicsObjectCommand(element, m_diagram, m_element -> pos(), undo_object); - //When we search for free aligned terminal we temporally remove m_element to - //avoid any interaction with the function Element::AlignedFreeTerminals - //This is useful when an element has two (or more) terminals on opposite sides, - //because m_element is exactly at the same pos of the new element - //added to the scene so new conductor are created between terminal of the new element - //and the opposite terminal of m_element. + //When we search for free aligned terminal we temporally remove m_element to + //avoid any interaction with the function Element::AlignedFreeTerminals + //This is useful when an element has two (or more) terminals on opposite sides, + //because m_element is exactly at the same pos of the new element + //added to the scene so new conductor are created between terminal of the new element + //and the opposite terminal of m_element. m_diagram->removeItem(m_element); - while (!element -> AlignedFreeTerminals().isEmpty() && m_diagram -> project() -> autoConductor()) + + //Auto break conductor: if a terminal of the new element lies on an existing + //conductor, break the conductor and reconnect through the new element's terminal. + //Track the endpoints of broken conductors so auto-connect doesn't create duplicates. + QSet broken_endpoints; + + if (m_diagram->project()->autoBreakConductor()) { - QPair pair = element -> AlignedFreeTerminals().takeFirst(); + //Track which conductors we already handled for this element + QList conductors_handled; + //Track which terminals of the new element are already used (by break or other-connect) + QSet used_terminals; + + foreach (Terminal *t, element->terminals()) + { + //Skip terminals already used by a previous break+reconnect (other_terminal) + if (used_terminals.contains(t)) + continue; + + QPointF t_dock = t->dockConductor(); + + //Collect all conductors that pass through this dock point. + struct ConductorMatch { + Conductor *conductor; + Terminal *connect_to; //endpoint "before" the dock point (based on orientation) + Terminal *other; //endpoint "after" the dock point + }; + QList all_matches; + + foreach (Conductor *c, m_diagram->conductors()) + { + //Skip conductors we already handled or connected to the new element + if (conductors_handled.contains(c) || + c->terminal1->parentElement() == element || + c->terminal2->parentElement() == element) + continue; + + //Check if dock point lies on the conductor path. Distance is + //measured to the segment itself (clamped), not the infinite + //line through it -- see distanceToSegment(). + QPointF local_dock = c->mapFromScene(t_dock); + bool point_on_conductor = false; + QPainterPath path = c->path(); + for (int i = 0; i < path.elementCount() - 1; ++i) + { + const QPainterPath::Element &e1 = path.elementAt(i); + const QPainterPath::Element &e2 = path.elementAt(i + 1); + QLineF segment(QPointF(e1.x, e1.y), QPointF(e2.x, e2.y)); + if (distanceToSegment(local_dock, segment) < 5.0) + { + point_on_conductor = true; + break; + } + } + + if (!point_on_conductor) + continue; + + Terminal *c1 = c->terminal1; + Terminal *c2 = c->terminal2; + QPointF c1_dock = c1->dockConductor(); + QPointF c2_dock = c2->dockConductor(); + + Terminal *connect_to = nullptr; + Terminal *other = nullptr; + + switch (t->orientation()) { + case Qet::North: + if (c1_dock.y() < t_dock.y()) { connect_to = c1; other = c2; } + else if (c2_dock.y() < t_dock.y()) { connect_to = c2; other = c1; } + break; + case Qet::South: + if (c1_dock.y() > t_dock.y()) { connect_to = c1; other = c2; } + else if (c2_dock.y() > t_dock.y()) { connect_to = c2; other = c1; } + break; + case Qet::East: + if (c1_dock.x() > t_dock.x()) { connect_to = c1; other = c2; } + else if (c2_dock.x() > t_dock.x()) { connect_to = c2; other = c1; } + break; + case Qet::West: + if (c1_dock.x() < t_dock.x()) { connect_to = c1; other = c2; } + else if (c2_dock.x() < t_dock.x()) { connect_to = c2; other = c1; } + break; + } + + if (!connect_to) { + qreal d1 = QLineF(t_dock, c1_dock).length(); + qreal d2 = QLineF(t_dock, c2_dock).length(); + if (d1 <= d2) { connect_to = c1; other = c2; } + else { connect_to = c2; other = c1; } + } + + all_matches.append({c, connect_to, other}); + } + + if (all_matches.isEmpty()) + continue; + + //Group matches by their "other" endpoint and find the largest group. + //This ensures that when multiple independent circuits cross at the + //same dock point, the group with the most conductors gets priority, + //not whichever happens to have the nearest connect_to endpoint. + QMap> groups; + for (const auto &m : all_matches) { + groups[m.other].append(m); + } + Terminal *best_other = nullptr; + int best_count = 0; + for (auto it = groups.constBegin(); it != groups.constEnd(); ++it) { + if (it.value().size() > best_count) { + best_count = it.value().size(); + best_other = it.key(); + } + } + + //Only break conductors in the largest group (same "other" endpoint). + //This prevents bridging independent nets: if two unrelated conductors + //cross at a dock point, only the larger group gets broken. + const QList &matches = groups[best_other]; + + //Mark terminal as used + used_terminals.insert(t); + + //Delete all matched conductors in one batch + DiagramContent content; + for (const auto &m : matches) { + content.m_other_conductors.append(m.conductor); + conductors_handled.append(m.conductor); + } + new DeleteQGraphicsItemCommand(m_diagram, content, undo_object); + + //Create new conductors from each connect_to endpoint to this terminal. + //This creates junctions at the terminal when multiple conductors + //from the same circuit pass through the dock point (e.g. left and + //right conductors going to the same terminal strip terminal). + for (const auto &m : matches) { + Conductor *new_c = new Conductor(m.connect_to, t); + new AddGraphicsObjectCommand(new_c, m_diagram, QPointF(), undo_object); + ConductorAutoNumerotation can(new_c, m_diagram, undo_object); + can.numerate(); + if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) + new_c->setFreezeLabel(true); + + broken_endpoints.insert(m.connect_to); + } + + //Connect the shared "other" endpoint to the nearest free terminal + //with matching orientation. + QPointF other_dock = best_other->dockConductor(); + Terminal *other_terminal = nullptr; + qreal best_dist = std::numeric_limits::max(); + foreach (Terminal *ot, element->terminals()) + { + if (used_terminals.contains(ot)) + continue; + + //Check that the other_dock approaches from the correct direction + //relative to the candidate terminal's orientation. + QPointF ot_dock = ot->dockConductor(); + bool orientation_ok = false; + switch (ot->orientation()) { + case Qet::North: orientation_ok = other_dock.y() < ot_dock.y(); break; + case Qet::South: orientation_ok = other_dock.y() > ot_dock.y(); break; + case Qet::East: orientation_ok = other_dock.x() > ot_dock.x(); break; + case Qet::West: orientation_ok = other_dock.x() < ot_dock.x(); break; + } + if (!orientation_ok) + continue; + + qreal dist = QLineF(ot_dock, other_dock).length(); + if (dist < best_dist) { + best_dist = dist; + other_terminal = ot; + } + } + + if (other_terminal) { + Conductor *new_c2 = new Conductor(best_other, other_terminal); + new AddGraphicsObjectCommand(new_c2, m_diagram, QPointF(), undo_object); + ConductorAutoNumerotation can2(new_c2, m_diagram, undo_object); + can2.numerate(); + if (m_diagram->freezeNewConductors() || m_diagram->project()->isFreezeNewConductors()) + new_c2->setFreezeLabel(true); + + broken_endpoints.insert(best_other); + used_terminals.insert(other_terminal); + } + } + } + + //Auto-connect: collect all aligned pairs first, then filter and process. + QList> aligned_pairs; + if (m_diagram->project()->autoConductor()) + aligned_pairs = element->AlignedFreeTerminals(); + + for (const QPair &pair : aligned_pairs) + { + //Skip if the other terminal was an endpoint of a broken conductor + if (broken_endpoints.contains(pair.second)) + continue; Conductor *conductor = new Conductor(pair.first, pair.second); new AddGraphicsObjectCommand(conductor, m_diagram, QPointF(), undo_object); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 655bcd0d4..1ae771162 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -370,6 +370,21 @@ void QETDiagramEditor::setUpActions() pv->project()->setAutoConductor(ac); }); + //AutoBreakConductor + m_auto_break_conductor = new QAction (QET::Icons::Conductor, tr("Coupure automatique de conducteur(s)","Tool tip of auto break conductor"), this); + m_auto_break_conductor->setStatusTip (tr("Couper automatiquement les conducteurs existants lors du placement d'un élément", "Status tip of auto break conductor")); + m_auto_break_conductor->setCheckable (true); + { + QSettings settings; + m_auto_break_conductor->setChecked(settings.value("diagrameditor/auto_break_conductor", false).toBool()); + } + connect(m_auto_break_conductor, &QAction::triggered, [this](bool abc) { + QSettings settings; + settings.setValue("diagrameditor/auto_break_conductor", abc); + if (ProjectView *pv = currentProjectView()) + pv->project()->setAutoBreakConductor(abc); + }); + //Switch background color m_grey_background = new QAction (QET::Icons::DiagramBg, tr("Couleur de fond blanc/gris","Tool tip of white/grey background button"), this); m_grey_background -> setStatusTip (tr("Affiche la couleur de fond du folio en blanc ou en gris", "Status tip of white/grey background button")); @@ -809,6 +824,7 @@ void QETDiagramEditor::setUpToolBar() diagram_tool_bar -> addAction (m_edit_diagram_properties); diagram_tool_bar -> addAction (m_conductor_reset); diagram_tool_bar -> addAction (m_auto_conductor); + diagram_tool_bar -> addAction (m_auto_break_conductor); m_add_item_tool_bar = new QToolBar(tr("Ajouter"), this); m_add_item_tool_bar->setObjectName("adding"); @@ -1896,9 +1912,14 @@ void QETDiagramEditor::slot_updateModeActions() { m_auto_conductor -> setEnabled (true); m_auto_conductor -> setChecked (pv -> project() -> autoConductor()); + m_auto_break_conductor -> setEnabled (true); + m_auto_break_conductor -> setChecked (pv -> project() -> autoBreakConductor()); } else + { m_auto_conductor -> setDisabled(true); + m_auto_break_conductor -> setDisabled(true); + } } /** diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index f5666f781..21df421f7 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -192,6 +192,8 @@ class QETDiagramEditor : public QETMainWindow *redo, ///< Redo the latest cancelled operation *m_paste, ///< Paste clipboard content on the current diagram *m_auto_conductor, ///< Enable/Disable the use of auto conductor + *m_auto_break_conductor, ///< Enable/Disable the use of auto break conductor + *conductor_default, ///< Show a dialog to edit default conductor properties *m_grey_background, ///< Switch the background color in white or grey *m_draw_grid, ///< Switch the background grid display or not *m_draw_guides = nullptr, ///< Switch the custom guides display or not diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 9b115458d..31dfb6365 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -69,6 +69,10 @@ m_project_properties_handler{this} init(); QSettings settings; + + //Read auto break conductor default from global settings + m_auto_break_conductor = settings.value(QStringLiteral("diagrameditor/auto_break_conductor"), false).toBool(); + int size = settings.beginReadArray(QStringLiteral("diagrameditor/defaultguides")); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); @@ -927,6 +931,28 @@ void QETProject::setAutoConductor(bool ac) m_auto_conductor = ac; } +/** + @brief QETProject::autoBreakConductor + @return true if use of auto break conductor is authorized. + See also Q_PROPERTY autoBreakConductor +*/ +bool QETProject::autoBreakConductor() const +{ + return m_auto_break_conductor; +} + +/** + @brief QETProject::setAutoBreakConductor + @param abc + Enable the use of auto break conductor if true + See also Q_PROPERTY autoBreakConductor +*/ +void QETProject::setAutoBreakConductor(bool abc) +{ + if (abc != m_auto_break_conductor) + m_auto_break_conductor = abc; +} + /** @brief QETProject::autoFolioNumberingNewFolios emit Signal to add new Diagram with autonum @@ -1735,6 +1761,7 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project) { m_current_conductor_autonum = conds_autonums.attribute(QStringLiteral("current_autonum")); m_freeze_new_conductors = conds_autonums.attribute(QStringLiteral("freeze_new_conductors")) == QLatin1String("true"); + m_auto_break_conductor = conds_autonums.attribute(QStringLiteral("auto_break_conductors")) == QLatin1String("true"); for (auto elmt : QET::findInDomElement(conds_autonums, QStringLiteral("conductor_autonum"))) { NumerotationContext nc; @@ -1861,6 +1888,7 @@ void QETProject::writeDefaultPropertiesXml(QDomElement &xml_element) QDomElement conductor_autonums = xml_document.createElement("conductors_autonums"); conductor_autonums.setAttribute("current_autonum", m_current_conductor_autonum); conductor_autonums.setAttribute("freeze_new_conductors", m_freeze_new_conductors ? "true" : "false"); + conductor_autonums.setAttribute("auto_break_conductors", m_auto_break_conductor ? "true" : "false"); foreach (QString key, conductorAutoNum().keys()) { QDomElement conductor_autonum = conductorAutoNum(key).toXml(xml_document, "conductor_autonum"); if (key != "" && conductorAutoNumFormula(key) != "") { diff --git a/sources/qetproject.h b/sources/qetproject.h index 61427ca72..b08e2b5b4 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -90,6 +90,7 @@ class QETProject : public QObject }; Q_PROPERTY(bool autoConductor READ autoConductor WRITE setAutoConductor) + Q_PROPERTY(bool autoBreakConductor READ autoBreakConductor WRITE setAutoBreakConductor) // constructors, destructor public: @@ -181,9 +182,11 @@ class QETProject : public QObject void setFreezeNewConductors(bool); bool autoConductor () const; + bool autoBreakConductor () const; bool autoElement () const; bool autoFolio () const; void setAutoConductor (bool ac); + void setAutoBreakConductor (bool abc); void setAutoElement (bool ae); void autoFolioNumberingNewFolios (); void autoFolioNumberingSelectedFolios(int, int, const QString&); @@ -318,6 +321,7 @@ class QETProject : public QObject QHash m_element_autonum; //Title and NumContext hash QString m_current_element_autonum; bool m_auto_conductor = true; + bool m_auto_break_conductor = false; XmlElementCollection *m_elements_collection = nullptr; bool m_freeze_new_elements = false; bool m_freeze_new_conductors = false; From 1198cf73a9c925a15075faced6b5dcb9be687343 Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Sat, 8 Aug 2026 07:23:17 +0200 Subject: [PATCH 034/350] Update translations files --- lang/qet_ar.ts | 460 +++++++++++++++++++++++++--------------------- lang/qet_ca.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_cs.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_da.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_de.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_el.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_en.qm | Bin 315401 -> 316402 bytes lang/qet_en.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_es.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_fr.qm | Bin 204494 -> 205059 bytes lang/qet_fr.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_hr.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_hu.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_it.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_ja.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_ko.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_mn.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_nb.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_nl_BE.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_nl_NL.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_pl.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_pt.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_pt_BR.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_ro.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_rs.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_ru.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_sk.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_sl.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_sr.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_sv.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_tr.ts | 448 +++++++++++++++++++++++--------------------- lang/qet_uk.ts | 446 +++++++++++++++++++++++--------------------- lang/qet_zh.ts | 448 +++++++++++++++++++++++--------------------- 33 files changed, 7430 insertions(+), 6438 deletions(-) diff --git a/lang/qet_ar.ts b/lang/qet_ar.ts index 22230f374..07c964f69 100644 --- a/lang/qet_ar.ts +++ b/lang/qet_ar.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link إدراج رابط - Title: العنوان: - URL: عنوان الموقع: @@ -1275,6 +1272,24 @@ Note: These options DO NOT allow or block Auto Numberings, only their Update Pol نقلة أوليّة + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1366,7 +1381,7 @@ Note: These options DO NOT allow or block Auto Numberings, only their Update Pol DiagramEventAddElement - + Ajouter %1 إضافة %1 @@ -2186,17 +2201,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations معلومات - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3452,7 +3472,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title تصدير @@ -5494,13 +5514,13 @@ Veuillez utiliser l'éditeur avancé pour cela. - + Nouveau folio configuration page title صفحة جديدة - + Nouveau projet configuration page title مشروع جديد @@ -6090,7 +6110,7 @@ Les variables suivantes sont incompatibles : PrintConfigPage - + Impression configuration page title طباعة @@ -6889,27 +6909,27 @@ Options disponibles : انقر على فعل للرجوع إلى الخلف في تحرير مخططتكم - + &Nouveau &جديد - + &Ouvrir &فتح - + &Fermer &غلق - + &Enregistrer &حفظ - + Enregistrer sous حفظ باسم @@ -6945,28 +6965,28 @@ Options disponibles : - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7017,238 +7037,250 @@ Options disponibles : &لصق - - Afficher la grille - عرض الشبكة + + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + - - Affiche ou masque la grille des folios - عرض أو إخفاء شبكة الصفخات - - - - Afficher les guides + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + Afficher la grille + عرض الشبكة + + + + Affiche ou masque la grille des folios + عرض أو إخفاء شبكة الصفخات + + + + Afficher les guides + + + + Affiche ou masque les guides - + Propriétés du folio خصائص الصفحة - + Ajouter un folio إضافة صفحة - - - + + + Supprimer le folio حذف الصفحة - + Exporter au format CSV - + Ajouter une nomenclature - + Gestionnaire de borniers (DEV) - + Lancer le plugin de création de borniers - + Exporter la liste des noms de conducteurs - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet - + Crée un nouveau projet status bar tip إحداث مشروع جديد - + Ouvre un projet existant status bar tip فتح مشروع قائم - + Ferme le projet courant status bar tip غلق المشروع الحالي - + Enregistre le projet courant et tous ses folios status bar tip حفظ المشروع الحالي بكلّ صفحاته - + Enregistre le projet courant avec un autre nom de fichier status bar tip حفظ المشروع الحالي باسم ملف آخر - + Ajouter une ligne Add row اضافة سطر - + Enlever une ligne Remove row إزالة صف - + Ajoute une colonne au folio status bar tip إضافة عمود للصفحة - + Enlève une colonne au folio status bar tip نزع عمود من الصفحة - + Agrandit le folio en hauteur status bar tip تكبير ارتفاع الصفحة - + Rétrécit le folio en hauteur status bar tip تقليص ارتفاع الصفحة - + Grouper les textes sélectionnés - + Enlève les éléments sélectionnés du folio status bar tip نزع العناصر المُحدّدة في الصفحة - + Tout sélectionner تحديد الكل - + Désélectionner tout إلغاء تحديد الكل - + Inverser la sélection اعكس التحديد - + Ajouter un plan de bornes - + Ajoute un champ de texte sur le folio actuel - + Ajoute une image sur le folio actuel - + Ajoute une ligne sur le folio actuel - + Ajoute un rectangle sur le folio actuel - + Ajoute une ellipse sur le folio actuel - + Ajoute une polyligne sur le folio actuel - + Ajoute un plan de bornier sur le folio actuel - + Chercher/remplacer - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Profondeur toolbar title العمق - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7261,7 +7293,7 @@ Options disponibles : - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7274,49 +7306,49 @@ Options disponibles : - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Groupe مجموعة - + Supprimer حذف - + Pivoter دوران محوري - + Orienter les textes توجيه النصوص - + Retrouver dans le panel إيجاد في اللوحة @@ -7326,157 +7358,157 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s إعادة تهيئة الموصلات - + Ajouter un champ de texte إضافة حقل نصي - + Ajouter une colonne إضافة عمود - + Ajouter une image إضافة صورة - + Enlever une colonne إزالة عمود - + Propriétés du projet خصائص المشروع - + Nettoyer le projet تنظيف المشروع - + Ajouter un sommaire إضافة مُلخص - + Zoom avant تكبير - + Zoom arrière تصغير - + Zoom sur le contenu تكبير المحتوى - + Zoom adapté تهيئة تكبير/تصغير - + Pas de zoom بدون تكبير/تصغير - + en utilisant des onglets باستعمال الزوايا الطرفية - + en utilisant des fenêtres باستعمال النوافذ - + Mode Selection أسلوب التحديد - + Mode Visualisation أسلوب العرض - + &Mosaïque &فسيفساء - + &Cascade &تتالي - + Projet suivant المشروع التالي - + Projet précédent المشروع السابق - + Sélectionne tous les éléments du folio status bar tip تحديد كلّ عناصر الصفحة - + Désélectionne tous les éléments du folio status bar tip إلغاء تحديد كلّ عناصر الصفحة - + Agrandit le folio status bar tip تكبير الصفحة - + Rétrécit le folio status bar tip تقليص الصفحة - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre مُوائمة التكبير لعرض كلّ مُحتوى الصفحة بغضّ النظر عن الاطار - + Adapte le zoom exactement sur le cadre du folio status bar tip موائمة التكبير بالظبط على إطار الصفحة - + Ajouter un rectangle اضافة مستطيل - + Ajouter une ellipse اضافة اهليج - + Ajouter une polyligne إضافة مُتعدد أضلع - + Retrouve l'élément sélectionné dans le panel status bar tip إيجاد العنصر المُحدّد في اللوحة @@ -7500,43 +7532,43 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s وضع العناصر المخزنة بالحافظة على الصفحة - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip تحرير خاصيات الصفحة (مقاسات, معلومات إطار التعريف, خاصيات المُوصلات ...) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip يسمح بعرض الصفحة دون القدرة على تغييرها - - + + Projet %1 enregistré dans le repertoire: %2. مشروع %1 محفوظ في الدليل: %2. - - + + Impossible d'ouvrir le fichier message box title إستحالة فتح الملف - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. يبدو أنّ الملف %1 الذي تُحاول فتحه غير موجود . - + Ouverture du projet en lecture seule message box title فتح المشروع للقراءة فقط - + Éditer l'item sélectionné تحرير العنصر المُحدّد @@ -7571,19 +7603,19 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s نسخ التحديد ووضعه في الحافظة - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip الغاء تحديد العناصر المحددة و تحديد العناصر الغير محددة - + Pivote les éléments et textes sélectionnés status bar tip تدوير العناصر والنصوص المُحدّدة - + Pivote les textes sélectionnés à un angle précis status bar tip تدوير النصوص المُحدّدة بزاوية مُعيّنة @@ -7607,258 +7639,258 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s استخدم الاحداث الآلي للموصلات كلّما كان ذلك مُمكنا - + Couleur de fond blanc/gris Tool tip of white/grey background button لون الخلفية أبيض / رمادي - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button عرض لون الخلفية للصفحة أبيض أو رمادي - + Restaure le zoom par défaut status bar tip استرجاع تكبير / تصغير الإفتراضي - + Ajouter une ligne Draw line اضافة سطر - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip يُقدّم مختلف المشاريع المفتوحة في النوافذ الثانوية - + Présente les différents projets ouverts des onglets status bar tip تقديم مختلف المشاريع المفتوحة في علامات - + Permet de sélectionner les éléments status bar tip يسمح بتحديد العناصر - + Dispose les fenêtres en mosaïque status bar tip يُنظم النوافذ على هيئة فسيفساء - + Dispose les fenêtres en cascade status bar tip يُنظم النوافذ على التتالي - + Active le projet suivant status bar tip تفعيل المشروع التالي - + Active le projet précédent status bar tip تفعيل المشروع السابق - + &Fichier &ملف - + &Édition &تحرير - + &Projet &مشروع - + Afficha&ge عر&ض - + Fe&nêtres نوا&فذ - + &Récemment ouverts &مفتوح حديثا - + Affiche ou non la barre d'outils principale عرض أو لا لشريط الأدوات الرئيسي - + Affiche ou non la barre d'outils Affichage عرض أو لا لشريط أدوات العرض - + Affiche ou non la barre d'outils Schéma عرض أو لا شريط أدوات المخطط - + Affiche ou non le panel d'appareils عرض أو لا للوحة الأجهزة - + Affiche ou non la liste des modifications عرض أو لا لقائمة التحويرات - + Afficher les projets عرض المشاريع - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) مشاريع QElectroTech (*.qet);ملفات XML (*.xml);;كلّ الملفات (*) - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content - + Active le projet « %1 » تنشيط المشروع « %1 » - + Outils أدوات - + Affichage عرض - + Schéma مخطط - + Ajouter إضافة - + Ouvrir un fichier فتح ملف - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. يبدو أنّ الملف التي تُحاول فتحه لا يُمكن الوصول إليه للقراءة وبالتالي يستحيل فتحه. الرجاء التثبت من تراخيص الملف. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. يبدو أنّ المشروع التي تحاول فتحه, غير قابل للوصول إليه للكتابة. وبالتالي لايُمكن فتحه إلا للقراءة فقط. - - + + Échec de l'ouverture du projet message box title فشل فتح المشروع - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content يبدو أنّ الملف %1 ليس بملف مشروع QElectrotech. ;وبالتالي لا يمكن فتحه. - + Éditer l'élement edit element تحرير العنصر - + Éditer le champ de texte edit text field تحرير الحقل النصّي - + Éditer l'image edit image تحرير الصورة - + Éditer le conducteur edit conductor تحرير الموصل - + Éditer l'objet sélectionné edit selected item تحرير الكائن المُحدّد - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title خطأ @@ -8736,42 +8768,42 @@ les conditions requises ne sont pas valides QETProject - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path مشروع « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name مشروع %1 - + Projet sans titre displayed title for a project-less, file-less project مشروع بدون عنوان - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [قراءة فقط] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [مُتغيّر] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8779,56 +8811,56 @@ Voulez-vous continuer ? - + Une erreur s'est produite durant l'intégration du modèle. error message حدث خطأ أثناء الإدماج. - + Avertissement message box title تنبيه - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? - + Avertissement message box title - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>جاري فتح المشروع ...</b><br/>إنشاء الصفحات</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>جاري فتح المشروع ...</b><br/>وضع المرجعيات المتقاطعة</p> @@ -10489,22 +10521,22 @@ Voulez-vous la remplacer ? - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin حدث خطأ أثناء تشغيل المكون الإضافي qet_tb_generator diff --git a/lang/qet_ca.ts b/lang/qet_ca.ts index b160459b6..2a5ad9c1a 100644 --- a/lang/qet_ca.ts +++ b/lang/qet_ca.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Insereix enllaç - Title: Títol: - URL: URL: @@ -1273,6 +1270,24 @@ Nota: Aquestes opcions NO permeten ni bloquegen les numeracions automàtiques, n Moure una primitiva + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1364,7 +1379,7 @@ Nota: Aquestes opcions NO permeten ni bloquegen les numeracions automàtiques, n DiagramEventAddElement - + Ajouter %1 Afegeix %1 @@ -2172,17 +2187,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations Dades - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3440,7 +3460,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title Exporta @@ -5499,13 +5519,13 @@ Si us plau, feu servir l'editor avançat per a això. - + Nouveau folio configuration page title Nou full - + Nouveau projet configuration page title Nou projecte @@ -6102,7 +6122,7 @@ Les variables següents són incompatibles: PrintConfigPage - + Impression configuration page title Impressió @@ -6908,27 +6928,27 @@ Opcions disponibles: Trieu una acció per retrocedir en l'edició de l'esquema - + &Nouveau &Nou - + &Ouvrir &Obre - + &Fermer &Tanca - + &Enregistrer &Desa - + Enregistrer sous Desa com a @@ -6953,28 +6973,28 @@ Opcions disponibles: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7026,264 +7046,276 @@ Opcions disponibles: + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Couleur de fond blanc/gris Tool tip of white/grey background button Color de fons blanc / gris - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Mostra el color de fons del full en blanc o gris - + Afficher la grille Mostra la quadrícula - + Affiche ou masque la grille des folios Mostra o oculta la quadrícula - + Afficher les guides - + Affiche ou masque les guides - + Propriétés du folio Propietats del full - + Ajouter un folio Afegeix un full - - - + + + Supprimer le folio Suprimeix un full - + Exporter au format CSV Exporta en format CSV - + Ajouter une nomenclature Afegeix una nomenclatura - + Gestionnaire de borniers (DEV) Gestor de blocs de borns (DEV) - + Lancer le plugin de création de borniers Inicieu el connector de creació de blocs de borns - + Exporter la liste des noms de conducteurs Exporta la llista de noms de conductors - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet Exporta la base de dades interna del projecte - + Crée un nouveau projet status bar tip Crea un nou projecte - + Ouvre un projet existant status bar tip Obre un projecte existent - + Ferme le projet courant status bar tip Tanca el projecte actual - + Enregistre le projet courant et tous ses folios status bar tip Desa el projecte actual i tots els seus fulls - + Enregistre le projet courant avec un autre nom de fichier status bar tip Desa el projecte actual amb un altre nom de fitxer - + Ajouter une ligne Add row Afegeix una línia - + Enlever une ligne Remove row Suprimeix una línia - + Ajoute une colonne au folio status bar tip Afegeix una columna al full - + Enlève une colonne au folio status bar tip Suprimeix una columna al full - + Agrandit le folio en hauteur status bar tip Augmenta l'altura del full - + Rétrécit le folio en hauteur status bar tip Disminueix l'altura del full - + Grouper les textes sélectionnés Agrupa els textos seleccionats - + Enlève les éléments sélectionnés du folio status bar tip Suprimeix els elements seleccionats del full - + Tout sélectionner Selecciona-ho tot - + Désélectionner tout Desselecciona-ho tot - + Inverser la sélection Inverteix la selecció - + Ajouter un plan de bornes Afegeix un pla de borns - + Ajoute un champ de texte sur le folio actuel Afegeix un camp de text al full actual - + Ajoute une image sur le folio actuel Afegeix una imatge al full actual - + Ajoute une ligne sur le folio actuel Afegeix una fila al full actual - + Ajoute un rectangle sur le folio actuel Afegeix un rectangle al full actual - + Ajoute une ellipse sur le folio actuel Afegeix una el·lipse al full actual - + Ajoute une polyligne sur le folio actuel Afegeix un polígon al full actual - + Ajoute un plan de bornier sur le folio actuel Afegeix un pla de borns al full actual - + Chercher/remplacer Cerca i reemplaça - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Profondeur toolbar title Profunditat - + Supprimer Suprimeix - + Pivoter Gira - + Orienter les textes Orienta els textos - + Retrouver dans le panel Cerca al panell @@ -7293,157 +7325,157 @@ Opcions disponibles: Reinicia els conductors - + Ajouter un champ de texte Afegeix un camp de text - + Ajouter une colonne Afegeix una columna - + Ajouter une image Afegeix una imatge - + Enlever une colonne Suprimeix una columna - + Propriétés du projet Propietats del projecte - + Nettoyer le projet Neteja el projecte - + Ajouter un sommaire Afegeix un resum - + Zoom avant Apropa - + Zoom arrière Allunya - + Zoom sur le contenu Amplia el contingut - + Zoom adapté Zoom adaptat - + Pas de zoom Sense zoom - + en utilisant des onglets En pestanyes - + en utilisant des fenêtres En finestres - + Mode Selection Mode Selecció - + Mode Visualisation Mode Visualització - + &Mosaïque &Mosaic - + &Cascade &Cascada - + Projet suivant Projecte següent - + Projet précédent Projecte anterior - + Sélectionne tous les éléments du folio status bar tip Selecciona tots els elements del full - + Désélectionne tous les éléments du folio status bar tip Deselecciona tots els elements del full - + Agrandit le folio status bar tip Augmenta la mida del full - + Rétrécit le folio status bar tip Disminueix la mida del full - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Ajusta el zoom per mostrar tot el contingut del full independentment del marc - + Adapte le zoom exactement sur le cadre du folio status bar tip Ajusta el zoom exactament al marc del full - + Ajouter un rectangle Afegeix un rectangle - + Ajouter une ellipse Afegeix una el·lipse - + Ajouter une polyligne Afegeix un polígon - + Retrouve l'élément sélectionné dans le panel status bar tip Troba l'element seleccionat en el panell @@ -7467,48 +7499,48 @@ Opcions disponibles: Enganxa els elements del porta-retalls al full - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Edita les propietats del full (dimensions, informació del caixetí, propietats dels conductors, etc.) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Permet veure el full sense poder modificar-lo - - + + Projet %1 enregistré dans le repertoire: %2. Projecte %1 desat al directori: %2. - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) Projectes QElectroTech (* .qet);; Arxius XML (* .xml);; Tots els fitxers (*) - - + + Impossible d'ouvrir le fichier message box title Impossible obrir el fitxer - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Sembla que el fitxer %1 que estàs intentant obrir no existeix. - + Ouverture du projet en lecture seule message box title Obertura del projecte en mode de només lectura - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7517,7 +7549,7 @@ Opcions disponibles: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7526,55 +7558,55 @@ Opcions disponibles: - + Polices du projet message box title - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content S'ha produït un error en obrir el fitxer %1. - + Active le projet « %1 » Activa el projecte « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Error @@ -7610,7 +7642,7 @@ Opcions disponibles: Copia els elements seleccionats al porta-retalls - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Desselecciona els elements seleccionats i selecciona els elements no seleccionats @@ -7622,18 +7654,18 @@ Opcions disponibles: Recalcula les rutes dels conductors sense tenir en compte els canvis - + Pivote les éléments et textes sélectionnés status bar tip Gira els elements i textos seleccionats - + Éditer l'item sélectionné Edita l'element seleccionat - + Pivote les textes sélectionnés à un angle précis status bar tip Gira els textos seleccionats a un angle específic @@ -7662,214 +7694,214 @@ Opcions disponibles: Utilitza la creació automàtica de conductor (s) sempre que sigui possible - + Restaure le zoom par défaut status bar tip Restaura el nivell de zoom per defecte - + Ajouter une ligne Draw line Afegeix una línia - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Mostra els projectes oberts en subfinestres - + Présente les différents projets ouverts des onglets status bar tip Mostra els projectes oberts en pestanyes - + Permet de sélectionner les éléments status bar tip Permet seleccionar els elements - + Dispose les fenêtres en mosaïque status bar tip Disposa les finestres en mosaic - + Dispose les fenêtres en cascade status bar tip Disposa les finestres en cascada - + Active le projet suivant status bar tip Activa el projecte següent - + Active le projet précédent status bar tip Activa el projecte anterior - + &Fichier &Fitxer - + &Édition &Edita - + &Projet &Projecte - + Afficha&ge &Visualitza - + Fe&nêtres Fi&nestres - + &Récemment ouverts &Obre'n un de recent - + Affiche ou non la barre d'outils principale Mostra o amaga la barra d'eines principal - + Affiche ou non la barre d'outils Affichage Mostra o amaga la barra d'eines de visualització - + Affiche ou non la barre d'outils Schéma Mostra o amaga la barra d'eines d'esquema - + Affiche ou non le panel d'appareils Mostra o amaga el panell d'elements - + Affiche ou non la liste des modifications Mostra o amaga la llista de canvis - + Afficher les projets Mostra els projectes - + Outils Eines - + Affichage Visualitza - + Schéma Esquema - + Ajouter Afegeix - + Ouvrir un fichier Obre un fitxer - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Sembla que el fitxer que intentes obrir no és llegible. Per tant, no es pot obrir. Si us plau, comprova els permisos del fitxer. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Sembla que el projecte que intentes obrir no és accessible en mode d'escriptura. Per tant serà obert en mode de només lectura. - - + + Échec de l'ouverture du projet message box title Impossible obrir el projecte - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content Sembla que el fitxer %1 no és un fitxer de projecte QElectroTech. Per tant no es pot obrir. - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Feu doble clic per completar la forma, feu clic amb el botó dret per desfer l'últim punt - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Groupe Grup - + Éditer l'élement edit element Edita l'element - + Éditer le champ de texte edit text field Edita el camp de text - + Éditer l'image edit image Edita la imatge - + Éditer le conducteur edit conductor Edita el conductor - + Éditer l'objet sélectionné edit selected item Edita l'objecte seleccionat @@ -8736,42 +8768,42 @@ Les condicions requerides no són vàlides QETProject - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Projecte « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Projecte %1 - + Projet sans titre displayed title for a project-less, file-less project Projecte sense títol - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [només lectura] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [modificat] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8779,19 +8811,19 @@ Voulez-vous continuer ? - + Une erreur s'est produite durant l'intégration du modèle. error message S'ha produït un error mentre s'integrava el model. - + Avertissement message box title Avís - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 @@ -8800,7 +8832,7 @@ Vous utilisez actuellement QElectroTech en version %2 Actualment esteu utilitzant la versió %2 de QElectroTech - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? @@ -8809,32 +8841,32 @@ Aleshores és possible que l'obertura de tot o part d'aquest document Què voleu fer? - + Avertissement message box title Avís - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. El projecte que esteu intentant obrir és parcialment compatible amb la vostra versió %1 de QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? Perquè sigui totalment compatible, obriu aquest mateix projecte amb la versió 0.8 o 0.80 de QElectroTech, deseu el projecte i torneu-lo a obrir amb aquesta versió. Què voleu fer? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Obrint el projecte actual...</b><br/>Creant els folis</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Obrint el projecte actual...</b><br/>Configurant referències creuades</p> @@ -10643,22 +10675,22 @@ Voleu substituir-la? Importa la configuració de text : %1 - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> Per instal·lar el connector qet_tb_generator<br>Visiteu:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requereix python 3.5 o superior.<br><B><U> Primera instal·lació a Windows</B></U><br>1. Instal·leu, si cal, python 3.5 o superior<br> Visiteu:<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Actualització a Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>L'usuari podria iniciar aquest script en un terminal en aquest directori<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> Per instal·lar el connector qet_tb_generator<br>Visiteu:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> Primera instal·lació a macOSX</B></U><br>1. Instal·leu, si cal, només el paquet python 3.11, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Executeu l'script Profile.command<br>perquè el programa utilitza el PATH codificat per localitzar el connector qet-tb-generator <br> Visiteu:<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>com fer-ho</a><br>2. instal·lació de qet_tb_generator amb pip3<br><B><U> Actualització a macOSX</B></U><br> instal·lació de pip3 --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> Per instal·lar el connector qet_tb_generator<br>Visiteu:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requereix python 3.5 o superior.<br><br><B><U> Primera instal·lació a Linux</B></U><br>1. comproveu que teniu pip3 instal·lat: pip3 --version<br>Si no, instal·leu-lo amb: sudo apt-get install python3-pip<br>2. Instal·leu el programa: sudo pip3 install qet_tb_generator<br>3. Executeu el programa: qet_tb_generator<br><br><B><U> Actualització a Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Error en iniciar el connector qet_tb_generator diff --git a/lang/qet_cs.ts b/lang/qet_cs.ts index ee4552ab7..e09e47ed7 100644 --- a/lang/qet_cs.ts +++ b/lang/qet_cs.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Vložit odkaz - Title: Název: - URL: Adresa (URL): @@ -1273,6 +1270,24 @@ Poznámka: tyto volby automatické číslování ani NEPOVOLÍ ani nezakáží, Přesunout primitivu + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1364,7 +1379,7 @@ Poznámka: tyto volby automatické číslování ani NEPOVOLÍ ani nezakáží, DiagramEventAddElement - + Ajouter %1 vložit %1 @@ -2171,17 +2186,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations Informace - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3438,7 +3458,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title Vyvedení @@ -5491,13 +5511,13 @@ Na toto , prosím, použijte pokročilý editor. - + Nouveau folio configuration page title Nový list - + Nouveau projet configuration page title Nový projekt @@ -6094,7 +6114,7 @@ Následující proměnné jsou neslučitelné: PrintConfigPage - + Impression configuration page title Tisk @@ -6871,22 +6891,22 @@ Dostupné volby: QETDiagramEditor - + Afficha&ge Po&hled - + Affiche ou non le panel d'appareils Zobrazit/Nezobrazit panel s prvky - + Ajouter une colonne Přidat sloupec - + &Cascade &Překrývat @@ -6906,27 +6926,27 @@ Dostupné volby: &Vyjmout - + Désélectionner tout Zrušit výběr - + &Édition Úp&ravy - + Enlever une colonne Odstranit sloupec - + &Enregistrer &Uložit - + Enregistrer sous Uložit jako @@ -6936,17 +6956,17 @@ Dostupné volby: &Vyvést - + Fe&nêtres &Okna - + &Fermer &Zavřít - + &Fichier &Soubor @@ -6956,12 +6976,12 @@ Dostupné volby: Tisk - + Inverser la sélection Obrátit výběr - + Mode Selection Výběrový režim @@ -6972,51 +6992,51 @@ Dostupné volby: Tento panel uvádí různé změny použité na nynější list. Klepnutí na změnu dovolí vrácení listu do stavu hned po jejím použití. - + Couleur de fond blanc/gris Tool tip of white/grey background button Barva pozadí bílá/šedá - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Zobrazí barvu pozadí listu bílé nebo šedé - + Afficher la grille Zobrazit mřížku - + Affiche ou masque la grille des folios Zobrazit/Skrýt mřížku listů - + Propriétés du folio Vlastnosti listu - + Ajouter un folio Přidat list - - - + + + Supprimer le folio Smazat list - + Mode Visualisation Pohledový režim - + &Mosaïque Klást &vedle sebe @@ -7030,28 +7050,28 @@ Dostupné volby: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7067,180 +7087,180 @@ Dostupné volby: Vyvést jeden nebo několik listů nynějšího projektu - + Afficher les guides - + Affiche ou masque les guides - + Exporter au format CSV Vyvést do formátu CSV - + Gestionnaire de borniers (DEV) Správce svorkovnic (DEV) - + Lancer le plugin de création de borniers Spustit přídavný modul na vytváření svorkovnic - + Exporter la liste des noms de conducteurs Vyvést seznam názvů vodičů - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet Vyvést vnitřní projektovou databázi - + &Nouveau &Nový - + Crée un nouveau projet status bar tip Vytvořit nový projekt - + Ouvre un projet existant status bar tip Otevřít stávající projekt - + Ferme le projet courant status bar tip Zavřít nynější projekt - + Enregistre le projet courant et tous ses folios status bar tip Uloží nynější projekt a všechny jeho listy - + Enregistre le projet courant avec un autre nom de fichier status bar tip Uloží nynější projekt pod jiným souborovým názvem - + Ajouter une ligne Add row Přidat řádek - + Enlever une ligne Remove row Odstranit řádek - + Ajoute une colonne au folio status bar tip Přidat do listu sloupec - + Enlève une colonne au folio status bar tip Odstranit z listu sloupec - + Agrandit le folio en hauteur status bar tip Zvětšit výšku listu - + Rétrécit le folio en hauteur status bar tip Zmenšit výšku listu - + Enlève les éléments sélectionnés du folio status bar tip Odstraní vybrané prvky z listu - + Sélectionne tous les éléments du folio status bar tip Vybere všechny prvky na listu - + Désélectionne tous les éléments du folio status bar tip Zruší výběr všech prvků na listu - + Agrandit le folio status bar tip Zvětší list - + Rétrécit le folio status bar tip Zmenší list - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Přizpůsobí zvětšení tak, že je zobrazován obsah bez ohledu na rámec - + Adapte le zoom exactement sur le cadre du folio status bar tip Upraví zvětšení tak, že je zobrazena přesně určitá část listu - + Ajouter une ligne Draw line Přidat čáru - + Ajouter un rectangle Přidat obdélník - + Ajouter une ellipse Přidat elipsu - + Ajouter une polyligne Přidat mnohoúhelník @@ -7257,13 +7277,13 @@ Dostupné volby: Vytiskne jeden nebo více listů nynějšího projektu - + Profondeur toolbar title Hloubka - + Groupe Skupina @@ -7274,39 +7294,39 @@ Dostupné volby: Vloží prvky ze schránky do listu - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Upraví vlastnosti listu (rozměry, údaje v záhlaví výkresu, vlastnosti vodičů...) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Dovolí zobrazení listu, aniž by jej bylo možné upravovat - + Outils Nástroje - + &Ouvrir &Otevřít - + Ouvrir un fichier Otevřít soubor - + Pas de zoom Obnovit výchozí zvětšení - + Pivoter Otočit @@ -7316,27 +7336,27 @@ Dostupné volby: &Ukončit - + Supprimer Smazat - + Tout sélectionner Vybrat vše - + Zoom adapté Přizpůsobit přiblížení - + Zoom arrière Oddálit - + Zoom avant Přiblížit @@ -7356,32 +7376,32 @@ Dostupné volby: Obnovit výchozí vodiče - + Affiche ou non la barre d'outils principale Zobrazit/Skrýt hlavní pruh s nástroji - + Affiche ou non la barre d'outils Affichage Zobrazit/Skrýt pruh s nástroji pro zobrazení - + Affiche ou non la barre d'outils Schéma Zobrazit/Skrýt pruh s nástroji pro výkres - + Affichage Zobrazení - + Schéma Výkres - + Ajouter un champ de texte Přidat textové pole @@ -7391,97 +7411,97 @@ Dostupné volby: Žádná úprava - + Affiche ou non la liste des modifications Zobrazit/Skrýt seznam kroků zpět - + Éditer l'item sélectionné Upravit vybranou položku - + Grouper les textes sélectionnés Seskupit vybrané texty - + Pivote les éléments et textes sélectionnés status bar tip Otáčí vybrané prvky a texty - + Pivote les textes sélectionnés à un angle précis status bar tip Otáčí vybrané texty v přesném úhlu - + Chercher/remplacer Hledat/Nahradit - + &Projet &Projekt - + &Récemment ouverts &Nedávno otevřené - - + + Projet %1 enregistré dans le repertoire: %2. Projekt 1% uložený v adresáři: %2. - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Nezdá se, že by byl soubor, který se pokoušíte otevřít, čitelný. A nelze jej otevřít. Zkontrolujte, prosím, oprávnění k souboru. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Zdá se, že projekt, který se pokoušíte otevřít, není zapisovatelný. Bude tedy otevřen pouze pro čtení. - + en utilisant des onglets Používat karty - + en utilisant des fenêtres Používat okna - + Afficher les projets Zobrazení projektů - + Propriétés du projet Vlastnosti projektu - + Nettoyer le projet Vyčistit projekt - - + + Échec de l'ouverture du projet message box title Projekt nelze otevřít - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content Zdá se, že soubor %1 není souborem projektu QElectroTech. Nemůže být tedy otevřen. @@ -7511,27 +7531,27 @@ Dostupné volby: Klepněte na některý z kroků pro návrat zpět ve změnách udělaných ve vašem výkresu - + Orienter les textes Natočit texty - + Retrouver dans le panel Najít v panelu - + Ajouter une image Přidat obrázek - + Ajouter un sommaire Přidat souhrn - + Zoom sur le contenu Přiblížit obsah @@ -7566,13 +7586,13 @@ Dostupné volby: Zkopíruje vybrané prvky do schránky - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Zruší výběr vybraných prvků a vybere nevybrané prvky - + Retrouve l'élément sélectionné dans le panel status bar tip Najde prvek vybraný v panelu @@ -7607,115 +7627,127 @@ Dostupné volby: Použít automatické vytvoření vodiče(ů), když je to možné - + Restaure le zoom par défaut status bar tip Obnoví výchozí úroveň přiblížení - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Ukáže různé otevřené projekty v podoknech - + + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Ajouter une nomenclature Přidat seznam součástí - + Présente les différents projets ouverts des onglets status bar tip Ukáže různé otevřené projekty v kartách - + Permet de sélectionner les éléments status bar tip Dovolí výběr prvků - + Ajouter un plan de bornes Přidat plán svorek - + Ajoute un champ de texte sur le folio actuel Přidat textové pole do nynějšího listu - + Ajoute une image sur le folio actuel Přidat obrázek do nynějšího listu - + Ajoute une ligne sur le folio actuel Přidat čáru do nynějšího listu - + Ajoute un rectangle sur le folio actuel Přidat obdélník do nynějšího listu - + Ajoute une ellipse sur le folio actuel Přidat elipsu do nynějšího listu - + Ajoute une polyligne sur le folio actuel Přidat lomenou čáru do nynějšího listu - + Ajoute un plan de bornier sur le folio actuel Přidat plán svorek do nynějšího listu - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Ajouter Přidání - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) Projekty QElectroTech (*.qet);;Soubory XML (*.xml);;Všechny soubory (*) - - + + Impossible d'ouvrir le fichier message box title Soubor nelze otevřít - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Zdá se, že soubor %1, který se pokoušíte otevřít, už neexistuje. - + Ouverture du projet en lecture seule message box title Otevření souboru pouze pro čtení - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7725,7 +7757,7 @@ Dostupné volby: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7735,135 +7767,135 @@ Dostupné volby: - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Dvakrát klepnout pro dokončení tvaru, klepnutí pravým tlačítkem myši pro zrušení posledního bodu - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Éditer l'élement edit element Upravit prvek - + Éditer le champ de texte edit text field Upravit textové pole - + Éditer l'image edit image Upravit obrázek - + Éditer le conducteur edit conductor Upravit vodič - + Éditer l'objet sélectionné edit selected item Upravit vybraný předmět - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content Během otevírání souboru %1 se vyskytla chyba. - + Active le projet « %1 » Spustí projekt « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Chyba - + Dispose les fenêtres en mosaïque status bar tip Uspořádá okna tím způsobem, že je položí vedle sebe - + Dispose les fenêtres en cascade status bar tip Uspořádá okna tím způsobem, že je položí v kaskádě pod sebe - + Projet suivant Další projekt - + Projet précédent Předchozí projekt - + Active le projet suivant status bar tip Spustí další projekt - + Active le projet précédent status bar tip Spustí předchozí projekt @@ -8736,48 +8768,48 @@ podmínky nejsou platné QETProject - + Avertissement message box title Varování - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Projekt « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Projekt %1 - + Projet sans titre displayed title for a project-less, file-less project Nepojmenovaný projekt - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [pouze pro čtení] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [změněno] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8785,13 +8817,13 @@ Voulez-vous continuer ? - + Une erreur s'est produite durant l'intégration du modèle. error message Během začleňování vzoru se vyskytla chyba. - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 @@ -8800,7 +8832,7 @@ Ta je novější než vaše verze! V současné době používáte QElectroTech ve verzi %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? @@ -8809,32 +8841,32 @@ Pak je možné, že se otevření celého dokumentu nebo jeho části nezdaří. Co si přejete udělat ? - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. Projekt, který se snažíte otevřít, je částečně kompatibilní s vaší verzí %1 programu QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? Aby byl projekt plně kompatibilní, otevřete jej s verzí 0.8 nebo 0.80 programu QElectroTech, uložte jej a otevřete znovu s touto verzí. Co si přejete udělat? - + Avertissement message box title Varování - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Otevírá se projekt ...</b><br/>Vytváří se listy</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Otevírá se projekt ...</b><br/>Nastavují se křížové odkazy</p> @@ -10506,22 +10538,22 @@ Chcete je nahradit? Vytvoření vodičů - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> Pro nainstalování přídavného modulu qet_tb_generator<br>navštivte :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>vyžaduje python 3.5 nebo novější.<br><B><U> Nejprve nainstalujte v OS Windows</B></U><br>1. V případě potřeby nainstalujte python 3.5 nebo novější<br> Navštivte:<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Aktualizace na OS Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>uživatel tento skript může spustit v terminálu v tomto adresáři<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> Pro nainstalování přídavného modulu qet_tb_generator<br>navštivte:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> Nejprve nainstalujte v macOSX</B></U><br>1. V případě potřeby nainstalujte python 3.11 nebo novější<br> Navštivte:<br><a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2. Spusťte skript Profile.command<br><B><U> Aktualizujte na macOSX</B></U><br>pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> Pro nainstalování přídavného modulu qet_tb_generator<br>navštivte :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>vyžaduje python 3.5 nebo novější.<br><B><U> Nejprve instalace v OS Linux</B></U><br>1. Ověřte, že máte nainstalován pip3: pip3 --version<br>Pokud ne, nainstalujte pomocí: sudo apt-get install python3-pip<br>2. Nainstalujte program: sudo pip3 install qet_tb_generator<br>3. Spusťte program: qet_tb_generator<br><br><B><U> Aktualizace v OS Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Chyba při spouštění přídavného modulu qet_tb_generator diff --git a/lang/qet_da.ts b/lang/qet_da.ts index 2aec1994c..ea72c46d9 100644 --- a/lang/qet_da.ts +++ b/lang/qet_da.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Indsæt henvisning - Title: Titel: - URL: URL: @@ -1273,6 +1270,24 @@ Bemærk: Disse muligheder VIL IKKE tillade eller blokere autonummereringer, kun Flyt til oprindelig + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1364,7 +1379,7 @@ Bemærk: Disse muligheder VIL IKKE tillade eller blokere autonummereringer, kun DiagramEventAddElement - + Ajouter %1 Tilføj %1 @@ -2171,17 +2186,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations Informationer - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3437,7 +3457,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title Eksport @@ -5491,13 +5511,13 @@ Brug avanceret redigering til dette. - + Nouveau folio configuration page title Nyt ark - + Nouveau projet configuration page title Nyt projekt @@ -6093,7 +6113,7 @@ Følgende variabler er ikke kompatible: PrintConfigPage - + Impression configuration page title Udskriv @@ -6870,22 +6890,22 @@ Kommandovalg: QETDiagramEditor - + Afficha&ge &Vis - + Affiche ou non le panel d'appareils Vis eller skjul symbol panel - + Ajouter une colonne Tilføj kolonne - + &Cascade &Overlappet @@ -6905,27 +6925,27 @@ Kommandovalg: &Klip - + Désélectionner tout Vælg ingen - + &Édition &Redigere - + Enlever une colonne Slet kolonne - + &Enregistrer &Gem - + Enregistrer sous Gem som @@ -6935,17 +6955,17 @@ Kommandovalg: &Eksport - + Fe&nêtres &Vinduer - + &Fermer &Luk - + &Fichier &Filer @@ -6955,12 +6975,12 @@ Kommandovalg: Udskriv - + Inverser la sélection Vælg modsat - + Mode Selection Vælg @@ -6971,51 +6991,51 @@ Kommandovalg: Vinduet viser de forskellige ændringer, der udføres på nuværende ark. Klik på en ænding for at vende tilbage til tidligere tilstand. - + Couleur de fond blanc/gris Tool tip of white/grey background button Bagrundsfarve hvid / grå - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Viser ark baggrundsfarve i hvid eller grå - + Afficher la grille Vis gitter - + Affiche ou masque la grille des folios Vis eller skjul ark gitter - + Propriétés du folio Ark egenskab - + Ajouter un folio Tilføj ark - - - + + + Supprimer le folio Slet ark - + Mode Visualisation Vise - + &Mosaïque &Side om side @@ -7029,28 +7049,28 @@ Kommandovalg: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7066,180 +7086,180 @@ Kommandovalg: Eksportere et eller flere ark fra nuværende projekt - + Afficher les guides - + Affiche ou masque les guides - + Exporter au format CSV Eksportere som CSV format - + Gestionnaire de borniers (DEV) Terminalrække håndtering (DEV) - + Lancer le plugin de création de borniers Starte udvidelsesmodul til opretning af terminalblokke - + Exporter la liste des noms de conducteurs Eksportere liste med navne på ledere - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet Eksportere intern projekt database - + &Nouveau &Ny - + Crée un nouveau projet status bar tip Opret nyt projekt - + Ouvre un projet existant status bar tip Åbn eksisterende projekt - + Ferme le projet courant status bar tip Luk nuværende projekt - + Enregistre le projet courant et tous ses folios status bar tip Gem nuværende projekt og alle ark - + Enregistre le projet courant avec un autre nom de fichier status bar tip Gem nuværende projekt under andet filnavn - + Ajouter une ligne Add row Tilføj linje - + Enlever une ligne Remove row Slet linje - + Ajoute une colonne au folio status bar tip Tilføj kolonne til ark - + Enlève une colonne au folio status bar tip Slet kolonne fra ark - + Agrandit le folio en hauteur status bar tip Udvid ark højde - + Rétrécit le folio en hauteur status bar tip Indskrænk ark højde - + Enlève les éléments sélectionnés du folio status bar tip Slet symbol fra ark - + Sélectionne tous les éléments du folio status bar tip Væg alle symboler på ark - + Désélectionne tous les éléments du folio status bar tip Vælg ingen symboler på ark - + Agrandit le folio status bar tip Udvid ark - + Rétrécit le folio status bar tip Indskrænk ark - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Tilpas visning til indhold uanset ark ramme - + Adapte le zoom exactement sur le cadre du folio status bar tip Tilpas visning til ark - + Ajouter une ligne Draw line Tilføj linje - + Ajouter un rectangle Tilføj rektangel - + Ajouter une ellipse Tilføj cirkel - + Ajouter une polyligne Tilføj flerkant @@ -7256,13 +7276,13 @@ Kommandovalg: Udskriv et eller flere ark fra nuværende projekt - + Profondeur toolbar title Placeringsniveau - + Groupe Gruppe @@ -7273,39 +7293,39 @@ Kommandovalg: Indsæt symboler fra udklipsholder på ark - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Rediger ark egenskab (størrelse, titelblok information, leder egenskab etc.) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Tillader skrivebeskyttet ark visning - + Outils Værktøjer - + &Ouvrir &Åbn - + Ouvrir un fichier Åbn fil - + Pas de zoom Nulstil - + Pivoter Roter @@ -7315,27 +7335,27 @@ Kommandovalg: &Afslut - + Supprimer Slet - + Tout sélectionner Vælg alle - + Zoom adapté Tilpas ark - + Zoom arrière Formindsk - + Zoom avant Forstør @@ -7355,32 +7375,32 @@ Kommandovalg: Nulstil leder - + Affiche ou non la barre d'outils principale Vis eller skjul værktøjslinje - + Affiche ou non la barre d'outils Affichage Vis eller skjul værktøjslinjen Vis - + Affiche ou non la barre d'outils Schéma Vis eller skjul værktøjslinjen Diagram - + Affichage Vise - + Schéma Diagram - + Ajouter un champ de texte Tilføj tekstfelt @@ -7390,97 +7410,97 @@ Kommandovalg: Ingen ændring - + Affiche ou non la liste des modifications Vis eller skjul gendan liste - + Éditer l'item sélectionné Rediger emne - + Grouper les textes sélectionnés Gruppere valgte tekste - + Pivote les éléments et textes sélectionnés status bar tip Roter symbol og tekst - + Pivote les textes sélectionnés à un angle précis status bar tip Roter tekst til vinkel - + Chercher/remplacer Søg/erstat - + &Projet &Projekter - + &Récemment ouverts &Senest åbnet - - + + Projet %1 enregistré dans le repertoire: %2. Projekt %1 registreret i bibliotek: %2. - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Skrivebeskyttet fil forsøgt åbnet. Kontroller fil rettigheder. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Projekt åbnes skrivebeskyttet. - + en utilisant des onglets faneblade - + en utilisant des fenêtres vinduer - + Afficher les projets Vis projekt - + Propriétés du projet Projekt egenskab - + Nettoyer le projet Ryd op i projekt - - + + Échec de l'ouverture du projet message box title Projekt kan ikke åbnes - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content %1 er ikke en QElectroTech projekt fil. @@ -7510,27 +7530,27 @@ Kommandovalg: Klik på en ændring for at komme tilbage i diagram ændringer - + Orienter les textes Vælg tekst retning - + Retrouver dans le panel Find i panel - + Ajouter une image Tilføj billede - + Ajouter un sommaire Tilføj oversigt - + Zoom sur le contenu Tilpas indhold @@ -7565,13 +7585,13 @@ Kommandovalg: Kopier symboler fra udklipsholder - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Vælger modsat - + Retrouve l'élément sélectionné dans le panel status bar tip Find symbol i panel @@ -7606,115 +7626,127 @@ Kommandovalg: Brug automatisk opret af leder hvor det er muligt - + Restaure le zoom par défaut status bar tip Gendan standard visning - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Vis åbne projekter i vinduer - + + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Ajouter une nomenclature Tilføje en BOM - + Présente les différents projets ouverts des onglets status bar tip Vis åbne projekter i faneblade - + Permet de sélectionner les éléments status bar tip Tillader symbol valg - + Ajouter un plan de bornes - + Ajoute un champ de texte sur le folio actuel Tilføje tekstfelt til det aktuelle ark - + Ajoute une image sur le folio actuel Tilføje billede til det aktuelle ark - + Ajoute une ligne sur le folio actuel Tilføje linje til det aktuelle ark - + Ajoute un rectangle sur le folio actuel Tilføje rektangel til det aktuelle ark - + Ajoute une ellipse sur le folio actuel Tilføje elipse til det aktuelle ark - + Ajoute une polyligne sur le folio actuel Tilføje flerkant til det aktuelle ark - + Ajoute un plan de bornier sur le folio actuel - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Ajouter Tilføj - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) QElectroTech projekter (*.qet);; XML-filer (*.xml);; Alle filer (*) - - + + Impossible d'ouvrir le fichier message box title Kan ikke åbne filen - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Fil %1 findes ikke. - + Ouverture du projet en lecture seule message box title Projekt åbnes skrivebeskyttet - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7723,7 +7755,7 @@ Kommandovalg: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7732,135 +7764,135 @@ Kommandovalg: - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Dobbeltklik for at afslutte formular, højreklik for at fortryde det sidste punkt - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Éditer l'élement edit element Rediger symbol - + Éditer le champ de texte edit text field Rediger tekstfelt - + Éditer l'image edit image Rediger billede - + Éditer le conducteur edit conductor Rediger leder - + Éditer l'objet sélectionné edit selected item Rediger objekt - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content Der opstod en fejl under åbning af fil %1. - + Active le projet « %1 » Aktiver projekt « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Fejl - + Dispose les fenêtres en mosaïque status bar tip Arranger vinduer side om side - + Dispose les fenêtres en cascade status bar tip Arranger vinduer overlappet - + Projet suivant Næste projekt - + Projet précédent Foregående projekt - + Active le projet suivant status bar tip Aktiver næste projekt - + Active le projet précédent status bar tip Aktiver foregående projekt @@ -8727,48 +8759,48 @@ betingelser ikke gyldig QETProject - + Avertissement message box title Advarsel - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Projekt « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Projekt %1 - + Projet sans titre displayed title for a project-less, file-less project Ikke navngivet projekt - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [skrivebeskyttet] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [ændret] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8776,50 +8808,50 @@ Voulez-vous continuer ? - + Une erreur s'est produite durant l'intégration du modèle. error message Der opstod fejl under integration af skabelon. - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? - + Avertissement message box title Advarsel - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Åbning af projekt...</b><br/>Oprettelse af ark:</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Åbning af igangværende projekt...</b><br/>Opsætning af referencekors</p> @@ -10481,22 +10513,22 @@ Voulez-vous la remplacer ? Oprette ledere - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> For at installere udvidelsesmodul qet_tb_generator<br>Besøg: <a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Kræver python 3.5 eller over.<br><B><U>Første installering på Windows</B></U><br>1. Installere, hvis påkrævet, python 3.5 eller over<br>Besøg:<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip installere qet_tb_generator<br><B><U>Opdatere på Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>brugeren kan i en terminal udføre dette skript i følgende mappe<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> For at installere udvidelsesmodulet qet_tb_generator<br>Besøg:<br> <a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a> <br> <br>Kræver python 3.5 eller nyere.<br> <br> <B> <U>Første installation på Linux</B> </U> <br>1. kontrllere, at pip3 er installeret: pip3 --version<br>Hvis ikke, installere med: sudo apt-get install python3-pip<br>2. installere programmet: sudo pip3 install qet_tb_generator<br>3. kør programmet: qet_tb_generator<br> <br> <B> <U>Opdatering på Linux</B> </U> <br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Fejl ved opstart af qet_tb_generator udvidelsesmodul diff --git a/lang/qet_de.ts b/lang/qet_de.ts index 0b77c7566..488508aae 100644 --- a/lang/qet_de.ts +++ b/lang/qet_de.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Link einfügen - Title: Titel: - URL: URL: @@ -1276,6 +1273,24 @@ Bemerkung: diese Optionen verhindern NICHT das automatische Nummerieren.Stammfunktion verschieben + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1367,7 +1382,7 @@ Bemerkung: diese Optionen verhindern NICHT das automatische Nummerieren. DiagramEventAddElement - + Ajouter %1 Einfügen von .%1 @@ -2177,17 +2192,22 @@ Der angezeigte Name des Elements lässt sich separat in den Eigenschaften des El Sperre der automatischen Nummerierung - + Informations Informationen - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel Potentialtrennung - + Exclure de la nomenclature Aus der Materialliste ausschließen @@ -3457,7 +3477,7 @@ Mit dem Import dieser Datei bestätigen Sie, dass: ExportConfigPage - + Export configuration page title Exportieren @@ -5516,13 +5536,13 @@ Veuillez utiliser l'éditeur avancé pour cela. Hilfslinien - + Nouveau folio configuration page title Neue Folie - + Nouveau projet configuration page title Neues Projekt @@ -6117,7 +6137,7 @@ Folgende Variablen sind inkompatibel: PrintConfigPage - + Impression configuration page title Druck @@ -6923,27 +6943,27 @@ Verfügbare Optionen: Klicken Sie auf eine Aktion, um die Bearbeitung rückgängig zu machen - + &Nouveau &Neu - + &Ouvrir &Öffnen - + &Fermer &Schließen - + &Enregistrer &Speichern - + Enregistrer sous Speichern unter @@ -6994,129 +7014,129 @@ Verfügbare Optionen: E&infügen - + Propriétés du folio Folieneigenschaften - + Ajouter un folio Neue Folie hinzufügen - - - + + + Supprimer le folio Folie löschen - + Ajouter une nomenclature Betriebsmittelverzeichnis einfügen - + Lancer le plugin de création de borniers Klemmenplan-Plugin starten - + Crée un nouveau projet status bar tip Erstellt ein neues Projekt - + Ouvre un projet existant status bar tip Öffnet ein existierendes Projekt - + Ferme le projet courant status bar tip Schliesst das aktuelle Projekt - + Enregistre le projet courant et tous ses folios status bar tip Speichert das aktuelle Projekt und alle seine Folien - + Enregistre le projet courant avec un autre nom de fichier status bar tip Speichert das aktuelle Projekt unter einem anderen Dateinamen - + Ajoute une colonne au folio status bar tip Fügt eine neue Spalte zur Folie hinzu - + Enlève une colonne au folio status bar tip Löscht eine Spalte der Folie - + Agrandit le folio en hauteur status bar tip Vergrössert die Höhe der Folie - + Rétrécit le folio en hauteur status bar tip Verkleinert die Höhe der Folie - + Grouper les textes sélectionnés Ausgewählte Texte gruppieren - + Enlève les éléments sélectionnés du folio status bar tip Entfernt die ausgewählten Bauteile von der Folie - + Tout sélectionner Alles auswählen - + Désélectionner tout Auswahl aufheben - + Inverser la sélection Auswahl umkehren - + Supprimer Löschen - + Pivoter Drehen - + Orienter les textes Texte drehen - + Retrouver dans le panel Bauteil in Sammlung suchen @@ -7126,157 +7146,157 @@ Verfügbare Optionen: Leiter zurücksetzen - + Ajouter un champ de texte Textfeld einfügen - + Éditer l'item sélectionné Auswahl bearbeiten - + Ajouter une colonne Spalte einfügen - + Ajouter une image Bild einfügen - + Enlever une colonne Spalte entfernen - + Propriétés du projet Projekteigenschaften - + Nettoyer le projet Projekt bereinigen - + Ajouter un sommaire Inhaltsverzeichnis einfügen - + Zoom avant Vergrößern - + Zoom arrière Verkleinern - + Zoom sur le contenu Auf Inhalt einpassen - + Zoom adapté Folie einpassen - + Pas de zoom Kein Zoom - + en utilisant des onglets mittels Reiter - + en utilisant des fenêtres mittels Fenster - + Mode Selection Auswahlmodus - + Mode Visualisation Ansichtmodus - + &Mosaïque &Kacheln - + &Cascade &Überlappende Fenster - + Projet suivant Nächstes Projekt - + Projet précédent Vorheriges Projekt - + Sélectionne tous les éléments du folio status bar tip Wählt alle Bauteile der Folie aus - + Désélectionne tous les éléments du folio status bar tip Wählt alle Bauteile der Folie ab - + Agrandit le folio status bar tip Vergrössert die Folie - + Rétrécit le folio status bar tip Verkleinert die Folie - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Passt die Ansicht auf den Inhalt der Folie an, unabhängig vom Folienrahmen - + Adapte le zoom exactement sur le cadre du folio status bar tip Passt die Ansicht genau auf den Folienrahmen an - + Ajouter un rectangle Rechteck einfügen - + Ajouter une ellipse Ellipse einfügen - + Ajouter une polyligne Polylinie einfügen @@ -7311,25 +7331,25 @@ Verfügbare Optionen: kopiert die Auswahl in die Zwischenablage - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip kehrt die Auswahl um - + Pivote les éléments et textes sélectionnés status bar tip dreht die Auswahl - + Pivote les textes sélectionnés à un angle précis status bar tip dreht die ausgewählten Texte in einem bestimmten Winkel - + Retrouve l'élément sélectionné dans le panel status bar tip Sucht das Bauteil in der Sammlung @@ -7364,59 +7384,59 @@ Verfügbare Optionen: Wenn möglich, automatische Leiterverbindung benutzen - + Afficher la grille Raster anzeigen - + Affiche ou masque la grille des folios Zeige den Hintergrundsraster der Folien an - + Ajouter une ligne Add row Zeile einfügen - + Enlever une ligne Remove row Zeile entfernen - + Restaure le zoom par défaut status bar tip Standardansicht wiederherstellen - + Ajouter une ligne Draw line Linie einfügen - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip zeige die geöffneten Projekte in Fenstern an - + Présente les différents projets ouverts des onglets status bar tip zeige die geöffneten Projekte in Reitern an - + Permet de sélectionner les éléments status bar tip wählt Bauteile aus - + Dispose les fenêtres en mosaïque status bar tip ordnet die Fenster in Kacheln an @@ -7431,28 +7451,28 @@ Verfügbare Optionen: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7468,192 +7488,204 @@ Verfügbare Optionen: Eine oder mehrere Folien des aktuellen Projekts exportieren - + + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Afficher les guides Hilfslinien anzeigen - + Affiche ou masque les guides Zeigt die Hilfslinien an oder blendet sie aus - + Exporter au format CSV Als CSV-Datei exportieren - + Gestionnaire de borniers (DEV) Klemmleisten-Manager (DEV) - + Exporter la liste des noms de conducteurs Leiterbeschriftungen exportieren - + Exporter le plan de câblage Verdrahtungsplan erstellen - + Numérotation automatique des bornes Automatische Nummerierung der Klemmen - + Exporter la base de donnée interne du projet Interne Datenbank exportieren - + Dispose les fenêtres en cascade status bar tip ordnet die Fenster überlappend an - + Active le projet suivant status bar tip wechselt zum nächsten Projekt - + Active le projet précédent status bar tip wechselt zum vorherigen Projekt - + Ajouter un plan de bornes Klemmenplan hinzufügen - + Ajoute un champ de texte sur le folio actuel Fügt ein Textfeld auf die aktuelle Folie ein - + Ajoute une image sur le folio actuel Fügt ein Bild auf die aktuelle Folie ein - + Ajoute une ligne sur le folio actuel Fügt eine Linie auf die aktuelle Folie ein - + Ajoute un rectangle sur le folio actuel Fügt ein Rechteck auf die aktuelle Folie ein - + Ajoute une ellipse sur le folio actuel Fügt eine Ellipse auf die aktuelle Folie ein - + Ajoute une polyligne sur le folio actuel Fügt eine Polylinie auf die aktuelle Folie ein - + Ajoute un plan de bornier sur le folio actuel Klemmenplan auf aktueller Folie einfügen - + Chercher/remplacer Suchen/ersetzen - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Profondeur toolbar title Tiefe/Ebene - + &Fichier &Datei - + &Édition B&earbeiten - + &Projet &Projekt - + Afficha&ge &Anzeige - + Fe&nêtres Fe&nster - + &Récemment ouverts &Zuletzt geöffnet - + Affiche ou non la barre d'outils principale Zeigt oder versteckt die Hauptwerkzeugsleiste - + Affiche ou non la barre d'outils Affichage Zeigt oder versteckt die Anzeigeleiste - + Affiche ou non la barre d'outils Schéma Zeigt oder versteckt die Schaltplan-Werkzeugsleiste - + Affiche ou non le panel d'appareils Zeigt oder versteckt die Bauteilsammlung - + Affiche ou non la liste des modifications Zeigt oder versteckt die Änderungsliste - + Afficher les projets Projekte anzeigen - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) QElectroTech-Projekte (*.qet);;XML-Dateien (*.xml);;Alle Dateien (*) - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7662,7 +7694,7 @@ Verfügbare Optionen: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7671,57 +7703,57 @@ Verfügbare Optionen: - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Doppelclick, um die Form zu beenden / Rechtsklick, um den letzten Punkt zu entfernen - + Suppression de borne impossible Klemme kann nicht gelöscht werden - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer Die Löschung kann nicht durchgeführt werden, da die Auswahl eine oder mehrere Klemmen enthält, die überbrückt sind und/oder zu einer Klemme mit mehreren Ebenen gehören. Entfernen Sie die Überbrückung und/oder löschen Sie die Ebenen der betroffenen Klemmen, um sie löschen zu können - + Groupe Gruppe - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content Ein Fehler ist beim Öffnen der Datei %1 aufgetreten. - + Active le projet « %1 » Aktiviert das Projekt "%1" - + Outils Werkzeuge - + Couleur de fond blanc/gris Tool tip of white/grey background button Hintergrundfarbe weiß/grau - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Schalte die Hintergrundfarbe der Folien in weiß oder grau um @@ -7745,147 +7777,147 @@ Entfernen Sie die Überbrückung und/oder löschen Sie die Ebenen der betroffene Inhalt der Zwischenablage auf Folie einfügen - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Bearbeitet die Folieneigenschaften (Maße, Schriftfeld-Daten, Leitereigenschaften...) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Wechselt in das Ansichtsmodus, in dem die Folie nicht bearbeitet werden kann - + Affichage Anzeige - + Schéma Schaltplan - + Ajouter Einfügen - - + + Projet %1 enregistré dans le repertoire: %2. Projekt %1 gespeichert im Pfad: %2. - + Ouvrir un fichier Datei öffnen - - + + Impossible d'ouvrir le fichier message box title Öffnen der Datei nicht möglich - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Die zu öffnende Datei %1 existiert nicht. - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Die zu öffnende Datei kann zum Lesen nicht zugegriffen werden. Prüfen Sie die Zugriffsrechte der Datei. - + Ouverture du projet en lecture seule message box title Projekt wird schreibgeschützt geöffnet - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Es sind keine Schreibrechte für das zu öffnende Projekt vorhanden. Es wird trotzdem schreibgeschützt geöffnet. - - + + Échec de l'ouverture du projet message box title Öffnen des Projekts gescheitert - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content Die Datei %1 ist vermutlich keine QElectroTech-Projektdatei. Sie kann nicht geöffnet werden. - + Éditer l'élement edit element Bauteil bearbeiten - + Éditer le champ de texte edit text field Textfeld bearbeiten - + Éditer l'image edit image Bild bearbeiten - + Éditer le conducteur edit conductor Leitereigenschaften bearbeiten - + Éditer l'objet sélectionné edit selected item Auswahl bearbeiten - + Êtes-vous sûr de vouloir supprimer ce folio ? Möchten Sie diese Seite wirklich löschen? - + Supprimer les folios Seiten löschen - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? Möchten Sie die ausgewählten %1 Seiten wirklich löschen? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Fehler @@ -8751,42 +8783,42 @@ Die erforderlichen Bedingungen wurden nicht erfüllt QETProject - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Projekt "%1: %2" - + Projet %1 displayed title for a title-less project - %1 is the file name Projekt %1 - + Projet sans titre displayed title for a project-less, file-less project Projekt ohne Titel - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [schreibgeschützt] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [geändert] - + Système de contacts modifié Modifiziertes Kontaktsystem - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8797,19 +8829,19 @@ Bestehende Slave-Elemente werden nicht automatisch zugeordnet. Sie müssen die S Möchten Sie fortfahren? - + Une erreur s'est produite durant l'intégration du modèle. error message Ein Fehler ist beim Einfügen der Vorlage aufgetreten. - + Avertissement message box title Warnung - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 @@ -8817,7 +8849,7 @@ Vous utilisez actuellement QElectroTech en version %2 Sie verwenden derzeit QElectroTech Version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? @@ -8825,32 +8857,32 @@ Que désirez vous faire ? Was möchten Sie tun? - + Avertissement message box title Warnung - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. Das Projekt, das Sie zu öffnen versuchen, ist teilweise mit Ihrer Version %1 von QElectroTech kompatibel. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? Um es vollständig kompatibel zu machen, öffnen Sie bitte das gleiche Projekt mit der QElectroTech-Version 0.8 oder 0.80, speichern Sie das Projekt und öffnen Sie es erneut mit dieser Version. Was möchten Sie tun? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Öffnen des Projekts...</b><br/>Folien werden erstellt</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Öffnen des Projekts...</b><br/>Querverweise werden eingelesen</p> @@ -10513,22 +10545,22 @@ Möchten Sie sie ersetzen? Leiter erstellen - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> Installation des Plugins qet_tb_generator:<br>Besuche <br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Erfordert Python 3.5 oder höher.<br><B><U> Erstinstallation unter Windows</B></U><br>1. Falls erforderlich, installiere Python 3.5 oder höher<br> Besuche :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Aktualisierung unter Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>Der Benutzer kann in einem Terminal dieses Skript in folgendem Verzeichnis ausführen:<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> Installation des Plugins qet_tb_generator:<br>Besuche <br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> Erstinstallation unter macOSX</B></U><br>1. Falls erforderlich, installiere das Python 3.11-Bundle: <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2. Führe das Skript Profile.command aus<br>da das Programm einen festgelegten PATH zur Lokalisierung des Plugins qet-tb-generator verwendet.<br>Besuche :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>Anleitung</a><br>3. pip3 install qet_tb_generator<br><B><U> Aktualisierung unter macOS</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> Installation des Plugins qet_tb_generator:<br>Besuche <br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Erfordert Python 3.5 oder höher.<br><br><B><U> Erstinstallation unter Linux</B></U><br>1. Überprüfe, ob pip3 installiert ist: pip3 --version<br>Falls nicht, installiere es mit: sudo apt-get install python3-pip<br>2. Installiere das Programm: sudo pip3 install qet_tb_generator<br>3. Starte das Programm: qet_tb_generator<br><br><B><U> Aktualisierung unter Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Fehler beim Ausführen vom Plugin qet_tb_generator diff --git a/lang/qet_el.ts b/lang/qet_el.ts index bc39450d1..bb95de70b 100644 --- a/lang/qet_el.ts +++ b/lang/qet_el.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Εισαγωγή συνδέσμου - Title: Τίτλος: - URL: URL: @@ -1273,6 +1270,24 @@ Note: These options DO NOT allow or block Auto Numberings, only their Update Pol Μετακίνηση ενός βασικού στοιχείου + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1364,7 +1379,7 @@ Note: These options DO NOT allow or block Auto Numberings, only their Update Pol DiagramEventAddElement - + Ajouter %1 Προσθήκη %1 @@ -2171,17 +2186,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations Πληροφορίες - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3437,7 +3457,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title Εξαγωγή @@ -5491,13 +5511,13 @@ Veuillez utiliser l'éditeur avancé pour cela. - + Nouveau folio configuration page title Νέα σελίδα - + Nouveau projet configuration page title Νέο έργο @@ -6091,7 +6111,7 @@ Les variables suivantes sont incompatibles : PrintConfigPage - + Impression configuration page title Εκτύπωση @@ -6865,22 +6885,22 @@ Options disponibles : QETDiagramEditor - + Afficha&ge Προβο&λή - + Affiche ou non le panel d'appareils Εμφανίζει (ή όχι) το πλαίσιο στοιχείων - + Ajouter une colonne Προσθήκη στήλης - + &Cascade &Κλιμάκωση @@ -6900,27 +6920,27 @@ Options disponibles : Α&ποκοπή - + Désélectionner tout Αποεπιλογή όλων - + &Édition Ε&πεξεργασία - + Enlever une colonne Απομάκρυνση στήλης - + &Enregistrer &Αποθήκευση - + Enregistrer sous Αποθήκευση ως @@ -6930,17 +6950,17 @@ Options disponibles : Ε&ξαγωγή - + Fe&nêtres Παρά&θυρα - + &Fermer &Κλείσιμο - + &Fichier &Αρχείο @@ -6950,52 +6970,52 @@ Options disponibles : Εκτύπωση - + Inverser la sélection Αντιστροφή της επιλογής - + Mode Selection Κατάσταση Λειτουργίας Επιλογής - + Mode Visualisation Κατάσταση Λειτουργίας Προβολής - + &Mosaïque &Μωσαϊκό - + &Nouveau &Νέο - + Outils Εργαλεία - + &Ouvrir Άν&οιγμα - + Ouvrir un fichier Άνοιγμα αρχείου - + Pas de zoom Επαναφορά της εστίασης - + Pivoter Περιστροφή @@ -7005,27 +7025,27 @@ Options disponibles : &Τερματισμός - + Supprimer Διαγραφή - + Tout sélectionner Επιλογή Όλων - + Zoom adapté Εστίαση ώστε να χωράει - + Zoom arrière Αποεστίαση - + Zoom avant Εστίαση @@ -7045,32 +7065,32 @@ Options disponibles : Επαναφορά των αγωγών - + Affiche ou non la barre d'outils principale Προβολή ή απόκρυψη της κύριας γραμμής εργαλείων - + Affiche ou non la barre d'outils Affichage Προβολή ή απόκρυψη της γραμμής εργαλείων Προβολής - + Affiche ou non la barre d'outils Schéma Προβολή ή απόκρυψη της γραμμής εργαλείων Διαγραμμάτων - + Affichage Προβολή - + Schéma Διάγραμμα - + Ajouter un champ de texte Προσθήκη πεδίου κειμένου @@ -7080,102 +7100,102 @@ Options disponibles : Καμία αλλαγή - + Affiche ou non la liste des modifications Προβολή ή απόκρυψη του καταλόγου αναιρέσεων - + Éditer l'item sélectionné Επεξεργασία του επιλεγμένου αντικειμένου - + Lancer le plugin de création de borniers Έναρξη του προσθέτου δημιουργίας ακροδεκτών - + Grouper les textes sélectionnés Ομαδοποίηση επιλεγμένων κειμένων - + Pivote les éléments et textes sélectionnés status bar tip Περιστροφή των επιλεγμένων στοιχείων και των επιλεγμένων κειμένων - + Pivote les textes sélectionnés à un angle précis status bar tip Περιστροφή των επιλεγμένων κειμένων κατά μία συγκεκριμένη γωνία - + Chercher/remplacer Αναζήτηση / Αντικατάσταση - + &Projet Έρ&γο - + &Récemment ouverts Προσφάτως ανοιγμένα - - + + Projet %1 enregistré dans le repertoire: %2. Το έργο %1 αποθηκεύτηκε στον κατάλογο: %2. - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Το αρχείο, το όποιο προσπαθείτε να ανοίξετε, δεν φαίνεται να είναι αναγνώσιμο και δεν μπορεί να ανοιχτεί. Παρακαλώ, ελέγξτε τα δικαιώματα του αρχείου. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Το έργο, το οποίο προσπαθείτε να ανοίξετε, δεν φαίνεται να είναι εγγράψιμο. Θα ανοιχτεί μόνο για ανάγνωση. - + en utilisant des onglets χρήση καρτελών - + en utilisant des fenêtres χρήση παραθύρων - + Afficher les projets Προβολή των έργων - + Propriétés du projet Ιδιότητες του έργου - + Nettoyer le projet Καθαρισμός του έργου - - + + Échec de l'ouverture du projet message box title Αδυναμία ανοίγματος του έργου - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content Το αρχείο %1 δεν δείχνει να είναι αρχείο έργου QElectroTech. Κατά συνέπεια, δεν μπορεί να ανοιχτεί. @@ -7205,27 +7225,27 @@ Options disponibles : Επιλέξτε μια ενέργεια για να επαναφέρετε τις αλλαγές που κάνατε στο διάγραμμα σας - + Orienter les textes Προσανατολισμός των κειμένων - + Retrouver dans le panel Εύρεση στο πλαίσιο - + Ajouter une image Προσθήκη εικόνας - + Ajouter un sommaire Προσθήκη περίληψης - + Zoom sur le contenu Εστίαση στο περιεχόμενο @@ -7260,13 +7280,13 @@ Options disponibles : Αντιγράφει τα επιλεγμένα στοιχεία - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Αποεπιλέγει όσα στοιχεία είναι επιλεγμένα, και επιλέγει όσα δεν ήταν επιλεγμένα - + Retrouve l'élément sélectionné dans le panel status bar tip Εύρεση του επιλεγμένου στοιχείου στον πίνακα @@ -7301,92 +7321,92 @@ Options disponibles : Χρήση της αυτόματης δημιουργίας αγωγών όταν αυτό είναι δυνατόν - + Restaure le zoom par défaut status bar tip Επαναφέρει το προκαθορισμένο μέγεθος εστίασης - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Εμφανίζει τα διάφορα ανοιγμένα έργα, σε παράθυρα - + Ajouter une nomenclature Προσθήκη ονοματολογίας - + Présente les différents projets ouverts des onglets status bar tip Εμφανίζει τα διάφορα ανοιγμένα έργα, σε καρτέλες - + Permet de sélectionner les éléments status bar tip Επιτρέπει την επιλογή στοιχείων - + Ajouter un plan de bornes - + Ajoute un champ de texte sur le folio actuel Προσθέτει ένα πεδίο κειμένου στην τρέχουσα σελίδα - + Ajoute une image sur le folio actuel Προσθήκη εικόνας στην τρέχουσα σελίδα - + Ajoute une ligne sur le folio actuel Προσθήκη γραμμής στην τρέχουσα σελίδα - + Ajoute un rectangle sur le folio actuel Προσθήκη ορθογώνιου στην τρέχουσα σελίδα - + Ajoute une ellipse sur le folio actuel Προσθήκη έλλειψης στην τρέχουσα σελίδα - + Ajoute une polyligne sur le folio actuel Προσθήκη πολυγραμμής στην τρέχουσα σελίδα - + Ajoute un plan de bornier sur le folio actuel - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Ajouter Προσθήκη - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7395,7 +7415,7 @@ Options disponibles : - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7404,119 +7424,119 @@ Options disponibles : - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Διπλό κλικ για τελείωμα του σχήματος, Δεξί κλικ για ακύρωση του τελευταίου σημείου - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Éditer l'élement edit element Επεξεργασία του στοιχείου - + Éditer le champ de texte edit text field Επεξεργασία του πεδίου κειμένου - + Éditer l'image edit image Επεξεργασία εικόνας - + Éditer le conducteur edit conductor Επεξεργασία αγωγού - + Éditer l'objet sélectionné edit selected item Επεξεργασία του επιλεγμένου αντικειμένου - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content Παρουσιάστηκε σφάλμα κατά το άνοιγμα του αρχείου %1. - + Active le projet « %1 » Ενεργοποιεί το έργο « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Σφάλμα - + Dispose les fenêtres en mosaïque status bar tip Διαρρυθμίζει τα παράθυρα σαν πλακίδια - + Dispose les fenêtres en cascade status bar tip Διαρρύθμιση των παραθύρων σε κλιμακωτή διάταξη - + Projet suivant Επόμενο έργο @@ -7536,28 +7556,28 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7574,213 +7594,225 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Couleur de fond blanc/gris Tool tip of white/grey background button Χρώμα παρασκηνίου λευκό/γκρι - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Εμφανίζει το χρώμα παρασκηνίου της σελίδας σε λευκό ή γκρι - + Afficher la grille Εμφάνιση του δικτυώματος - + Affiche ou masque la grille des folios Εμφάνιση ή απόκρυψη του δικτυώματος της σελίδας - + Afficher les guides - + Affiche ou masque les guides - + Propriétés du folio Ιδιότητες σελίδας - + Ajouter un folio Προσθήκη σελίδας - - - + + + Supprimer le folio Διαγραφή σελίδας - + Exporter au format CSV Εξαγωγή ως CSV - + Gestionnaire de borniers (DEV) Διαχειριστής ακροδεκτών (DEV) - + Exporter la liste des noms de conducteurs Εξαγωγή της λίστας των ονομάτων των αγωγών - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet Εξαγωγή της εσωτερικής βάσης δεδομένων έργου - + Projet précédent Προηγούμενο έργο - + Crée un nouveau projet status bar tip Δημιουργία νέου έργου - + Ouvre un projet existant status bar tip Άνοιγμα υπάρχοντος έργου - + Ferme le projet courant status bar tip Κλείσιμο τρέχοντος έργου - + Enregistre le projet courant et tous ses folios status bar tip Αποθήκευση τρέχοντος έργου - + Enregistre le projet courant avec un autre nom de fichier status bar tip Αποθήκευση του τρέχοντος έργου με διαφορετικό όνομα αρχείου - + Ajouter une ligne Add row Προσθήκη γραμμής - + Enlever une ligne Remove row Αφαίρεση γραμμής - + Ajoute une colonne au folio status bar tip Προσθήκη στήλης στη σελίδα - + Enlève une colonne au folio status bar tip Απομάκρυνση στήλης από τη σελίδα - + Agrandit le folio en hauteur status bar tip Επεκτείνει το ύψος της σελίδας - + Rétrécit le folio en hauteur status bar tip Συρρικνώνει το ύψος της σελίδας - + Enlève les éléments sélectionnés du folio status bar tip Διαγράφει τα επιλεγμένα στοιχεία από τη σελίδα - + Sélectionne tous les éléments du folio status bar tip Επιλέγει όλα τα στοιχεία τις σελίδας - + Désélectionne tous les éléments du folio status bar tip Αποεπιλέγει όλα τα στοιχεία τις σελίδας - + Agrandit le folio status bar tip Επεκτείνει τη σελίδα - + Rétrécit le folio status bar tip Συρρικνώνει τη σελίδα - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Προσαρμογή της εστίασης έτσι ώστε να εμφανιστούν όλα τα περιεχόμενα της σελίδας ανεξάρτητα από το πλαίσιο - + Adapte le zoom exactement sur le cadre du folio status bar tip Προσαρμογή της εστίασης στο μέγεθος του πλαισίου της σελίδας - + Ajouter une ligne Draw line Προσθήκη γραμμής - + Ajouter un rectangle Προσθήκη παραλληλόγραμμου - + Ajouter une ellipse Προσθήκη έλλειψης - + Ajouter une polyligne Προσθήκη πολυγραμμής @@ -7797,13 +7829,13 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Εκτυπώνει μία ή περισσότερες σελίδες του τρέχοντος έργου - + Profondeur toolbar title Βάθος - + Groupe Ομάδα @@ -7814,48 +7846,48 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Επικολλάει τα περιεχόμενα του προχείρου στη σελίδα - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Επεξεργαστείτε τις ιδιότητες της σελίδας (διαστάσεις, πληροφορίες πινακίδας, ιδιότητες αγωγών...) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Επιτρέπει την προβολή της σελίδας χωρίς να είναι δυνατή η μετατροπή της - + Active le projet suivant status bar tip Ενεργοποιεί το επόμενο έργο - + Active le projet précédent status bar tip Ενεργοποιεί το προηγούμενο έργο - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) Έργα QElectroTech (*.qet);;Αρχεία XML (*.xml);;Όλα τα αρχεία (*) - - + + Impossible d'ouvrir le fichier message box title Αδυναμία ανοίγματος του αρχείου - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Φαίνεται ότι το αρχείο 1% που προσπαθείτε να ανοίξετε δεν υπάρχει. - + Ouverture du projet en lecture seule message box title Άνοιγμα του αρχείου μόνο για ανάγνωση @@ -8722,54 +8754,54 @@ les conditions requises ne sont pas valides QETProject - + Une erreur s'est produite durant l'intégration du modèle. error message Παρουσιάστηκε σφάλμα κατά την ενσωμάτωση του προτύπου. - + Avertissement message box title Προειδοποίηση - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Έργο « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Έργο %1 - + Projet sans titre displayed title for a project-less, file-less project Ανώνυμο έργο - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [μόνο-για-ανάγνωση] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [Αλλαγμένο] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8777,44 +8809,44 @@ Voulez-vous continuer ? - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? - + Avertissement message box title Προειδοποίηση - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Άνοιγμα του έργου...</b><br/>Δημιουργία των σελίδων</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Άνοιγμα του τρέχοντος έργου ...</b><br/>Εφαρμογή των παραπομπών</p> @@ -10476,22 +10508,22 @@ Voulez-vous la remplacer ? Δημιουργία αγωγών - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> Για να εγκαταστήσετε το πρόσθετο qet_tb_generator<br>Επισκεφθείτε το:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'> qet-tb-generator</a><br> Απαιτεί python 3.5 ή παραπάνω <br> <B> <U> Πρώτη εγκατάσταση στα Windows </B> </U> <br> 1. Εγκατάσταση, εάν απαιτείται, python 3.5 ή παραπάνω <br> Επισκεφθείτε το: <br> <a href='https://www.python.org/downloads/'> python.org </a> <br> 2. pip install qet_tb_generator <br> <B> <U> Ενημέρωση στα Windows </B> </U> <br> python -m pip install --upgrade qet_tb_generator <br>>> Ο χρήστης θα μπορούσε να ξεκινήσει σε ένα τερματικό αυτό το σενάριο σε αυτό τον κατάλογο <br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> Για να εγκαταστήσετε το πρόσθετο qet_tb_generator<br>Επισκεφθείτε το:<br><a href='https://pypi.python.org/pypi/qet-tb-generator'> qet-tb-generator</a><br><br> Απαιτεί python 3.5 ή παραπάνω <br><br> <B> <U> Πρώτη εγκατάσταση στο Linux </B> </U> <br> 1. ελέγχτε αν έχετε εγκατεστημένο το pip3: pip3 --version<br>αν οχι, εγκαταστήστε το με: sudo apt-get install python3-pip<br>2. Εγκαταστήστε την εφαρμογή: sudo pip3 install qet_tb_generator<br>3. Εκκινήστε την εφαρμογή: qet_tb_generator<br><br><B><U> Αναβάθμιση σε Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Σφάλμα εκκίνησης του προσθέτου qet_tb_generator diff --git a/lang/qet_en.qm b/lang/qet_en.qm index 9b01c5982f04b7edb023b79c7f02fbb70ddf5bcd..3c294cf4be6af322854730e315773e3108010aa0 100644 GIT binary patch delta 20788 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 JnNlCm{{eRt=|BJg diff --git a/lang/qet_en.ts b/lang/qet_en.ts index d01c84aa9..6abfb2cd5 100644 --- a/lang/qet_en.ts +++ b/lang/qet_en.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Insert Link - Title: Title: - URL: URL: @@ -1273,6 +1270,24 @@ Note: these options DO NOT allow or block auto numberings, only their update pol Move a primitive + + CustomElementInfoPartWidget + + + nom_de_la_propriete + name_of_the_property + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + Lower-case letters, numbers, hyphens and underscores only + + + + Supprimer cette propriété + Delete this property + + DiagnosticsReportDialog @@ -1364,7 +1379,7 @@ Note: these options DO NOT allow or block auto numberings, only their update pol DiagramEventAddElement - + Ajouter %1 insert %1 @@ -2174,17 +2189,22 @@ The element's display name is edited separately in the element properties.< Exclude from automatic numbering - + Informations Information - + + Ajouter une propriété personnalisée + Add a custom property + + + Séparation de potentiel Potential separation - + Exclure de la nomenclature Exclude from the bill of materials @@ -3450,7 +3470,7 @@ By importing this file, you confirm that: ExportConfigPage - + Export configuration page title Export @@ -5499,13 +5519,13 @@ Please use the advanced editor for this. Guides - + Nouveau folio configuration page title New folio - + Nouveau projet configuration page title New project @@ -6101,7 +6121,7 @@ The following variables are incompatible: PrintConfigPage - + Impression configuration page title Printing @@ -6879,22 +6899,22 @@ Available options: QETDiagramEditor - + Afficha&ge Displ&ay - + Affiche ou non le panel d'appareils Show or hide the elements panel - + Ajouter une colonne Add a column - + &Cascade &Cascade @@ -6914,27 +6934,27 @@ Available options: Cu&t - + Désélectionner tout Select none - + &Édition &Edit - + Enlever une colonne Remove a column - + &Enregistrer &Save - + Enregistrer sous Save as @@ -6944,17 +6964,17 @@ Available options: &Export - + Fe&nêtres Wi&ndows - + &Fermer &Close - + &Fichier &File @@ -6964,12 +6984,12 @@ Available options: Print - + Inverser la sélection Invert selection - + Mode Selection Select @@ -6980,51 +7000,51 @@ Available options: This panel lists the various changes applied to the current folio. Clicking a change gets the folio back to its state right after it was applied. - + Couleur de fond blanc/gris Tool tip of white/grey background button Background color white / gray - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Displays the background color of the folio in white or gray - + Afficher la grille Display the grid - + Affiche ou masque la grille des folios Display or hide the grid of folio - + Propriétés du folio Folio properties - + Ajouter un folio Add a folio - - - + + + Supprimer le folio Delete this folio - + Mode Visualisation Move - + &Mosaïque &Tile @@ -7038,28 +7058,28 @@ Available options: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas Diagram editors @@ -7075,180 +7095,180 @@ Available options: Export one or more folios of the current project - + Afficher les guides View the guides - + Affiche ou masque les guides Shows or hides the guides - + Exporter au format CSV Export to CSV - + Gestionnaire de borniers (DEV) Terminal block manager (DEV) - + Lancer le plugin de création de borniers Launch the terminal block creation plugin - + Exporter la liste des noms de conducteurs Export the list of names of wires - + Exporter le plan de câblage Export the wiring diagram - + Numérotation automatique des bornes Automatic numbering of terminals - + Exporter la base de donnée interne du projet Export the internal project database - + &Nouveau &New - + Crée un nouveau projet status bar tip Creates a new project - + Ouvre un projet existant status bar tip Opens an existing project - + Ferme le projet courant status bar tip Closes the current project - + Enregistre le projet courant et tous ses folios status bar tip Saves the current project and all its folios - + Enregistre le projet courant avec un autre nom de fichier status bar tip Saves the current project with a different file name - + Ajouter une ligne Add row Add row - + Enlever une ligne Remove row Remove a row - + Ajoute une colonne au folio status bar tip Add a column to the folio - + Enlève une colonne au folio status bar tip Remove a column from the folio - + Agrandit le folio en hauteur status bar tip Expands the folio height - + Rétrécit le folio en hauteur status bar tip Shrinks the folio height - + Enlève les éléments sélectionnés du folio status bar tip Removes selected elements from the folio - + Sélectionne tous les éléments du folio status bar tip Selects all elements on the folio - + Désélectionne tous les éléments du folio status bar tip Deselect all elements on the folio - + Agrandit le folio status bar tip Expand the folio - + Rétrécit le folio status bar tip Shrinks the folio - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Adjusts the zoom to display all the contents of folio regardless of context - + Adapte le zoom exactement sur le cadre du folio status bar tip Adjusts the zoom on exactly the part of the folio - + Ajouter une ligne Draw line Add line - + Ajouter un rectangle Add a rectangle - + Ajouter une ellipse Add an ellipse - + Ajouter une polyligne Add a polygon @@ -7265,13 +7285,13 @@ Available options: Prints one or more folio of the current project - + Profondeur toolbar title Depth - + Groupe Group @@ -7282,39 +7302,39 @@ Available options: Pastes elements from the clipboard into the folio - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Edits the properties of the folio (size, title block informations, conductor properties...) - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Allows to view the folio without modifying it - + Outils Tools - + &Ouvrir &Open - + Ouvrir un fichier Open a file - + Pas de zoom Reset zoom - + Pivoter Rotate @@ -7324,27 +7344,27 @@ Available options: &Quit - + Supprimer Delete - + Tout sélectionner Select All - + Zoom adapté Fit in view - + Zoom arrière Zoom Out - + Zoom avant Zoom In @@ -7364,32 +7384,32 @@ Available options: Reset conductors - + Affiche ou non la barre d'outils principale Display or hide the main toolbar - + Affiche ou non la barre d'outils Affichage Display or hide the Display toolbar - + Affiche ou non la barre d'outils Schéma Display or hide the Diagram toolbar - + Affichage Display - + Schéma Diagram - + Ajouter un champ de texte Add a textfield @@ -7399,97 +7419,97 @@ Available options: No modification - + Affiche ou non la liste des modifications Display or hide the undo list - + Éditer l'item sélectionné Edit the selected item - + Grouper les textes sélectionnés Group selected texts - + Pivote les éléments et textes sélectionnés status bar tip Rotate selected elements and texts - + Pivote les textes sélectionnés à un angle précis status bar tip Rotate selected texts to a specific angle - + Chercher/remplacer Search / Replace - + &Projet &Project - + &Récemment ouverts &Latest files - - + + Projet %1 enregistré dans le repertoire: %2. Project %1 registered in the directory: %2. - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. The file you try to open does not seem readable and can not be opened. Please check the file permissions. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. The project you try to open does not seem writable. It will be opened read-only. - + en utilisant des onglets using tabs - + en utilisant des fenêtres using windows - + Afficher les projets Display projects - + Propriétés du projet Project properties - + Nettoyer le projet Clean project - - + + Échec de l'ouverture du projet message box title Unable to open project - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content The file %1 does not appear to be a QElectroTech project file. Thus it cannot be opened. @@ -7519,27 +7539,27 @@ Available options: Click an action to get back in the changes you made to your diagram - + Orienter les textes Choose texts orientation - + Retrouver dans le panel Find in the panel - + Ajouter une image Add a picture - + Ajouter un sommaire Add a summary - + Zoom sur le contenu Zoom content @@ -7574,13 +7594,13 @@ Available options: Copies selected elements - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Inverts selection of elements - + Retrouve l'élément sélectionné dans le panel status bar tip Find the selected item in the panel @@ -7615,115 +7635,127 @@ Available options: Using the automatic creation of conductor (s) when possible - + Restaure le zoom par défaut status bar tip Restores default zoom level - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Shows the various opened projects in windows - + + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + Automatic disconnection of conductor(s) + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + Automatically cut existing conductors when placing an element + + + Ajouter une nomenclature Add a nomenclature - + Présente les différents projets ouverts des onglets status bar tip Shows the various opened projects in tabs - + Permet de sélectionner les éléments status bar tip Allows to select elements - + Ajouter un plan de bornes Add a terminal plan - + Ajoute un champ de texte sur le folio actuel Adds a text field to the current folio - + Ajoute une image sur le folio actuel Add an image to the current folio - + Ajoute une ligne sur le folio actuel Add a line to the current folio - + Ajoute un rectangle sur le folio actuel Adds a rectangle on the current folio - + Ajoute une ellipse sur le folio actuel Add an ellipse to the current folio - + Ajoute une polyligne sur le folio actuel Adds a polyline to the current folio - + Ajoute un plan de bornier sur le folio actuel Add a terminal plan on the current sheet - + Atteindre un élément Navigate to an element - + Recherche et sélectionne rapidement un élément du folio status bar tip Quickly search for and select an element in the folio - + Ajouter Add - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) QElectroTech project(*.qet);;XML Files (*.xml);;All files (*) - - + + Impossible d'ouvrir le fichier message box title Unable to open file - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. It appears the %1 file which you are trying to open does not exist or does not exist anymore. - + Ouverture du projet en lecture seule message box title Opening the file read-only - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7732,7 +7764,7 @@ Available options: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7741,136 +7773,136 @@ Available options: - + Polices du projet message box title Project fonts - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Double-click to finish the shape, Right click to cancel the last point - + Suppression de borne impossible Unable to delete the terminal - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer The deletion cannot be performed because the selection contains one or more terminals that are bridged and/or belong to a multi-level terminal. Unbridge and/or remove the levels from the affected terminals so that they can be deleted - + Éditer l'élement edit element Edit the element - + Éditer le champ de texte edit text field Edit the text field - + Éditer l'image edit image Edit the image - + Éditer le conducteur edit conductor Edit conductor - + Éditer l'objet sélectionné edit selected item Edit the selected object - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content An error occurred while opening file %1. - + Active le projet « %1 » Activates the project « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? Are you sure you want to delete this folio? - + Supprimer les folios Delete the folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? Are you sure you want to delete the selected %1 folios ? - + Supprimer %1 folios Delete %1 folios - - - - - - - + + + + + + + Déplacer les folios Move the folios - + Erreur message box title Error - + Dispose les fenêtres en mosaïque status bar tip Arranges windows in a tile pattern - + Dispose les fenêtres en cascade status bar tip Arranges windows in a cascade pattern - + Projet suivant Next project - + Projet précédent Previous project - + Active le projet suivant status bar tip Activates the next project - + Active le projet précédent status bar tip Activates the previous project @@ -8737,48 +8769,48 @@ the conditions are not valid QETProject - + Avertissement message box title Warning - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Project « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Project %1 - + Projet sans titre displayed title for a project-less, file-less project Untitled project - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [read-only] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [modified] - + Système de contacts modifié Modified contact system - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8789,13 +8821,13 @@ Existing slave elements will not be automatically assigned. You will need to lin Do you wish to continue? - + Une erreur s'est produite durant l'intégration du modèle. error message An error occurred during the template integration. - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 @@ -8804,7 +8836,7 @@ Vous utilisez actuellement QElectroTech en version %2 You are currently using QElectroTech in version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? @@ -8813,32 +8845,32 @@ Que désirez vous faire ? What do you wish to do ? - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. The project you are trying to open is partially compatible with your version %1 of QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? In order to make it fully compatible please open this same project with version 0.8, or 0.80 of QElectroTech and save the project and open it again with this version. What do you wish to do ? - + Avertissement message box title Warning - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b>Opening the project ...</b><br/>Creation of folios</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Opening the project ...</b><br/>Setting up cross references</p> @@ -10501,22 +10533,22 @@ Do you want to replace it ? Creation of conductors - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Error launching qet_tb_generator plugin diff --git a/lang/qet_es.ts b/lang/qet_es.ts index 5f701d292..21c8f069a 100644 --- a/lang/qet_es.ts +++ b/lang/qet_es.ts @@ -329,19 +329,16 @@ AddLinkDialog - Insert Link Insertar enlace - Title: Título: - URL: URL: @@ -1274,6 +1271,24 @@ Nota: Estas opciones NO permiten o bloquean las Numeraciones automáticas, solo Mover una primitiva + + CustomElementInfoPartWidget + + + nom_de_la_propriete + + + + + Lettres minuscules, chiffres, tiret et underscore uniquement + + + + + Supprimer cette propriété + + + DiagnosticsReportDialog @@ -1365,7 +1380,7 @@ Nota: Estas opciones NO permiten o bloquean las Numeraciones automáticas, solo DiagramEventAddElement - + Ajouter %1 Añadir %1 @@ -2174,17 +2189,22 @@ Le nom affiché de l'élément se modifie séparément dans les propriété - + Informations Información - + + Ajouter une propriété personnalisée + + + + Séparation de potentiel - + Exclure de la nomenclature @@ -3446,7 +3466,7 @@ En important ce fichier, vous confirmez que : ExportConfigPage - + Export configuration page title Exportar @@ -5505,13 +5525,13 @@ Por favor use el editor avanzado para esto. - + Nouveau folio configuration page title Nuevo folio - + Nouveau projet configuration page title Nuevo projecto @@ -6105,7 +6125,7 @@ Las siguientes variables son incompatibles; PrintConfigPage - + Impression configuration page title Impresión @@ -6886,27 +6906,27 @@ Opciones disponibles: Ninguna modificación - + &Nouveau &Nuevo - + &Ouvrir &Abrir - + &Fermer &Cerrar - + &Enregistrer &Guardar - + Enregistrer sous Guardar como @@ -6931,28 +6951,28 @@ Opciones disponibles: - - - - - - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Éditeur de schémas @@ -7004,234 +7024,246 @@ Opciones disponibles: + Coupure automatique de conducteur(s) + Tool tip of auto break conductor + + + + + Couper automatiquement les conducteurs existants lors du placement d'un élément + Status tip of auto break conductor + + + + Couleur de fond blanc/gris Tool tip of white/grey background button Color de fondo blanco / gris - + Affiche la couleur de fond du folio en blanc ou en gris Status tip of white/grey background button Muestra el color de fondo de la hoja en blanco o gris - + Afficher la grille Mostrar cuadrícula - + Affiche ou masque la grille des folios Muestra u oculta la cuadrícula - + Afficher les guides - + Affiche ou masque les guides - + Propriétés du folio Propiedades del folio - + Ajouter un folio Añadir un folio - - - + + + Supprimer le folio Eliminar el folio - + Exporter au format CSV - + Ajouter une nomenclature - + Gestionnaire de borniers (DEV) - + Exporter la liste des noms de conducteurs - + Exporter le plan de câblage - + Numérotation automatique des bornes - + Exporter la base de donnée interne du projet - + Crée un nouveau projet status bar tip Crear un nuevo proyecto - + Ouvre un projet existant status bar tip Abrir un proyecto existente - + Ferme le projet courant status bar tip Cerrar el proyecto - + Enregistre le projet courant et tous ses folios status bar tip Guardar el proyecto - + Enregistre le projet courant avec un autre nom de fichier status bar tip Guardar el proyecto con otro nombre de archivo - + Ajouter une ligne Add row Añadir una fila - + Enlever une ligne Remove row Eliminar una fila - + Ajoute une colonne au folio status bar tip Añadir una columna - + Enlève une colonne au folio status bar tip Eliminar una columna - + Agrandit le folio en hauteur status bar tip Aumentar el tamaño vertical del folio - + Rétrécit le folio en hauteur status bar tip Disminuir el tamaño vertical del folio - + Enlève les éléments sélectionnés du folio status bar tip Eliminar los elementos seleccionados - + Tout sélectionner Seleccionar todo - + Désélectionner tout Deseleccionar todo - + Inverser la sélection Invertir la selección - + Ajouter un plan de bornes - + Ajoute un champ de texte sur le folio actuel Agrega un campo de texto en el folio actual - + Ajoute une image sur le folio actuel Agregar una imagen en el folio actual - + Ajoute une ligne sur le folio actuel Añadir una línea al folio actual - + Ajoute un rectangle sur le folio actuel Añadir un rectangulo al folio actual - + Ajoute une ellipse sur le folio actuel Agregar una elipse al folio actual - + Ajoute une polyligne sur le folio actuel Agregar una polilínea al folio actual - + Ajoute un plan de bornier sur le folio actuel - + Atteindre un élément - + Recherche et sélectionne rapidement un élément du folio status bar tip - + Profondeur toolbar title Profundidad - + %n description(s) de police écrite(s) dans un format étranger ou corrompu ont été restaurée(s). Elles seront réécrites dans un format stable au prochain enregistrement du projet. message box content @@ -7240,7 +7272,7 @@ Opciones disponibles: - + %n description(s) de police n'ont pas pu être lue(s) ; la police par défaut sera utilisée pour ces textes. message box content @@ -7249,50 +7281,50 @@ Opciones disponibles: - + Polices du projet message box title - + Double-click pour terminer la forme, Click droit pour annuler le dernier point Doble clic para terminar la forma, Clic derecho para cancelar el último punto - + Suppression de borne impossible - + La suppression ne peut être effectué car la selection possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple. Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les supprimer - + Groupe Grupo - + Une erreur est survenue lors de l'ouverture du fichier %1. message box content Se produjo un error al abrir el archivo %1. - + Supprimer Eliminar - + Pivoter Girar - + Éditer l'item sélectionné Editar el elemento seleccionado @@ -7302,62 +7334,62 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Reiniciar los conductores - + Ajouter un champ de texte Añadir un campo de texto - + Ajouter une colonne Añadir una columna - + Enlever une colonne Eliminar una columna - + Propriétés du projet Propiedades del proyecto - + Zoom avant Ampliar - + Zoom arrière Reducir - + Zoom adapté Ajustar - + Pas de zoom Normal - + en utilisant des onglets utilizando pestañas - + en utilisant des fenêtres utilizando ventanas - + Mode Selection Modo selección - + Mode Visualisation Modo visualización @@ -7368,32 +7400,32 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Haga clic en una acción para volver atras en la edición de su esquema - + Retrouver dans le panel Encontrar en el panel - + Ajouter une image Añadir una imagen - + Ajouter un sommaire Añadir un resumen - + Zoom sur le contenu Ampliar el contenido - + &Mosaïque &Mosaico - + &Cascade &Cascada @@ -7421,221 +7453,221 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Utilizar creación automática de un conductor(es) - + Lancer le plugin de création de borniers terminales o bornes Lanzar el plugin de creación de terminales - + Grouper les textes sélectionnés Agrupar los textos seleccionados - + Pivote les éléments et textes sélectionnés status bar tip Gira los elementos y textos seleccionados - + Pivote les textes sélectionnés à un angle précis status bar tip Gira los textos seleccionados a un ángulo determinado - + Retrouve l'élément sélectionné dans le panel status bar tip Encontrar el elemento seleccionado en el panel - + Ajouter une ligne Draw line Añadir una línea - + Chercher/remplacer Buscar/Reemplazar - + &Fichier &Archivo - + &Édition &Edición - + &Projet P&royecto - + Afficha&ge &Ver - + Fe&nêtres Venta&nas - + Affiche ou non la barre d'outils principale Mostrar u ocultar la barra de herramientas principal - + Affiche ou non la barre d'outils Affichage Mostrar u ocultar la barra de herramientas "Ver" - + Affiche ou non la barre d'outils Schéma Mostrar u ocultar la barra de herramientas "Esquema" - + Affiche ou non le panel d'appareils Mostrar u ocultar el panel de dispositivos - + Affiche ou non la liste des modifications Mostrar u ocultar la lista de modificaciones - + Afficher les projets Mostrar los proyectos - + Outils Herramientas - + Affichage Ver - + Schéma Esquema - + Ajouter Añadir - + Ouvrir un fichier Abrir un archivo - + Il semblerait que le fichier que vous essayez d'ouvrir ne soit pas accessible en lecture. Il est donc impossible de l'ouvrir. Veuillez vérifier les permissions du fichier. Parece que el archivo que intenta abrir no es accesible en lectura. Por eso es imposible abrirlo. Por favor compruebe los permisos del archivo. - + Il semblerait que le projet que vous essayez d'ouvrir ne soit pas accessible en écriture. Il sera donc ouvert en lecture seule. Parece que el proyecto que intenta abrir no es accesible en escritura. Por eso se abrira en sólo lectura. - + Éditer l'élement edit element Editar el elemento - + Éditer le champ de texte edit text field Editar el campo de texto - + Éditer l'image edit image Editar la imagen - + Éditer le conducteur edit conductor Editar el conductor - + Éditer l'objet sélectionné edit selected item Editar el objeto seleccionado - + Active le projet « %1 » Activar el proyecto « %1 » - + Êtes-vous sûr de vouloir supprimer ce folio ? - + Supprimer les folios - + Êtes-vous sûr de vouloir supprimer les %1 folios sélectionnés ? - + Supprimer %1 folios - - - - - - - + + + + + + + Déplacer les folios - + Erreur message box title Error - + Nettoyer le projet Limpiar el proyecto - - + + Échec de l'ouverture du projet message box title Fracaso al abrir el proyecto - + Il semblerait que le fichier %1 ne soit pas un fichier projet QElectroTech. Il ne peut donc être ouvert. message box content Parece que el archivo %1 no es un archivo de proyecto QElectroTech. Por eso no se puede abrir. @@ -7659,7 +7691,7 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Anulaciones - + Orienter les textes Orientar los textos @@ -7694,7 +7726,7 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Copiar los elementos seleccionados al portapapeles - + Désélectionne les éléments sélectionnés et sélectionne les éléments non sélectionnés status bar tip Deseleccionar los elementos ya seleccionados y seleccionar los elementos no seleccionados @@ -7706,98 +7738,98 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Recalcule los caminos de los conductores sin tener en cuenta las modificaciones - + Restaure le zoom par défaut status bar tip Restaurar el zoom por defecto - + Présente les différents projets ouverts dans des sous-fenêtres status bar tip Mostrar los diferentes proyectos abiertos en sub ventanas - + Présente les différents projets ouverts des onglets status bar tip Mostrar los diferentes proyectos abiertos en pestañas - + Permet de sélectionner les éléments status bar tip Permite seleccionar los elementos - + Dispose les fenêtres en mosaïque status bar tip Poner las ventanas en mosaico - + Dispose les fenêtres en cascade status bar tip Poner las ventanas en cascada - + Projet suivant Proyecto siguiente - + Projet précédent Proyecto previo - + Sélectionne tous les éléments du folio status bar tip Selecciona todos los elementos - + Désélectionne tous les éléments du folio status bar tip Deselecciona todos los elementos - + Agrandit le folio status bar tip Aumenta el tamaño del folio - + Rétrécit le folio status bar tip Disminuye el tamaño del folio - + Adapte le zoom de façon à afficher tout le contenu du folio indépendamment du cadre Ajusta el zoom para visualizar todos los contenidos del folio - + Adapte le zoom exactement sur le cadre du folio status bar tip Ajusta el zoom al folio - + Ajouter un rectangle Añadir un rectángulo - + Ajouter une ellipse Añadir una elipse - + Ajouter une polyligne Añadir un polígono @@ -7820,59 +7852,59 @@ Déponter et/ou supprimer les niveaux des bornes concerné afin de pouvoir les s Pega los elementos del portapapeles en el folio - + Édite les propriétés du folio (dimensions, informations du cartouche, propriétés des conducteurs...) status bar tip Edita las propiedades del folio - + Permet de visualiser le folio sans pouvoir le modifier status bar tip Permitir ver el folio sin modificarlo - + Active le projet suivant status bar tip Activar el proyecto siguiente - + Active le projet précédent status bar tip Activar el proyecto previo - + &Récemment ouverts &Recientemente abiertos - - + + Projet %1 enregistré dans le repertoire: %2. Proyecto %1 guardar en el directorio: %2. - + Projets QElectroTech (*.qet);;Fichiers XML (*.xml);;Tous les fichiers (*) Projectos QElectroTech (*.qet);;Archivos XML (*.xml);;Todos los archivos (*.") - - + + Impossible d'ouvrir le fichier message box title Imposible de abrir el archivo - + Il semblerait que le fichier %1 que vous essayez d'ouvrir n'existe pas ou plus. Parece que el archivo %1 que usted está intentando abrir no existe. - + Ouverture du projet en lecture seule message box title Abriendo el proyecto en sólo lectura @@ -8738,48 +8770,48 @@ veuillez patienter durant l'import... QETProject - + Avertissement message box title Advertencia - + Projet « %1 : %2» displayed title for a ProjectView - %1 is the project title, -%2 is the project path Projecto « %1 : %2» - + Projet %1 displayed title for a title-less project - %1 is the file name Proyecto %1 - + Projet sans titre displayed title for a project-less, file-less project Proyecto sín título - + %1 [lecture seule] displayed title for a read-only project - %1 is a displayable title %1 [sólo lectura] - + %1 [modifié] displayed title for a modified project - %1 is a displayable title %1 [modificado] - + Système de contacts modifié - + Le nouvel élément définit des groupes de contacts esclaves. Les éléments esclaves existants ne seront pas automatiquement assignés. Vous devrez relier manuellement les esclaves et assigner les groupes de contacts. @@ -8787,50 +8819,50 @@ Voulez-vous continuer ? - + Une erreur s'est produite durant l'intégration du modèle. error message Un error ocurrió durante la integración del modelo. - + Ce document semble avoir été enregistré avec une version %1 qui est ultérieure à votre version ! Vous utilisez actuellement QElectroTech en version %2 - + . Il est alors possible que l'ouverture de tout ou partie de ce document échoue. Que désirez vous faire ? - + Avertissement message box title - + Le projet que vous tentez d'ouvrir est partiellement compatible avec votre version %1 de QElectroTech. - + Afin de le rendre totalement compatible veuillez ouvrir ce même projet avec la version 0.8, ou 0.80 de QElectroTech et sauvegarder le projet et l'ouvrir à nouveau avec cette version. Que désirez vous faire ? - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Création des folios</p> <p align="center"><b><p align="center"><b>Apertura del proyecto en curso...</b><br/>Creación de folios</p> - + <p align="center"><b>Ouverture du projet en cours...</b><br/>Mise en place des références croisées</p> <p align="center"><b>Apertura del proyecto en curso...</b><br/>Configuración de referencias cruzadas</p> @@ -10498,22 +10530,22 @@ Voulez-vous la remplacer ? Creación de conductores - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requires python 3.5 or above.<br><B><U> First install on Windows</B></U><br>1. Install, if required, python 3.5 or above<br> Visit :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. pip install qet_tb_generator<br><B><U> Update on Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>user could launch in a terminal this script in this directory<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> Para instalar el plugin qet_tb_generator<br>Visita :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br>Requiere python 3.5 o superior.<br><B><U> Primera instalación en Windows</B></U><br>1. Instalar, si es necesario, python 3.5 o superior<br> Visita :<br><a href='https://www.python.org/downloads/'>python.org</a><br>2. instalación de pip qet_tb_generator<br><B><U> Update en Windows</B></U><br>python -m pip install --upgrade qet_tb_generator<br>>>El usuario podría iniciar en un terminal este script en este directorio.<br> C:\users\XXXX\AppData\Local\Programs\Python\Python36-32\Scripts <br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><B><U> First install on macOSX</B></U><br>1. Install, if required, python 3.11 bundle only, <a href='https://www.python.org/ftp/python/3.11.2/python-3.11.2-macos11.pkg'>python-3.11.2-macos11.pkg</a><br>2 Run Profile.command script<br>because program use hardcoded PATH for localise qet-tb-generator plugin <br> Visit :<br><a href='https://qelectrotech.org/forum/viewtopic.php?pid=5674#p5674'>howto</a><br>2. pip3 install qet_tb_generator<br><B><U> Update on macOSX</B></U><br> pip3 install --upgrade qet_tb_generator<br> - + To install the plugin qet_tb_generator<br>Visit :<br><a href='https://pypi.python.org/pypi/qet-tb-generator'>qet-tb-generator</a><br><br>Requires python 3.5 or above.<br><br><B><U> First install on Linux</B></U><br>1. check you have pip3 installed: pip3 --version<br>If not install with: sudo apt-get install python3-pip<br>2. Install the program: sudo pip3 install qet_tb_generator<br>3. Run the program: qet_tb_generator<br><br><B><U> Update on Linux</B></U><br>sudo pip3 install --upgrade qet_tb_generator<br> - + Error launching qet_tb_generator plugin Error al iniciar el complemento qet_tb generator diff --git a/lang/qet_fr.qm b/lang/qet_fr.qm index 4e36f8350619c3c57631d7bd4f659f47b91375fc..f2cf5588023cc544ac15ada18414abe3b0fb2843 100644 GIT binary patch delta 20587 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 M!j4T#;e);Z2b2ssmH+?% delta 20168 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