Commit Graph

66 Commits

Author SHA1 Message Date
ispyisail 7c0e867226 Rewrite element-prefix lookup for nesting and multi-tree common collections
The remaining two defects from bugtracker #671's original analysis,
which #686 knowingly didn't cover (see that PR's review thread and the
comment on the now-closed #672).

## #671 item 5: the XML matching ignored nesting

prefixFromLabelFile() was a flat token scan: it matched any <category
name="..."> whose name equalled the next path segment, with no check
that the match was actually a *child* of the previous match. It gave
correct results on the shipped 10_electric/qet_labels.xml only because
that file's document order happens to line up with its hierarchy --
any file with a same-named category at the wrong nesting depth would
silently return the wrong prefix.

Reproduced with a synthetic file where a top-level sibling category
happens to share a name with what should be an unmatched grandchild:
the old (already re-verified-fixed-for-whitespace) lookup returns a
prefix from a completely unrelated branch of the document; this
rewrite correctly reports "not found".

Fixed by replacing the QXmlStreamReader token walk with a QDomDocument
walk that only ever considers a matched node's direct <category>
children (firstChildElement()/nextSiblingElement(), scoped to that
node), which cannot cross into a same-named sibling subtree. This also
makes the whitespace-dependence fixed in #686 moot for the same
reason: DOM parsing doesn't distinguish pretty-printed from minified
input to begin with.

The inheritance rule ("if a directory has no prefix, use its parent's,
and so on") and the empty-<prefix/>-overrides-inheritance behaviour
#686 added both carry over unchanged: a category's own <prefix> child,
even an empty one, always overrides whatever a shallower ancestor
already provided; a category with no <prefix> child at all leaves the
inherited value untouched.

## #671 item 2: common-collection trees other than 10_electric

The lookup only ever consulted commonElementsDir()/10_electric --
literally: `if (current_location.fileName() == "10_electric")`. The
common collection ships four other top-level trees (20_logic,
30_hydraulic, 50_pneumatic, 60_energy); none of them could carry a
qet_labels.xml at all, because nothing ever looked for one.

Generalised to commonElementsDir()/<tree>/qet_labels.xml for whichever
top-level tree the element's path actually walks up to, tried first,
then custom, then company -- each of the latter two tried against both
a from-root layout (matching a custom/company file organised as a
mirror of the common collection, tree name included) and a
tree-relative one (matching a file scoped to just one tree), so
existing custom files keep working either way. This is the same
multi-candidate structure #686 already established for custom-then-
company; it now also covers which common-collection tree to check.

## Testing

Same constraint as #686: no working full build in this sandbox
(missing generated headers/deps), so the exact functions as committed
were extracted into a standalone Qt6 harness and run against the real
shipped 10_electric/qet_labels.xml (pretty-printed and minified),
a synthetic empty-prefix-override file, and the nesting-trap file
above -- 9/9, including the three cases #686 already fixed (direct
prefix, inherited prefix, not-found) staying correct, confirming this
rewrite doesn't regress that work.

