The right-drag ring showed the shortcut bar's commands for the selection.
A new Preferences page, "Gestes de la souris", lets the user pick the
ring's commands per selection context, one per direction, and choose 4 or
8 directions. Commands are dropped from the list onto a slot of a ring
editor, or placed with a button; Delete empties a slot.
A context the user never edits keeps following the shortcut bar, and 8
directions stays the default, so nothing changes for anyone who does not
open the page. A picked list is positional: a direction left empty, or
holding a command this build lacks, stays empty instead of shifting the
others. Stored like ShortcutBarSettings: diagrameditor/gestures/<context>
id lists in QSettings, defaults not stored.
tst_gesturesettings covers the defaults, positional lists, the 4/8
setting, the overlay's sectors and empty slots, and the page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fitCells() tried counts from 1, but BorderTitleBlock raises any column
or row count below 3 to 3. With very large cells (A5 portrait with
columns of about 200 px or more) the preset picked 2 columns; the folio
then got 3, came out wider than the sheet, and the dropdown fell back
to "Custom". Start the search, and the capped fallback, at 3, and
refuse a paper that leaves no room for 3 cells of the smallest size.
A5 portrait with 300 px columns now gives 3 x 179 px instead of
2 x 269 px; A4 landscape with the default cells is unchanged
(19 x 58 px). ctest 65/65.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A "Format" choice in the folio dimensions box sets the columns and rows
so the whole folio, title block included, has the size of an ISO A
sheet at the 96 dpi the PDF export uses. A4 landscape keeps 60 px
columns and 80 px rows and comes out as an A4 page in the PDF.
Nothing new is stored: the choice only fills in the columns and rows.
A folio whose size already matches a paper shows that paper; any other
shows "Custom". Changing the title block template after picking a paper
fits the folio again; a template too tall for the paper falls back to
"Custom".
The same box is in Folio properties and in the new-folio defaults of
the project and application settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
stderr got it in the previous commit; stdout (the JSON of --info, the
messages of the exports) still ended its lines in "\r\n" on Windows
while stderr ended them in "\n". Both streams now give the same bytes
on every system.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The skip applied wherever setPermissions() failed, which on Linux and
macOS would hide a real failure. Only Windows cannot take read
permission away; elsewhere the call must succeed as before.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
itemChange() removed the corner handles when the text left the scene
but did not bring them back when it returned still selected, which Qt
allows (undoing a scripted delete does it) without a selection change.
Refresh on every scene change. The two handle helpers are protected:
nothing outside the class calls them.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The box showed Auto for -1 while IndependentTextItem::setTextWidth()
treats every value up to 0 as automatic. Typing 0, or the first click
on the up arrow from Auto, then put a width change in the undo history
that changed nothing, left the box on 0, and in live edit every later
change of X, Y, angle, text or size was replaced by that empty command.
Auto is 0 in the box now, like in the setter: no number is the automatic
width, and the first step up is 1 px.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A dynamic text field is never edited inline in the element editor (it
never sets text interaction flags), so the handles never had to hide
for it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The slot was auto-connected by name to QComboBox::activated(QString),
which Qt 6 removed, so connectSlotsByName() found no signal and picking
a variable in the "Texte composé" dialog did nothing. activated(int)
exists in Qt 5 and Qt 6; the slot never used its argument and reads
currentData() as before.
Same fix as the CompositeTextEditDialog half of #674, which was closed
unmerged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With symbols as blocks, every non-empty information field of a symbol
(label, manufacturer, reference, supplier, quantity...) is written as a
hidden attribute of its INSERT, tagged with the field's name. A CAD
program can then list the parts from the drawing, as with AutoCAD's
attribute extraction; hidden, they change nothing on screen, in any
reader. A field already written as a visible attribute (with
--dxf-attributes) is not repeated. The label formula is left out: it is
how the label is made, not part data.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With symbols as blocks and the new "DXF : textes des symboles en
attributs" option (--dxf-attributes on the command line), a symbol's own
texts (its label, function, comment...) are attributes of its INSERT
instead of loose texts, so a CAD program moves them with the symbol and
can list or edit them. Each is written exactly where, and as, the text
was. A text showing an information field is tagged with its name
(LABEL, FUNCTION...), a typed text TEXT1, TEXT2...; a text's second line
gets _2. The block defines each tag once, placed where the first symbol
has it.
Its own option, off by default, because LibreCAD (2.2.1.5) does not
show attributes: the labels would vanish there. AutoCAD shows them.
The text geometry moves into textLines(), shared with the text loop,
so the attributes and the plain texts cannot drift apart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With "DXF : symboles en blocs" ticked in the export dialog, or
--dxf-blocks on the command line, each symbol definition a folio uses is
written once as a DXF block and every placed symbol as an INSERT of it.
A CAD program then selects, counts and replaces a symbol as one object.
The block is drawn by the same code as a symbol drawn in full, as if
the symbol sat unturned at the folio's origin, which is DXF (0,
sheetHeight): that is the block's base point, so the INSERT carries the
symbol's position and quarter-turn and nothing else. Blocks have to come
before any entity, so the export collects them first and dxfBegin()
writes them in its BLOCKS section. Entities in a block keep their own
layers. Off by default; with it off the file is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Circles and arcs: drawArcEllipse() split each curve into quarters and
fitted a circular ARC through a point half way between the curve and its
chord, so every circle came out as a flattened diamond. A circle or an
arc of one is now one exact CIRCLE or ARC. R10 has no ELLIPSE entity, so
a true ellipse is a polyline through the curve, one point every 5
degrees. The export also used a different scale on each axis, which made
round things oval; it now uses one, the largest that fits the sheet.
Title block at the right: the DXF laid the horizontal template out in
the narrow vertical strip, squashing it into the top corner. It is now
laid out horizontally and turned a quarter, as draw() turns the painter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Edit menu had grown to 42 entries and no longer fitted on a laptop
screen; Qt wrapped it into a second column. Select, Group, Rows and
columns and Depth now sit one level down, as Add and Align already did.
Search for a command, Shortcut bar and Repeat move to the end, beside
Search/Replace. No action, label or shortcut changes: Ctrl+A was checked
to still select everything from inside the new Select submenu.
Lignes et colonnes was already built as a submenu for the folio's
context menu; the Edit menu now uses the same one instead of a flat copy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
applyToAll() restyled every QMainWindow, including the terminal strip
editor and the print window, which never read the settings when they
open: they changed on OK and went back to defaults when reopened.
applyTo() now marks the window, and applyToAll() only updates marked
windows, so the page covers the folio, element and title block editors
as described.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parseText() creates a QGraphicsSimpleTextItem for every <text> of an
element (the DXF export reads them later) and appends it to the
primitives it is given. build() draws every primitive twice, once for
the normal and once for the low-zoom picture, and gave the second pass
a fresh `primitives fake_prim` per primitive that went out of scope
with its text items still allocated. dropCache() also removed a
location's primitives without deleting their text items.
LeakSanitizer on the Linux CI sanitizer build (separate PR) stops
every --resave or export of a project whose elements have texts:
ERROR: LeakSanitizer: detected memory leaks
Indirect leak of 37200 byte(s) in 75 object(s) allocated from:
#1 QGraphicsSimpleTextItem::QGraphicsSimpleTextItem(QGraphicsItem*)
#2 ElementPictureFactory::parseText(...) elementpicturefactory.cpp:658
#4 ElementPictureFactory::build(...) elementpicturefactory.cpp:324
Give the low-zoom pass one set of primitives for the whole element and
delete its text items when both pictures are drawn; in dropCache(),
take the primitives out of the hash and delete their text items. The
items kept in m_primitives_H for the DXF export are unchanged, and the
destructor deletes those as before.
No file-format change, nothing drawn differently. Tests: the
sanitizer job on Linux fails on master with the report above and
passes with this change; ctest on macOS 64/64. The leak is invisible
to a plain test and to ASan on macOS, which has no LeakSanitizer.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Beat Hangartner <beat@hangartners.ch>
The exports, --info, --resave and --run return before QetLogger's
handler is installed, so they keep Qt's default handler. On Linux and
macOS it writes to stderr. On Windows it writes to the debugger when the
program has no console, and a GUI program started by another program
never has one: everything a headless run reported -- a wire that could
not be reconnected, which way the project database was filled, an
element that could not be read -- was lost to the caller, a test or a
tool like qet-mcp. Install a handler for these runs that writes to
stderr in the form the default handler uses on the other systems (the
default message pattern, UTF-8).
On macOS the stderr of --info, --resave, --run and --export-svg is
byte-identical before and after (memory addresses aside). On Windows,
tst_databasefromdocument and tst_terminaluuids, which read these
messages, fail before and pass after.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
anUnreadableSymbolIsNotACollision() takes every permission away from a
symbol file to check that an unreadable symbol is reported as such, not
as a collision. QFile::setPermissions() cannot do that on Windows, where
Qt only knows the read-only flag, so it returns false and the test
failed there. It now skips, as it already does when run as root, which
reads the file anyway.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
In the element editor, a dynamic text field that is the only selected
item gets the corner handles of TextResizeHandles: dragging one sets
the width the field wraps to, keeping the opposite corner in place;
double-clicking a handle goes back to the automatic width. One undo
step per drag, on the editor's undo stack.
ElementScene keeps the handles of the same text when the undo stack
changes: pushing the resize itself calls managePrimitivesGroups()
again, and deleting the handles there would delete them while they are
still emitting.
No file format change (text_width on <dynamic_text> already exists).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A selected free text gets the corner handles of the previous commit:
dragging one sets the width the text wraps to, keeping the opposite
corner in place; double-clicking a handle goes back to the automatic
width. One undo step per drag, on the folio's undo stack. The handles
are hidden while the text is typed in.
DiagramTextItem shows the handles for a subclass that asks for them
(textResizeHandlesWanted()); only free texts do for now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A "Width" spin box in the properties of a free text sets the width it
wraps to (previous commit). "Auto" (-1) is the automatic width. It also
works with several selected texts, like the size and the angle; texts
with different widths show "Auto" and are left alone unless the box is
changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>