diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake
index c0daa3aca..6cd543f73 100644
--- a/cmake/qet_compilation_vars.cmake
+++ b/cmake/qet_compilation_vars.cmake
@@ -277,6 +277,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/autoNum/numerotationcontextcommands.h
${QET_DIR}/sources/autoNum/numerotationcontext.cpp
${QET_DIR}/sources/autoNum/numerotationcontext.h
+ ${QET_DIR}/sources/autoNum/renumberelementscommand.cpp
+ ${QET_DIR}/sources/autoNum/renumberelementscommand.h
${QET_DIR}/sources/autoNum/ui/autonumberingdockwidget.cpp
${QET_DIR}/sources/autoNum/ui/autonumberingdockwidget.h
${QET_DIR}/sources/autoNum/ui/autonumberingmanagementw.cpp
@@ -287,6 +289,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/autoNum/ui/formulaautonumberingw.h
${QET_DIR}/sources/autoNum/ui/numparteditorw.cpp
${QET_DIR}/sources/autoNum/ui/numparteditorw.h
+ ${QET_DIR}/sources/autoNum/ui/renumberelementsdialog.cpp
+ ${QET_DIR}/sources/autoNum/ui/renumberelementsdialog.h
${QET_DIR}/sources/autoNum/ui/selectautonumw.cpp
${QET_DIR}/sources/autoNum/ui/selectautonumw.h
diff --git a/sources/autoNum/renumberelementscommand.cpp b/sources/autoNum/renumberelementscommand.cpp
new file mode 100644
index 000000000..27f2c5912
--- /dev/null
+++ b/sources/autoNum/renumberelementscommand.cpp
@@ -0,0 +1,78 @@
+/*
+ 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 "renumberelementscommand.h"
+
+#include "../qetproject.h"
+#include "../qetgraphicsitem/element.h"
+
+RenumberElementsCommand::RenumberElementsCommand(
+ QETProject *project,
+ QVector changes,
+ QHash old_ctx,
+ QHash new_ctx,
+ const QString &text)
+ : QUndoCommand(text)
+ , project_(project)
+ , changes_(std::move(changes))
+ , old_ctx_(std::move(old_ctx))
+ , new_ctx_(std::move(new_ctx))
+{
+}
+
+void RenumberElementsCommand::undo()
+{
+ apply(false);
+}
+
+void RenumberElementsCommand::redo()
+{
+ // QUndoStack calls redo() once immediately after push(); keep standard behaviour.
+ if (first_redo_) {
+ first_redo_ = false;
+ }
+ apply(true);
+}
+
+void RenumberElementsCommand::apply(bool use_new)
+{
+ if (!project_) return;
+
+ // Restore project contexts
+ const auto &ctx = use_new ? new_ctx_ : old_ctx_;
+ for (auto it = ctx.constBegin(); it != ctx.constEnd(); ++it) {
+ project_->addElementAutoNum(it.key(), it.value());
+ }
+
+ // Apply per-element changes
+ for (const ElementChange &c : changes_) {
+ if (!c.element) continue;
+
+ const bool frozen = use_new ? c.new_frozen : c.old_frozen;
+ const auto &infos = use_new ? c.new_infos : c.old_infos;
+ const auto &seq = use_new ? c.new_seq : c.old_seq;
+
+ // Temporarily unfreeze so that label/infos update correctly.
+ const bool was_frozen = c.element->isFreezeLabel();
+ if (was_frozen) c.element->freezeLabel(false);
+
+ c.element->rSequenceStruct() = seq;
+ c.element->setElementInformations(infos);
+ c.element->freezeLabel(frozen);
+ }
+}
diff --git a/sources/autoNum/renumberelementscommand.h b/sources/autoNum/renumberelementscommand.h
new file mode 100644
index 000000000..4c3d1c871
--- /dev/null
+++ b/sources/autoNum/renumberelementscommand.h
@@ -0,0 +1,70 @@
+/*
+ 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 RENUMBERELEMENTSCOMMAND_H
+#define RENUMBERELEMENTSCOMMAND_H
+
+#include
+#include
+#include
+
+#include "../diagramcontext.h"
+#include "assignvariables.h" // defines autonum::sequentialNumbers
+
+class Element;
+class QETProject;
+
+/**
+ * @brief Undoable renumbering of element labels and sequence structs.
+ */
+class RenumberElementsCommand final : public QUndoCommand
+{
+public:
+ struct ElementChange
+ {
+ Element *element = nullptr;
+ DiagramContext old_infos;
+ DiagramContext new_infos;
+ autonum::sequentialNumbers old_seq;
+ autonum::sequentialNumbers new_seq;
+ bool old_frozen = false;
+ bool new_frozen = false;
+ };
+
+ RenumberElementsCommand(
+ QETProject *project,
+ QVector changes,
+ QHash old_ctx,
+ QHash new_ctx,
+ const QString &text);
+
+ void undo() override;
+ void redo() override;
+
+private:
+ void apply(bool use_new);
+
+private:
+ QETProject *project_ = nullptr;
+ QVector changes_;
+ QHash old_ctx_;
+ QHash new_ctx_;
+ bool first_redo_ = true;
+};
+
+#endif // RENUMBERELEMENTSCOMMAND_H
diff --git a/sources/autoNum/ui/autonumberingmanagementw.cpp b/sources/autoNum/ui/autonumberingmanagementw.cpp
index ba3e7f826..4e6499548 100644
--- a/sources/autoNum/ui/autonumberingmanagementw.cpp
+++ b/sources/autoNum/ui/autonumberingmanagementw.cpp
@@ -23,6 +23,7 @@
#include "formulaautonumberingw.h"
#include "numparteditorw.h"
#include "qdebug.h"
+#include "renumberelementsdialog.h"
#include "ui_autonumberingmanagementw.h"
#include "ui_formulaautonumberingw.h"
@@ -48,6 +49,8 @@ AutoNumberingManagementW::AutoNumberingManagementW(QETProject *project,
ui->m_selected_folios_le->setDisabled(true);
ui->m_selected_folios_le->setReadOnly(true);
ui->m_apply_project_rb->setChecked(true);
+ // Enabled only when project is in "Under Development" status and not read-only.
+ ui->m_renumber_elements_pb->setEnabled(ui->m_status_cb->currentIndex() == 0 && project_ && !project_->isReadOnly());
setProjectContext();
}
@@ -87,6 +90,7 @@ void AutoNumberingManagementW::on_m_status_cb_currentIndexChanged(int index)
ui->m_both_conductor_rb->setChecked(true);
ui->m_both_element_rb->setChecked(true);
ui->m_both_folio_rb->setChecked(true);
+ ui->m_renumber_elements_pb->setEnabled(true);
}
//Installing
else if (index == 1) {
@@ -96,15 +100,31 @@ void AutoNumberingManagementW::on_m_status_cb_currentIndexChanged(int index)
ui->m_new_conductor_rb->setChecked(true);
ui->m_new_element_rb->setChecked(true);
ui->m_new_folio_rb->setChecked(true);
+ ui->m_renumber_elements_pb->setEnabled(true);
}
//Built
else if (index == 2) {
ui->m_disable_conductor_rb->setChecked(true);
ui->m_disable_element_rb->setChecked(true);
ui->m_disable_folio_rb->setChecked(true);
+ ui->m_renumber_elements_pb->setEnabled(false);
}
}
+void AutoNumberingManagementW::on_m_renumber_elements_pb_clicked()
+{
+ if (!project_ || project_->isReadOnly()) return;
+ // Only allowed during "Under Development"
+ // if (ui->m_status_cb->currentIndex() != 1) return;
+
+ QStringList titles = project_->elementAutoNum().keys();
+ titles.sort(Qt::CaseInsensitive);
+ RenumberElementsDialog dlg(titles, this);
+ if (dlg.exec() != QDialog::Accepted) return;
+
+ project_->renumberElementsBySchemeTitle(dlg.selectedSchemeTitle());
+}
+
/**
@brief AutoNumberingManagementW::on_m_apply_folios_rb_clicked
Set From Folios Combobox
diff --git a/sources/autoNum/ui/autonumberingmanagementw.h b/sources/autoNum/ui/autonumberingmanagementw.h
index 5ecb6841a..c5893544e 100644
--- a/sources/autoNum/ui/autonumberingmanagementw.h
+++ b/sources/autoNum/ui/autonumberingmanagementw.h
@@ -50,6 +50,7 @@ class AutoNumberingManagementW : public QWidget
void on_m_from_folios_cb_currentIndexChanged(int);
void on_m_to_folios_cb_currentIndexChanged(int);
void on_m_status_cb_currentIndexChanged(int);
+ void on_m_renumber_elements_pb_clicked();
void on_m_apply_folios_rb_clicked();
void on_m_apply_project_rb_clicked();
void on_buttonBox_clicked(QAbstractButton *);
diff --git a/sources/autoNum/ui/autonumberingmanagementw.ui b/sources/autoNum/ui/autonumberingmanagementw.ui
index be70d22b6..7099bcef7 100644
--- a/sources/autoNum/ui/autonumberingmanagementw.ui
+++ b/sources/autoNum/ui/autonumberingmanagementw.ui
@@ -308,6 +308,13 @@
+ -
+
+
+ Renumber element(s)…
+
+
+
-
diff --git a/sources/autoNum/ui/renumberelementsdialog.cpp b/sources/autoNum/ui/renumberelementsdialog.cpp
new file mode 100644
index 000000000..a8c4c9dd1
--- /dev/null
+++ b/sources/autoNum/ui/renumberelementsdialog.cpp
@@ -0,0 +1,75 @@
+/*
+ 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 "renumberelementsdialog.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+RenumberElementsDialog::RenumberElementsDialog(const QStringList &scheme_titles, QWidget *parent)
+ : QDialog(parent)
+ , m_scheme_titles(scheme_titles)
+{
+ setWindowTitle(tr("Renumber element(s)"));
+ setModal(true);
+
+ auto *vl = new QVBoxLayout(this);
+
+ auto *scope = new QGroupBox(tr("Scope"), this);
+ auto *scope_l = new QVBoxLayout(scope);
+ m_all_rb = new QRadioButton(tr("All schemes"), scope);
+ m_one_rb = new QRadioButton(tr("One scheme"), scope);
+ scope_l->addWidget(m_all_rb);
+ scope_l->addWidget(m_one_rb);
+ vl->addWidget(scope);
+
+ auto *form = new QFormLayout();
+ m_combo = new QComboBox(this);
+ m_combo->addItems(m_scheme_titles);
+ form->addRow(new QLabel(tr("Scheme:"), this), m_combo);
+ vl->addLayout(form);
+
+ m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ connect(m_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ vl->addWidget(m_buttons);
+
+ m_all_rb->setChecked(true);
+ updateUi();
+
+ connect(m_all_rb, &QRadioButton::toggled, this, &RenumberElementsDialog::updateUi);
+ connect(m_one_rb, &QRadioButton::toggled, this, &RenumberElementsDialog::updateUi);
+}
+
+QString RenumberElementsDialog::selectedSchemeTitle() const
+{
+ if (m_all_rb && m_all_rb->isChecked()) return QString();
+ return m_combo ? m_combo->currentText() : QString();
+}
+
+void RenumberElementsDialog::updateUi()
+{
+ const bool one = m_one_rb && m_one_rb->isChecked();
+ if (m_combo) m_combo->setEnabled(one);
+}
diff --git a/sources/autoNum/ui/renumberelementsdialog.h b/sources/autoNum/ui/renumberelementsdialog.h
new file mode 100644
index 000000000..8a49fac93
--- /dev/null
+++ b/sources/autoNum/ui/renumberelementsdialog.h
@@ -0,0 +1,59 @@
+/*
+ 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 RENUMBERELEMENTSDIALOG_H
+#define RENUMBERELEMENTSDIALOG_H
+
+#include
+#include
+
+class QComboBox;
+class QRadioButton;
+class QDialogButtonBox;
+
+/**
+ * @brief Simple dialog to pick renumbering scope for elements.
+ *
+ * The user can choose between:
+ * - all element autonumbering schemes
+ * - one selected scheme title
+ */
+class RenumberElementsDialog final : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RenumberElementsDialog(const QStringList &scheme_titles, QWidget *parent = nullptr);
+
+ /**
+ * @return Empty string if "all" is selected, otherwise the chosen scheme title.
+ */
+ QString selectedSchemeTitle() const;
+
+private slots:
+ void updateUi();
+
+private:
+ QStringList m_scheme_titles;
+ QRadioButton *m_all_rb = nullptr;
+ QRadioButton *m_one_rb = nullptr;
+ QComboBox *m_combo = nullptr;
+ QDialogButtonBox *m_buttons = nullptr;
+};
+
+#endif // RENUMBERELEMENTSDIALOG_H
diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp
index d296ebf74..66f1c1b5b 100644
--- a/sources/qetproject.cpp
+++ b/sources/qetproject.cpp
@@ -22,7 +22,9 @@
#include "autoNum/assignvariables.h"
#include "autoNum/numerotationcontext.h"
#include "autoNum/numerotationcontextcommands.h"
+#include "autoNum/renumberelementscommand.h"
#include "diagram.h"
+#include "qetgraphicsitem/element.h"
#include "qetapp.h"
#include "qetmessagebox.h"
#include "qetresult.h"
@@ -40,7 +42,30 @@
#include
#include
#include
+
+namespace {
+
+/**
+ * @brief Reset numeric fields of a NumerotationContext so renumbering starts at 1.
+ * Keeps non-numeric parts (string/idfolio/folio/plant/locmach/elementline/elementcolumn/elementprefix) unchanged.
+ */
+NumerotationContext resetContextForRenumber(const NumerotationContext &tmpl)
+{
+ NumerotationContext out = tmpl;
+ for (int i = 0; i < out.size(); ++i) {
+ const QStringList parts = out.itemAt(i);
+ if (parts.isEmpty()) continue;
+ const QString type = parts.at(0);
+ if (out.keyIsNumber(type)) {
+ out.replaceValue(i, QStringLiteral("1"));
+ }
+ }
+ return out;
+}
+
+} // namespace
#include
+#include
#include
static int BACKUP_INTERVAL = 1200000; //interval in ms of backup = 20min
@@ -682,6 +707,109 @@ void QETProject::setCurrrentElementAutonum(QString autoNum) {
m_current_element_autonum = std::move(autoNum);
}
+/**
+ @brief QETProject::renumberElementsBySchemeTitle
+ Renumber existing elements by element autonumbering scheme title.
+
+ Elements do not store the scheme title; they store a "formula" (elementInformations["formula"]).
+ This method matches elements to schemes by comparing the stored formula with the formula derived
+ from each scheme's NumerotationContext.
+
+ If scheme_title is empty, all schemes are renumbered. Otherwise only that scheme is renumbered.
+ The operation is undoable.
+*/
+void QETProject::renumberElementsBySchemeTitle(const QString &scheme_title)
+{
+ if (!m_undo_stack) return;
+ if (isReadOnly()) return;
+
+ // Build map: scheme title -> canonical formula
+ QHash scheme_formula;
+ for (const QString &k : m_element_autonum.keys()) {
+ if (!scheme_title.isEmpty() && k != scheme_title) continue;
+ scheme_formula.insert(k, autonum::numerotationContextToFormula(m_element_autonum.value(k)));
+ }
+ if (scheme_formula.isEmpty()) return;
+
+ // Collect elements per scheme by formula match
+ QHash> by_key;
+ for (Diagram *d : diagrams()) {
+ if (!d) continue;
+ const auto items = d->items();
+ for (QGraphicsItem *it : items) {
+ auto *el = qgraphicsitem_cast(it);
+ if (!el) continue;
+ if (el->linkType() == Element::Slave || (el->linkType() & Element::AllReport))
+ continue;
+
+ const QString el_formula = el->elementInformations().value(QStringLiteral("formula")).toString();
+ if (el_formula.isEmpty()) continue;
+
+ QString matched_key;
+ for (auto itf = scheme_formula.constBegin(); itf != scheme_formula.constEnd(); ++itf) {
+ if (itf.value() == el_formula) { matched_key = itf.key(); break; }
+ }
+ if (matched_key.isEmpty()) continue;
+ by_key[matched_key].append(el);
+ }
+ }
+ if (by_key.isEmpty()) return;
+
+ QVector changes;
+ QHash old_ctx;
+ QHash new_ctx;
+
+ for (auto it = by_key.constBegin(); it != by_key.constEnd(); ++it) {
+ old_ctx.insert(it.key(), m_element_autonum.value(it.key()));
+ }
+
+ for (auto it = by_key.begin(); it != by_key.end(); ++it) {
+ const QString key = it.key();
+ auto &elements = it.value();
+ std::sort(elements.begin(), elements.end(), [](Element *a, Element *b){ return comparPos(a, b); });
+
+ NumerotationContext base_tmpl = m_element_autonum.value(key);
+ NumerotationContext nc = resetContextForRenumber(base_tmpl);
+ NumerotationContextCommands ncc(nc);
+
+ for (Element *el : elements) {
+ RenumberElementsCommand::ElementChange ch;
+ ch.element = el;
+ ch.old_infos = el->elementInformations();
+ ch.old_seq = el->sequenceStruct();
+ ch.old_frozen = el->isFreezeLabel();
+ ch.new_frozen = ch.old_frozen; // preserve frozen state
+
+ const QString formula = ch.old_infos.value(QStringLiteral("formula")).toString();
+ autonum::sequentialNumbers new_seq;
+ new_seq.clear();
+ autonum::setSequential(formula, new_seq, nc, el->diagram(), key);
+
+ DiagramContext new_infos = ch.old_infos;
+ new_infos.addValue(QStringLiteral("label"), autonum::AssignVariables::formulaToLabel(formula, new_seq, el->diagram(), el, nullptr));
+ ch.new_infos = new_infos;
+ ch.new_seq = new_seq;
+ changes.append(ch);
+
+ // advance
+ nc = ncc.next();
+ ncc = NumerotationContextCommands(nc);
+ }
+
+ new_ctx.insert(key, nc);
+ }
+
+ if (changes.isEmpty()) return;
+
+ auto *cmd = new RenumberElementsCommand(
+ this,
+ changes,
+ old_ctx,
+ new_ctx,
+ scheme_title.isEmpty() ? tr("Renumber elements") : tr("Renumber elements (%1)").arg(scheme_title));
+ m_undo_stack->push(cmd);
+}
+
/**
@brief QETProject::conductorAutoNumFormula
@param key : autonum title
diff --git a/sources/qetproject.h b/sources/qetproject.h
index 3817abad9..2c968f9d5 100644
--- a/sources/qetproject.h
+++ b/sources/qetproject.h
@@ -169,6 +169,20 @@ class QETProject : public QObject
QString elementCurrentAutoNum() const;
void setCurrrentElementAutonum(QString autoNum);
+ /**
+ * @brief Renumber existing elements by element autonumbering scheme.
+ *
+ * Elements do not store the scheme title but they store the corresponding formula.
+ * This operation matches elements to schemes by comparing the stored formula
+ * with the formula derived from the scheme's NumerotationContext.
+ *
+ * If @p scheme_title is empty, all schemes are renumbered.
+ * If @p scheme_title is non-empty, only that scheme is renumbered.
+ *
+ * The operation is undoable.
+ */
+ void renumberElementsBySchemeTitle(const QString &scheme_title = QString());
+
//Element
void freezeExistentElementLabel(bool freeze, int from, int to);
void freezeNewElementLabel(bool freeze, int from, int to);