Not exercised here (needs a real running QETApp / ElementsLocation,
which the standalone harness can't stand up): the elementPrefixForLocation()
candidate-list wiring itself -- collection_root computation, the
from-root/tree-relative dual lookup, and the common-then-custom-then-
company ordering. That code is mechanical and was reviewed carefully
by hand, but it has not been run.
2026-09-12 06:32:07 +12:00
ispyisail 0b7197118a Fix three follow-on defects in the prefix lookup this PR just refactored
Requested by @scorpio810 in review: an empty <prefix/> in the custom
collection should cancel a company-collection prefix, not fall through
to it. QXmlStreamReader::readElementText() returns a null QString for an
empty element, and the caller's isNull() check treats that the same as
"not found" -- distinguish the two so an explicit override actually
overrides. Verified in a standalone harness against a synthetic
override file, pretty-printed and minified.

Two more while in the same function, both from the original bugtracker
#671 analysis that this PR only partially addressed:

- QString path[10] with an unbounded index becomes a QStringList. The
  deepest category in the shipped collection already needs 9 of the 10
  slots; a custom collection can nest deeper, and overflow was writing
  QString objects past the end of a stack array (#671 item 3).
- The common-collection lookup still concatenated
  commonElementsDir() + "10_electric/qet_labels.xml" directly.
  commonElementsDir() returns the configured path verbatim with no
  guaranteed trailing separator, so relocating the collection to a path
  without one silently mangles this into one word and the file is never
  found -- the single most-reported cause of "prefixes don't work"
  (#671 item 1, forum #2178/#2651). QDir::filePath() joins correctly
  either way; applied to all three lookups (common, custom, company).

Also fixes a defect not in that original analysis: the token-matching
loop in prefixFromLabelFile() advanced twice per matched element --
once explicitly after a match, once more unconditionally at the bottom
of the loop -- which only produced the right result because a
pretty-printed file inserts a whitespace Characters token between
adjacent elements for the second advance to land on. A minified
qet_labels.xml has no such token, so the second advance skips clean
over the very element being searched for and the lookup silently finds
nothing -- reproduced against the real shipped 10_electric/qet_labels.xml
(returns "" instead of "K" for a plain coil, on every case tested, not
just the inheritance one). A single `continue` after a handled match
removes the double advance.

Testing: extracted the exact functions as committed into a standalone
Qt6 harness (outside the full QET build, which needs a dependency
fetch this sandbox doesn't have) and ran them against the real shipped
qet_labels.xml, pretty-printed and minified, covering a direct prefix,
inherited-from-ancestor prefix, not-found, and the explicit-empty-
override case -- 8/8, matching between formats, no regressions in the
pretty-printed results. The QDir::filePath() fix was verified
separately against both a trailing-slash and no-trailing-slash base
path. Not yet built inside the actual application (pugixml and other
generated headers aren't available standalone); the algorithm itself,
which is where all four defects lived, is what was under test.
2026-09-12 06:22:26 +12:00
Levi Jetzer e7cbb8f50e Reading prefixes from company collection
Added a reading for company collection prefixes which are overwritten by user collection prefixes
2026-08-07 17:20:45 +02:00
ispyisail d192d609ec Add a display format to numbering parts: a spreadsheet-style zero mask
A cyclic part could only ever be rendered at its natural width, which is
fine for one of @scorpio810's two real layouts and wrong for the other:

  April 5000/2000, 32-point cards   %IX0.0 .. %IX0.31, then %IX1.0
  Schneider M340, 64-point cards    I1.00 .. I1.63,    then I2.00

The first wants no padding, the second wants two digits. Since the two
conflict, the width cannot be derived from the modulus or from the part
type -- it has to be the user's to set.

Add a format field holding a run of zeros, the same convention a
spreadsheet uses for integer padding: "00" renders 7 as 07, "000" as 007.
The field's length is the minimum number of digits. It applies to every
numeric part type, not only cyclic ones, so "Chiffre 01" can be widened
past two digits without inventing another type for it.

An empty mask means the part type's own natural width, so it reproduces
exactly what every existing context does today -- Chiffre 1 stays 7,
Chiffre 01 stays 07, Chiffre 001 stays 007. That is what makes this safe
for existing projects: absent is the default, and absent changes nothing.

Stored as a sixth field on the context part and as an XML attribute
written only when set, following how modulus was added: readers guard on
size() and treat a short item as "no format". All seven places that
rebuild a part while incrementing it now carry the format through --
missing one would have silently dropped the padding on the second element
numbered.

The editor field is restricted to zeros by a validator, and is enabled
only for types that render as a number.

Measured:

  April, mask empty     %IX0.29 %IX0.30 %IX0.31 %IX1.0 %IX1.1
  M340,  mask "00"      I1.00 I1.01 ... I1.62 I1.63 I2.00 I2.01
  no mask               unit 7,8,9   ten 07,08,09   hundred 007,008,009
  ten with mask "0000"  0007 0008 0009
2026-08-02 20:29:02 +12:00
ispyisail 6f7e537db3 Let a Cyclique (modulo) part actually be displayed: %seqw_N
Reported by @scorpio810 on #632 with a screenshot: a "Chiffre 1" followed by
a "Cyclique (modulo) 8" numbers elements 0..7 and then jumps straight to 9,
never showing 8, and never producing the 0-7 / 10-17 / 20-27 pattern the
feature exists for.

The cause is that the wrap-and-carry feature shipped without its rendering
half. Commit 68c2603 added the arithmetic and the editor UI across seven
files, none of them assignvariables.*, so there is no %seqw_ variable, no
wrap list in sequentialNumbers, no branch in setSequential(), and no branch
in numerotationContextToFormula(). A cyclic part therefore contributes
nothing to the generated formula and cannot be referenced from one -- it is
invisible.

Invisible but not inert: it still advances and still carries. So the digit
in front of it receives +1 from the carry on top of its own increment, and
the only digit the label does show jumps by two. That is the missing 8.

Add the missing half:
  - sequentialNumbers gains a wrap list, handled in the copy constructor,
    assignment, comparison, clear(), toXml() and fromXml();
  - setSequential() collects wrap parts when the label uses %seqw_;
  - assignSequence() substitutes %seqw_N and counts wrap in its bound, so a
    context whose only counter is cyclic still resolves;
  - numerotationContextToFormula() emits %seqw_N, so adding a Cyclique part
    in the editor now puts a token in the formula instead of nothing.

Old projects are unaffected: <wrap> is simply absent from files written
before this, which fromXml() reads as an empty list, and such files have no
cyclic parts to reference in the first place. An older QET reading a newer
file ignores the unknown child.

Measured on the exact configuration from the report, unit + wrap(mod 8):

  formula generated   %sequ_1%seqw_1   (was %sequ_1 -- wrap contributed none)

  carry digit increment 1   00 11 22 33 44 55 66 77 90 101 112 ...
  carry digit increment 0   00 01 02 03 04 05 06 07 10 11 ... 17 20 21

The second line is the requested pattern. The first shows what is left once
the rendering is fixed but the carry digit still increments itself as well
as receiving the carry -- worth a UI decision, noted on the PR.
2026-08-02 18:46:28 +12:00
Laurent Trinques 2d99ba67f1 Merge pull request #588 from Kellermorph/Fix-PLC-Manager
Fix-PLC-Manager
2026-08-01 15:30:10 +02:00
ispyisail f7a79e75af Add alphabetical auto-numbering (a, b, ... z, aa, ab, ...) (#579)
Adds a real base-26 incrementing part type to the autonumbering engine,
alongside the 14 existing NumStrategy leaves. Unlike StringNum (a fixed,
non-incrementing text segment), AlphaNum::next()/previous() carry/borrow
entirely within the part's own value -- the composition loop in
NumerotationContextCommands doesn't need to change, since (unlike #578's
wrap-and-carry) nothing here needs to signal an adjacent part.

- incrementAlpha()/decrementAlpha() implement the spreadsheet-column-name
  algorithm: increment carries right-to-left on 'z'/'Z' overflow,
  prepending a new leading letter if the whole value overflows (z -> aa,
  az -> ba). decrement is the exact inverse, including the symmetric
  shrink case (aa -> z) once every position has borrowed. A single letter
  already at "a"/"A" has no representable predecessor and is clamped
  rather than turned into "z" -- caught via manual testing, since the
  initial implementation mutated the string in the borrow loop before
  checking whether to clamp, silently discarding the original value.
- Registered in NumerotationContext::validRegExpNum() but deliberately
  not in validRegExpNumber(), so addValue() doesn't force alphabetic
  values through int conversion.
- New "Cyclique"-adjacent "Alphabétique" entry in numparteditorw's type
  dropdown, with its own letters-only QRegularExpressionValidator; the
  increase spinbox is disabled since the step is always exactly one
  letter, not a configurable amount.

Also wires the new part type through to actual element/conductor labels,
which turned out to be required for the feature to do anything visible
beyond folio numbering (which applies a NumerotationContext's
represented string directly). Element and conductor numbering instead
go through a separate formula-substitution layer
(autonum::sequentialNumbers + %sequ_/%seqt_/%seqh_-style placeholders in
AssignVariables::assignSequence()) that numerotationContextToFormula()
auto-populates. Without a matching placeholder, an "alpha" part would
silently vanish from the generated formula and never reach the label,
even though the underlying counter was advancing correctly:
- sequentialNumbers gained an `alpha` QStringList member (copy ctor,
  operator=, operator==, toXml/fromXml, clear()).
- numerotationContextToFormula() emits a new %seqa_N placeholder for
  alpha parts, the same way %sequ_N is emitted for unit parts.
- setSequential()/setSequentialToList() populate seqStruct.alpha,
  passing the raw string through as-is rather than the .toInt()-based
  formatting used for the numeric part types.
- AssignVariables::assignSequence() substitutes %seqa_N from
  seqStruct.alpha, mirroring the existing %sequ_N/%seqt_N/%seqh_N
  substitutions.
No "alphafolio" variant was added, matching the discussion's scope (only
unit/ten/hundred have folio-anchored variants).

Verified against production code via the numbering config dialog's own
Suivant/Précédent buttons: from "a", 25 clicks reached "z"; one more
produced "aa"; 25 more reached "az"; one more produced "ba" (carry).
Reversed: "ba"->"az"->(25 clicks)->"aa"->"z" (shrink)->(25 clicks)->"a".
One more "previous" at "a" correctly stayed at "a" after the clamp fix.
Also confirmed the Formule field auto-updates to "%seqa_1" the instant
the type is switched to "Alphabétique", confirming the formula-generation
wiring works live in the UI, not just at the engine level.
2026-08-01 22:45:49 +12:00
Kellermorph 4c1f82f814 Fix-PLC-Manager 2026-07-31 21:02:07 +02:00
Kellermorph b3a8ae898e PLC Manager 2026-07-27 22:16:52 +02:00
Kellermorph 4e0c075575 Fix grid and guide startup behavior and update german translation 2026-06-16 17:41:03 +02:00
Laurent Trinques 4044d04cc5 One year
Auto-build doxygen docs / doxygen (push) Has been cancelled
Auto-build doxygen docs / deploy (push) Has been cancelled
2026-01-16 15:24:35 +01:00
achim f20ea041b6 correcting the visibility of Variables in CompositeText
When using composite text in report elements, the name of the variable
was displayed when inserting the reportElement into the drawing (e.g.
%{function}). This is corrected here.
Add missing variables to assignvariables.cpp
2025-08-02 22:16:12 +02:00
plc-user d007035237 whitespace and comment 2025-03-28 20:21:09 +01:00
Magnus Hellströmer 68a2ddde18 New variables for conductor text formulas 2025-02-19 20:26:53 +01:00
Laurent Trinques 77bfe84a4c One year 2025-01-04 13:37:40 +01:00
Laurent Trinques c1706cb055 Add new variables to elementInfoKeys
aux1, aux2, aux3, aux4
See:
https://qelectrotech.org/forum/viewtopic.php?pid=20558#p20558
2024-11-03 14:40:24 +01:00
Laurent Trinques e73cf633ce 2023->2024 2024-03-29 10:09:48 +01:00
Laurent Trinques 9afef79629 Update Copyright date 2023-01-01 17:05:57 +01:00
joshua 895417c98c Revert "Revert "Add terminalStripModel class""
This reverts commit 4615e6d060.
2021-09-10 23:30:49 +02:00
joshua 4615e6d060 Revert "Add terminalStripModel class"
This reverts commit a1e18d2bba.
2021-06-07 19:45:45 +02:00
joshua a1e18d2bba Add terminalStripModel class 2021-06-07 19:26:41 +02:00
Laurent Trinques ef58f34c14 Update Copyright date 2021-02-20 12:13:46 +01:00
joshua 2513961cd6 Revert "Update Copyright date"
This reverts commit d04bccc384.
2021-02-06 19:00:48 +01:00
Laurent Trinques d04bccc384 Update Copyright date 2021-02-06 18:33:42 +01:00
Simon De Backer 10c4c3d528 Wip Fix preprocessor on Cmake 2020-12-08 19:57:35 +01:00
Simon De Backer 6bfb2b95d2 QT6: QStringref replaced to QStringView in QT6
as a result this additional instruction is required
2020-10-26 23:01:45 +01:00
Simon De Backer 5d92393ee7 Wrap code for better readability 2020-09-07 22:03:40 +02:00
Simon De Backer 99abc165d6 Wrap code for better readability 2020-08-18 20:08:32 +02:00
Simon De Backer 790cdc5229 Fix some doxygen issues (~100) 2020-08-18 20:07:55 +02:00
Simon De Backer 76d16ab600 Improve code style, Wrap code for better readability 2020-08-16 14:22:36 +02:00
Simon De Backer d4ee161c07 Mod doc set style de same 2020-08-16 11:19:36 +02:00
Laurent Trinques e10ae8ce2e Update Copyright date 2020-06-15 17:42:53 +02:00
Claveau Joshua 55876293bc Replace minus (-) by underscore (_) in all element information 2020-04-12 19:45:19 +02:00
scorpio810 3ed7a4e63b Minor : update Copyright date
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5705 bfdf4180-ca20-0410-9c96-a3a8aa849046
2019-01-13 16:56:12 +00:00
scorpio810 2fe25e74fa Minor : indentation
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5630 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-12-04 22:33:11 +00:00
nuri f27954e507 Correction of some french and english notions and correction of typos. Variable %machine changed in %plant.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5629 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-12-04 19:07:14 +00:00
scorpio810 4ba3f477f8 Add new field "Group function" on properties of the selection widget and
for csv export


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5627 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-12-03 13:13:27 +00:00
scorpio810 e0c6cc6768 Add new fields "Quantity, Unity" onproperties of the selection widget
and for csv export


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5626 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-12-02 15:54:08 +00:00
scorpio810 58fb59491b Revert last commits
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5624 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-12-01 12:55:05 +00:00
scorpio810 ee91337d75 Add new fild and titleblock "Function group"
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5622 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-11-30 23:53:13 +00:00
scorpio810 48e730286d Improve last commit
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5514 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-09-22 15:59:05 +00:00
scorpio810 112df84964 Add in config the possibility to start the numbering of the columns of
titleblocks at 0.


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5510 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-09-22 10:39:36 +00:00
scorpio810 e4b1ba9797 Apply clang-tidy's performance-unnecessary-value-param, performance-for-
range-copy


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5448 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-07-19 14:14:31 +00:00
blacksun e3930df5b5 multi past dialog : add check box for autonum the pasted element
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5333 bfdf4180-ca20-0410-9c96-a3a8aa849046
2018-04-12 17:59:05 +00:00
scorpio810 9351ba63b7 Add new field Name of provider,
rename fields,
update *TS files


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5061 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-10-03 12:11:28 +00:00
scorpio810 9c24163556 Add new description field
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5059 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-10-02 16:59:53 +00:00
blacksun 29748874fd Dynamic element text item, can have for source of text a composite text, a text composed both by user typed text and element info.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5021 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-08-16 13:52:15 +00:00
scorpio810 2137ca744a Fix autonumbering menu cano assign formulas to custom element label.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4913 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-02-14 03:41:25 +00:00
scorpio810 7a62fe8356 Remove previous commits
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4912 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-02-13 20:49:31 +00:00
scorpio810 75140b63a4 Improve autonumbering to assign formulas to custom element label.
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@4911 bfdf4180-ca20-0410-9c96-a3a8aa849046
2017-02-13 19:26:09 +00:00