You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On a control schematic you place elements 100–300 times. Today every one of
those starts in the Collections dock: expand a category, find the symbol, press
and hold, drag across the window, release. The panel is a browsing tool being
used as a recall tool.
I started out writing a spec for a new cursor-anchored picker widget. Then I
read the code, and the interesting part turned out to be something else
entirely, so this post is about that instead.
QET already has the fast path
DiagramEventAddElement is a proper placement mode. The ghost element follows
the cursor, snapped to the user's configured grid. Left click places it. It stays loaded, so you can drop six terminals with six clicks. Space rotates
the pending element 90°. Right click or Esc cancels. It commits through AddGraphicsObjectCommand so undo behaves normally, and it auto-connects
aligned free terminals when the project has that enabled.
It is genuinely good. And it has exactly one entry point in the whole codebase:
That line is inside DiagramView::handleElementDrop(). The only way to reach
it is to finish a drag-and-drop.
Meanwhile the most natural alternative gesture does the slowest possible thing —
double-clicking an element in the Collections tree calls editElement() and
opens an Element Editor window (elementscollectionwidget.cpp:268).
So the problem isn't that QET lacks fast insertion. It has it, and most users
have never knowingly used it, because it only appears at the end of a drag.
More that is already built
Once I started looking, most of what a picker would need turned out to be
shipped already:
Where
Search index over display name and every element-info field (description, manufacturer, reference…)
fileelementcollectionitem.cpp:303-329, stored at Qt::UserRole+1
That index built eagerly at startup, multithreaded
A user-definable palette: make folders, drag elements in
Collections context menu + elementscollectionmodel.cpp:193 (ElementCollectionHandler::copy)
A shared team collection
QETApp::companyElementsDir()
Rebindable shortcuts with a preferences page
ShortcutManager::registerAction()
What is actually missing is small: any keyboard path to insertion, and any
memory of recently used elements (recentfiles.cpp is recent files).
Proposal
Phase 1 — insert without dragging (~100 lines, no new UI)
Two new call sites for the class that already exists:
Double-click / Enter in Collections enters place mode instead of opening
the editor. Editing stays on the context menu where it already is, plus F2.
"Insert last element" — a new action that re-enters place mode with the
last-placed element.
That is the whole first change. No new widget, no config file, no format change.
It makes all ~8,750 shipped elements reachable in two clicks, and lets you place
a run of identical symbols from the keyboard.
Phase 2 — flat ranked search results
The current search filters by hiding tree rows, so hits stay scattered through
an expanded tree. A QSortFilterProxyModel over the same model gives a flat
ranked list. No new index — it filters the string that is already there. Useful
in the dock on its own.
Phase 3 — a picker popup, at the cursor
Hotkey opens a popup at the mouse position with the search field focused; type
to filter, Enter to place, Esc to close.
The popup should be ElementsCollectionWidget shown in a popup, not a new
widget. The search field, tree, icons, context menu and translations all exist
already.
The one piece of real engineering: each widget currently builds its own ElementsCollectionModel (elementscollectionwidget.cpp:827), and a second one
would double an already slow startup — so model ownership needs hoisting to a
shared instance. There is precedent in the same area: QETApp::collectionCache()
is already a static singleton (qetapp.cpp:77).
Happily, sharing is safe: the dock filters with m_tree_view->setRowHidden(...), which is view state, not model state — so a
popup filtering hard will not disturb the dock behind it.
Phase 4 — a category icon grid
Only if Phases 1–3 turn out not to be enough. Presentation over data that would
already exist by then.
On configuration: a folder, not a file
My first draft had an XML menu file with default/shared/user layers, merge
rules, and a drag-to-customise mode. I have dropped all of it.
QET already has a user-owned, drag-populated, icon-rendering, searchable palette
— the custom collection. So:
A quick palette is a folder. Its subfolders are the categories; their contents
are the entries.
Which gives, with nothing new built:
Setup = drag elements into a folder, in the dock that is already open.
Ordering = filename prefixes 01_, 02_ — already the convention in the
shipped collection (10_electric, 20_logic, 30_hydraulic).
Team sharing = companyElementsDir(), which exists for exactly this.
Layering = common / company / custom, which users already understand.
Diffable and version-controllable = it is a directory tree.
No schema, no parser, no validation, no merge semantics, no "reset to default",
no customise mode. Only the palette path and the recently-used list go in QSettings.
One thing to get right: not Space
Space is bound four times:
diagrameditor.rotate_selection Space qetdiagrameditor.cpp:638
diagrameditor.rotate_group_selection Shift+Space qetdiagrameditor.cpp:639
diagrameditor.rotate_texts Ctrl+Space qetdiagrameditor.cpp:640
rotate the pending element 90° Space diagrameventaddelement.cpp:174
The last one rules it out — Space already means something inside place mode.
In the diagram editor the only bare bindings are Delete and Space, so most
letters are free, and bare letters have precedent (F = flip, M = mirror in
the element editor). I'd suggest A — it matches KiCad's add-symbol key for
people coming from there, and reads correctly in the source language
("Ajouter"). Low stakes either way, since ShortcutManager makes it a default
rather than a commitment and it shows up in the Shortcuts preferences page for
free.
Questions
Is changing double-click from "open editor" to "insert" acceptable? It is
a behaviour change. I can default to insert with a preference to restore, or
put edit on Alt+double-click. This is the only part of Phase 1 that is a
judgement call rather than plumbing, and I would rather settle it here than
in a PR.
Any objection to hoisting the collection model to a QETApp singleton?
It follows the existing collectionCache() pattern, but it touches loading
code that several people have worked on.
Does the folder-as-palette idea hold up against how people actually
organise their custom collections? I have designed it around the assumption
that users are already curating folders there. If that is not true in
practice, the whole config argument weakens and I would want to know before
building on it.
Is there appetite for Phase 1 alone? It is small and self-contained, and
it is useful whether or not anything later happens. I am happy to open it as
a standalone PR and let the rest wait for feedback.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
On a control schematic you place elements 100–300 times. Today every one of
those starts in the Collections dock: expand a category, find the symbol, press
and hold, drag across the window, release. The panel is a browsing tool being
used as a recall tool.
I started out writing a spec for a new cursor-anchored picker widget. Then I
read the code, and the interesting part turned out to be something else
entirely, so this post is about that instead.
QET already has the fast path
DiagramEventAddElementis a proper placement mode. The ghost element followsthe cursor, snapped to the user's configured grid. Left click places it. It
stays loaded, so you can drop six terminals with six clicks.
Spacerotatesthe pending element 90°. Right click or
Esccancels. It commits throughAddGraphicsObjectCommandso undo behaves normally, and it auto-connectsaligned free terminals when the project has that enabled.
It is genuinely good. And it has exactly one entry point in the whole codebase:
That line is inside
DiagramView::handleElementDrop(). The only way to reachit is to finish a drag-and-drop.
Meanwhile the most natural alternative gesture does the slowest possible thing —
double-clicking an element in the Collections tree calls
editElement()andopens an Element Editor window (
elementscollectionwidget.cpp:268).So the problem isn't that QET lacks fast insertion. It has it, and most users
have never knowingly used it, because it only appears at the end of a drag.
More that is already built
Once I started looking, most of what a picker would need turned out to be
shipped already:
fileelementcollectionitem.cpp:303-329, stored atQt::UserRole+1elementscollectionmodel.cpp:297—QtConcurrent::mapelementscollectioncache.cppelementscollectionmodel.cpp:193(ElementCollectionHandler::copy)QETApp::companyElementsDir()ShortcutManager::registerAction()What is actually missing is small: any keyboard path to insertion, and any
memory of recently used elements (
recentfiles.cppis recent files).Proposal
Phase 1 — insert without dragging (~100 lines, no new UI)
Two new call sites for the class that already exists:
the editor. Editing stays on the context menu where it already is, plus
F2.last-placed element.
That is the whole first change. No new widget, no config file, no format change.
It makes all ~8,750 shipped elements reachable in two clicks, and lets you place
a run of identical symbols from the keyboard.
Phase 2 — flat ranked search results
The current search filters by hiding tree rows, so hits stay scattered through
an expanded tree. A
QSortFilterProxyModelover the same model gives a flatranked list. No new index — it filters the string that is already there. Useful
in the dock on its own.
Phase 3 — a picker popup, at the cursor
Hotkey opens a popup at the mouse position with the search field focused; type
to filter, Enter to place,
Escto close.The popup should be
ElementsCollectionWidgetshown in a popup, not a newwidget. The search field, tree, icons, context menu and translations all exist
already.
The one piece of real engineering: each widget currently builds its own
ElementsCollectionModel(elementscollectionwidget.cpp:827), and a second onewould double an already slow startup — so model ownership needs hoisting to a
shared instance. There is precedent in the same area:
QETApp::collectionCache()is already a static singleton (
qetapp.cpp:77).Happily, sharing is safe: the dock filters with
m_tree_view->setRowHidden(...), which is view state, not model state — so apopup filtering hard will not disturb the dock behind it.
Phase 4 — a category icon grid
Only if Phases 1–3 turn out not to be enough. Presentation over data that would
already exist by then.
On configuration: a folder, not a file
My first draft had an XML menu file with default/shared/user layers, merge
rules, and a drag-to-customise mode. I have dropped all of it.
QET already has a user-owned, drag-populated, icon-rendering, searchable palette
— the custom collection. So:
Which gives, with nothing new built:
01_,02_— already the convention in theshipped collection (
10_electric,20_logic,30_hydraulic).companyElementsDir(), which exists for exactly this.No schema, no parser, no validation, no merge semantics, no "reset to default",
no customise mode. Only the palette path and the recently-used list go in
QSettings.One thing to get right: not
SpaceSpaceis bound four times:The last one rules it out —
Spacealready means something inside place mode.In the diagram editor the only bare bindings are
DeleteandSpace, so mostletters are free, and bare letters have precedent (
F= flip,M= mirror inthe element editor). I'd suggest
A— it matches KiCad's add-symbol key forpeople coming from there, and reads correctly in the source language
("Ajouter"). Low stakes either way, since
ShortcutManagermakes it a defaultrather than a commitment and it shows up in the Shortcuts preferences page for
free.
Questions
a behaviour change. I can default to insert with a preference to restore, or
put edit on
Alt+double-click. This is the only part of Phase 1 that is ajudgement call rather than plumbing, and I would rather settle it here than
in a PR.
QETAppsingleton?It follows the existing
collectionCache()pattern, but it touches loadingcode that several people have worked on.
organise their custom collections? I have designed it around the assumption
that users are already curating folders there. If that is not true in
practice, the whole config argument weakens and I would want to know before
building on it.
it is useful whether or not anything later happens. I am happy to open it as
a standalone PR and let the rest wait for feedback.
All line references are against master
7307a59c1.All reactions