Merge remote-tracking branch 'upstream/master' into wiring-manager

Conflicts resolved in 24 files. Notable decisions:

- ico/icon-themes.qrc: upstream's icon folder restructure kept; the 36
  cable icon entries re-added under the new qet/qet-dark path scheme
  (XML valid, every referenced file exists).
- Toolbar system: upstream's DiagramToolbarSettings now owns the
  toolbar filling. The cable tool is registered as
  diagrameditor.add_cable (generic group loop) and listed on the
  "diagram" toolbar right after the auto-break conductor action,
  separated by a divider, exactly like before the merge.
- Paste: the cable lines of a copy are handed to
  PasteNumberingImport::push() as extra commands, so paste + cable
  lines + the numbering question stay ONE undo step on both paste
  paths (DiagramView::paste and DiagramEventAddPaste::commit).
- PDF links: upstream's deterministic link sorting kept together with
  the cable cross-reference injector (injectLinkTo -> links list).
- Element renumbering: upstream's ElementAutoNumSchemeCommand::renumber
  replaces the old formula-based body of
  QETProject::renumberElementsBySchemeTitle; the cable numbering rule
  API (cableAutoNum, axis priority, rule name) is kept in full.
- Auto-numbering pages: upstream's scheme management kept, the Câbles
  tab added as index 4 (changeToCableTab), both entry points
  changeToCable() and changeToElement() kept side by side.
- SelectAutonumW: dirty tracking and the contextEdited signal moved
  into upstream's insertPartRow() row API, so single-rule mode, the
  rule-removable button and "confirm without change leaves the project
  alone" keep working.
- xrefpropertieswidget: upstream's offset clamping kept; the cable
  branch (Texte field, Police button, hidden display options) kept;
  the stack-overlapping checkbox is hidden for cables.

Verified after the merge: build green (515/515, no errors), ctest
85/86 (only the pre-existing headless tst_menubarkeyboard failure),
offscreen smoke exit 124.
This commit is contained in:
Kellermorph
2026-10-09 14:09:08 +02:00
1767 changed files with 194544 additions and 72846 deletions
+56 -27
View File
@@ -16,6 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "diagramview.h"
#include "autoNum/ui/pastenumberingimport.h"
#include "cellruler.h"
#include "lastusedstyle.h"
#include "utils/colordialogdoubleclick.h"
@@ -43,8 +44,10 @@
#include "utils/conductorcreator.h"
#include "undocommand/addgraphicsobjectcommand.h"
#include "diagram.h"
#include "foliogrid.h"
#include "diagramcontexttoolbar.h"
#include "diagramgestureoverlay.h"
#include "gesturesettings.h"
#include "shortcutbarsettings.h"
#include "shortcutmanager.h"
#include "ElementsCollection/xmlelementcollection.h"
@@ -203,6 +206,9 @@ DiagramView::DiagramView(Diagram *diagram, QWidget *parent) :
#ifdef Q_OS_MACOS
color_dialog -> setWindowFlags(Qt::Sheet);
#endif
// Qt's own dialog on every platform: the GTK one keeps its own
// recent-colours row and ignores the custom colours QET saves
color_dialog->setOption(QColorDialog::DontUseNativeDialog);
color_dialog->setCurrentColor(initial_properties.color);
ColorDialogDoubleClick::install(color_dialog);
@@ -506,8 +512,9 @@ void DiagramView::zoomFit()
*/
void DiagramView::zoomContent()
{
fitInView(m_diagram -> itemsBoundingRect(), Qt::KeepAspectRatio);
adjustGridToZoom();
const QRectF content = m_diagram->visibleItemsBoundingRect();
if (!content.isNull())
zoomToRect(content);
}
/**
@@ -638,16 +645,13 @@ void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) {
//One single step for the whole paste, cable lines included:
//undoing has to take back everything which came out of the
//clipboard in one go, and redoing has to put it all back.
QUndoCommand *command = nullptr;
if (content_pasted.count()) {
command = new PasteDiagramCommand(m_diagram, content_pasted);
}
QList<QUndoCommand *> cable_commands;
for (const CableCopy::Wired &line : std::as_const(wired)) {
if (!line.part) continue;
auto *added = new AddCableCommand(line.part->cable(), line.part.data(),
m_diagram, true, line.taken);
added->setText(QCoreApplication::translate("CableCopy", "Coller un câble"));
command = batchWith(command, added);
cable_commands << added;
}
//The copies end up selected, like everything else a paste
//just added, so the next Ctrl+V or Ctrl+D carries on from them
@@ -655,9 +659,12 @@ void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) {
if (line.part) line.part->setSelected(true);
}
if (command) {
m_diagram -> undoStack().push(command);
}
//Asks whether to import the numberings the copy brings, if the
//project has not got them; the paste itself and the cable lines
//travel inside the same step of the undo stack.
PasteNumberingImport::push(this, m_diagram, content_pasted,
PasteNumberingImport::copiedBy(document_xml),
cable_commands);
//The stack has just renewed the identity of a pasted
//conductor: the cores are pointed at the wires again and
//the cable fields written out once more, so the entries
@@ -726,10 +733,8 @@ void DiagramView::duplicate(const QPoint &stepOffset)
if (selection.isEmpty()) return;
QSettings settings;
const int x_grid = settings.value(QStringLiteral("diagrameditor/Xgrid"),
Diagram::xGrid).toInt();
const int y_grid = settings.value(QStringLiteral("diagrameditor/Ygrid"),
Diagram::yGrid).toInt();
const int x_grid = FolioGrid::step(settings.value(FolioGrid::x_key), Diagram::xGrid);
const int y_grid = FolioGrid::step(settings.value(FolioGrid::y_key), Diagram::yGrid);
const QPointF offset(stepOffset.x() * x_grid, stepOffset.y() * y_grid);
// Mirrors copy(), but does not touch the system clipboard: Ctrl+D
@@ -938,7 +943,8 @@ void DiagramView::mouseMoveEvent(QMouseEvent *e)
m_diagram->clearEventInterface();
m_swallow_native_menu = true;
}
m_gesture_overlay->showAt(m_gesture_origin, selectionCommands());
m_gesture_overlay->showAt(m_gesture_origin, gestureCommands(),
GestureSettings::directions());
}
if (m_gesture_overlay->isVisible()) {
m_gesture_overlay->setPointer(pos);
@@ -1125,6 +1131,28 @@ QList<QAction *> DiagramView::selectionCommands() const
return actions;
}
/**
@brief DiagramView::gestureCommands
@return the gesture ring's commands for the current selection, as this
window's actions. A list the user picked keeps its directions: a
command this window lacks leaves its direction empty (nullptr).
Otherwise the ring shows the shortcut bar's commands, in order.
*/
QList<QAction *> DiagramView::gestureCommands() const
{
QETDiagramEditor *qde = diagramEditor();
const auto context = ShortcutBarSettings::contextFor(m_diagram->selectedItems());
if (!qde || !GestureSettings::isCustom(context)) {
return selectionCommands();
}
QList<QAction *> actions;
for (const QString &id : GestureSettings::ids(context)) {
actions << (id.isEmpty() ? nullptr
: ShortcutManager::instance().action(id, qde));
}
return actions;
}
/**
@brief DiagramView::showContextToolbar
After a click that leaves something selected, show the shortcut bar's
@@ -1972,6 +2000,7 @@ QList<QAction *> DiagramView::contextMenuActions() const
list << qde->m_cut;
list << qde->m_copy;
list << m_multi_paste;
list << qde->m_paste_element_info;
list << m_separators.at(0);
list << m_create_template; // Add the create template action
//Disabled, and so left out below, unless a selected element
@@ -2173,8 +2202,8 @@ void DiagramView::contextMenuEvent(QContextMenuEvent *e)
@brief DiagramView::updateFolioReportMenu
Fill the "Renvoi de folio" submenu of the context menu with the folio
report elements this project already uses -- the ones in its embedded
collection -- or, when it has none yet, the coming and going arrows of
the common collection. An entry places its element where the context
collection -- and the coming and going arrows of the common collection,
each name listed once. An entry places its element where the context
menu was opened. Left empty, and so hidden, on a read-only diagram.
*/
void DiagramView::updateFolioReportMenu()
@@ -2188,9 +2217,9 @@ void DiagramView::updateFolioReportMenu()
QETProject *project = m_diagram->project();
XmlElementCollection *collection =
project ? project->embeddedElementCollection() : nullptr;
QSet<QString> names;
if (collection)
{
QSet<QString> names;
const QDomNodeList definitions =
collection->root().elementsByTagName(QStringLiteral("definition"));
for (int i = 0 ; i < definitions.count() ; ++i)
@@ -2213,16 +2242,16 @@ void DiagramView::updateFolioReportMenu()
}
}
if (locations.isEmpty())
//Always offer both standard arrows: placing one copies it into the
//embedded collection, and must not hide the other one.
for (const auto path : {
"common://10_electric/10_allpole/100_folio_referencing/01coming_arrow.elmt",
"common://10_electric/10_allpole/100_folio_referencing/02going_arrow.elmt"})
{
for (const auto path : {
"common://10_electric/10_allpole/100_folio_referencing/01coming_arrow.elmt",
"common://10_electric/10_allpole/100_folio_referencing/02going_arrow.elmt"})
{
const ElementsLocation location(QString::fromLatin1(path));
if (location.exist()) {
locations << location;
}
const ElementsLocation location(QString::fromLatin1(path));
if (location.exist() && !names.contains(location.name())) {
names.insert(location.name());
locations << location;
}
}