mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-11 22:54:12 +02:00
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:
@@ -19,6 +19,11 @@
|
||||
|
||||
#include "../../diagram.h"
|
||||
#include "../../diagramview.h"
|
||||
#include "../../qetgraphicsitem/element.h"
|
||||
#include "../../qeticons.h"
|
||||
#include "../elementautonumschemecommand.h"
|
||||
#include "counterwarning.h"
|
||||
#include "renumberpreviewdialog.h"
|
||||
#include "../../qetapp.h"
|
||||
#include "../../shortcutmanager.h"
|
||||
#include "../../titleblockproperties.h"
|
||||
@@ -29,7 +34,10 @@
|
||||
#include "../../undocommand/changetitleblockcommand.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QSignalBlocker>
|
||||
#include <QSpinBox>
|
||||
|
||||
@@ -43,9 +51,127 @@ AutoNumberingDockWidget::AutoNumberingDockWidget(QWidget *parent) :
|
||||
ui(new Ui::AutoNumberingDockWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
//The element row gets a button to the left of its reset button
|
||||
//which gives the numbering shown to the selected elements
|
||||
QPushButton *reset = ui->m_element_reset_start_pb;
|
||||
ui->gridLayout->removeWidget(reset);
|
||||
auto *actions = new QWidget(this);
|
||||
auto *actions_layout = new QHBoxLayout(actions);
|
||||
actions_layout->setContentsMargins(0, 0, 0, 0);
|
||||
actions_layout->setSpacing(2);
|
||||
m_element_apply_pb = new QPushButton(QET::Icons::DialogOk, QString(), actions);
|
||||
m_element_apply_pb->setObjectName(QStringLiteral("m_element_apply_pb"));
|
||||
m_element_apply_pb->setMaximumWidth(24);
|
||||
m_element_apply_pb->setToolTip(tr("Appliquer cette numérotation aux éléments sélectionnés"));
|
||||
reset->setParent(actions);
|
||||
actions_layout->addWidget(m_element_apply_pb);
|
||||
actions_layout->addWidget(reset);
|
||||
ui->gridLayout->addWidget(actions, 3, 2);
|
||||
connect(m_element_apply_pb, &QPushButton::clicked,
|
||||
this, &AutoNumberingDockWidget::applyElementSchemeToSelection);
|
||||
connect(ui->m_element_cb, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
this, &AutoNumberingDockWidget::updateApplyEnabled);
|
||||
m_element_apply_pb->setEnabled(false);
|
||||
|
||||
this->setDisabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AutoNumberingDockWidget::applyElementSchemeToSelection
|
||||
Give the element numbering shown in the list to the elements selected
|
||||
in the current folio: each takes its formula and the next number, in
|
||||
folio and position order, and the counter moves on.
|
||||
|
||||
What would change is shown first. An element which holds another
|
||||
numbering, or whose label is frozen, is left as it is, unless the user
|
||||
asks to replace them too (a frozen one is then given back). One undo
|
||||
step.
|
||||
*/
|
||||
void AutoNumberingDockWidget::applyElementSchemeToSelection()
|
||||
{
|
||||
if (!m_project || m_project->isReadOnly()) {
|
||||
return;
|
||||
}
|
||||
const QString caption = tr("Appliquer la numérotation");
|
||||
const QString title = ui->m_element_cb->currentText();
|
||||
DiagramView *view = m_project_view ? m_project_view->currentDiagram() : nullptr;
|
||||
Diagram *diagram = view ? view->diagram() : nullptr;
|
||||
if (!diagram || !m_project->elementAutoNum().contains(title)) {
|
||||
QMessageBox::information(this, caption,
|
||||
tr("Choisissez une numérotation d'éléments du projet."));
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<Element *> selected;
|
||||
const auto items = diagram->selectedItems();
|
||||
for (QGraphicsItem *item : items) {
|
||||
if (auto *el = qgraphicsitem_cast<Element *>(item)) {
|
||||
selected << el;
|
||||
}
|
||||
}
|
||||
if (selected.isEmpty()) {
|
||||
QMessageBox::information(this, caption,
|
||||
tr("Sélectionnez d'abord des éléments dans le folio."));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto plan = ElementAutoNumSchemeCommand::assignPlan(m_project, title, selected);
|
||||
QVector<RenumberPreviewDialog::LeftAlone> left;
|
||||
for (Element *el : plan.frozen) {
|
||||
left.append({el, tr("(figé)")});
|
||||
}
|
||||
for (Element *el : plan.otherFormula) {
|
||||
left.append({el, tr("(autre numérotation)")});
|
||||
}
|
||||
const int replaceable = static_cast<int>(left.size());
|
||||
|
||||
auto *cmd = ElementAutoNumSchemeCommand::assign(m_project, title, selected, false);
|
||||
if (!cmd && !replaceable) {
|
||||
QMessageBox::information(
|
||||
this, caption,
|
||||
tr("Rien à appliquer : les éléments sélectionnés suivent déjà "
|
||||
"la numérotation « %1 », ou prennent leur nom d'un autre élément.").arg(title));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString intro = cmd
|
||||
? tr("%n élément(s) vont recevoir la numérotation « %1 », dans l'ordre des folios "
|
||||
"et des positions.", "", static_cast<int>(plan.todo.size())).arg(title)
|
||||
: tr("Aucun élément ne peut recevoir la numérotation « %1 » sans remplacer "
|
||||
"ce qu'il a.").arg(title);
|
||||
const auto answer = RenumberPreviewDialog::ask(
|
||||
this, caption, intro,
|
||||
cmd ? cmd->changes() : QVector<RenumberElementsCommand::ElementChange>(),
|
||||
left,
|
||||
replaceable
|
||||
? tr("Remplacer aussi les %n élément(s) laissés comme ils sont", "", replaceable)
|
||||
: QString());
|
||||
|
||||
if (answer == RenumberPreviewDialog::Answer::Cancel) {
|
||||
delete cmd;
|
||||
return;
|
||||
}
|
||||
int applied = cmd ? static_cast<int>(cmd->changes().size()) : 0;
|
||||
if (answer == RenumberPreviewDialog::Answer::GoAndReplace) {
|
||||
delete cmd;
|
||||
cmd = ElementAutoNumSchemeCommand::assign(m_project, title, selected, true);
|
||||
applied = cmd ? static_cast<int>(cmd->changes().size()) : 0;
|
||||
}
|
||||
if (cmd) {
|
||||
m_project->undoStack()->push(cmd);
|
||||
}
|
||||
|
||||
const int not_given = static_cast<int>(selected.size()) - applied;
|
||||
if (not_given > 0) {
|
||||
QMessageBox::information(
|
||||
this, caption,
|
||||
tr("%n élément(s) numérotés.", "", applied)
|
||||
+ QLatin1Char('\n')
|
||||
+ tr("%n élément(s) sélectionnés sont restés comme ils sont.", "", not_given));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AutoNumberingDockWidget::~AutoNumberingDockWidget
|
||||
Destructor
|
||||
@@ -117,6 +243,8 @@ void AutoNumberingDockWidget::setProject(QETProject *project,
|
||||
disconnect(m_project, &QETProject::conductorAutoNumRemoved, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
||||
disconnect(m_project, &QETProject::conductorAutoNumAdded, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
||||
disconnect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::setConductorActive);
|
||||
disconnect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::followSelectionOf);
|
||||
followSelectionOf(nullptr);
|
||||
|
||||
//Element Signals
|
||||
disconnect(m_project, &QETProject::elementAutoNumRemoved, this, &AutoNumberingDockWidget::elementAutoNumChanged);
|
||||
@@ -142,6 +270,8 @@ void AutoNumberingDockWidget::setProject(QETProject *project,
|
||||
connect(m_project, &QETProject::conductorAutoNumRemoved, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
||||
connect(m_project, &QETProject::conductorAutoNumAdded, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
||||
connect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::setConductorActive);
|
||||
connect(m_project_view, &ProjectView::diagramActivated, this, &AutoNumberingDockWidget::followSelectionOf);
|
||||
followSelectionOf(m_project_view->currentDiagram());
|
||||
|
||||
//Element Signals
|
||||
connect(m_project, &QETProject::elementAutoNumRemoved, this, &AutoNumberingDockWidget::elementAutoNumChanged);
|
||||
@@ -207,6 +337,56 @@ void AutoNumberingDockWidget::setContext()
|
||||
this->setActive();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AutoNumberingDockWidget::followSelectionOf
|
||||
Enable the apply button only while elements are selected in the folio
|
||||
shown: it gives a numbering to the selected elements, and with none
|
||||
selected there is nothing for it to do.
|
||||
@param view : the folio now shown, nullptr for none
|
||||
*/
|
||||
void AutoNumberingDockWidget::followSelectionOf(DiagramView *view)
|
||||
{
|
||||
Diagram *diagram = view ? view->diagram() : nullptr;
|
||||
if (m_selection_diagram) {
|
||||
disconnect(m_selection_diagram, &QGraphicsScene::selectionChanged,
|
||||
this, &AutoNumberingDockWidget::updateApplyEnabled);
|
||||
}
|
||||
m_selection_diagram = diagram;
|
||||
if (m_selection_diagram) {
|
||||
connect(m_selection_diagram, &QGraphicsScene::selectionChanged,
|
||||
this, &AutoNumberingDockWidget::updateApplyEnabled);
|
||||
}
|
||||
updateApplyEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AutoNumberingDockWidget::updateApplyEnabled
|
||||
The apply button needs a numbering to give and elements selected.
|
||||
*/
|
||||
void AutoNumberingDockWidget::updateApplyEnabled()
|
||||
{
|
||||
if (!m_element_apply_pb) {
|
||||
return;
|
||||
}
|
||||
bool elements_selected = false;
|
||||
if (m_selection_diagram) {
|
||||
const auto items = m_selection_diagram->selectedItems();
|
||||
for (QGraphicsItem *item : items) {
|
||||
if (qgraphicsitem_cast<Element *>(item)) {
|
||||
elements_selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_element_apply_pb->setEnabled(
|
||||
elements_selected && m_project && !m_project->isReadOnly()
|
||||
&& ui->m_element_cb->count() > 0);
|
||||
m_element_apply_pb->setToolTip(
|
||||
elements_selected
|
||||
? tr("Appliquer cette numérotation aux éléments sélectionnés")
|
||||
: tr("Sélectionnez d'abord des éléments dans le folio"));
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AutoNumberingDockWidget::setConductorActive
|
||||
@param dv: activated diagramview
|
||||
@@ -539,6 +719,12 @@ void AutoNumberingDockWidget::applyValueField(QComboBox *combo_box, QLineEdit *l
|
||||
}
|
||||
|
||||
context.replaceValue(index, typed);
|
||||
//An element counter put back on numbers in use: ask first
|
||||
if (category == AutoNumCategory::Element
|
||||
&& !CounterWarning::confirm(this, m_project, combo_box->currentText(), context)) {
|
||||
refreshRow(category);
|
||||
return;
|
||||
}
|
||||
storeContext(combo_box, category, context);
|
||||
refreshRow(category);
|
||||
}
|
||||
@@ -684,6 +870,12 @@ void AutoNumberingDockWidget::resetAutoNum(QComboBox *combo_box, AutoNumCategory
|
||||
context.replaceValue(i, QStringLiteral("a"));
|
||||
}
|
||||
|
||||
//Back to the first number, over numbers in use: ask first
|
||||
if (category == AutoNumCategory::Element
|
||||
&& !CounterWarning::confirm(this, m_project, combo_box->currentText(), context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
storeContext(combo_box, category, context);
|
||||
refreshRow(category);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include "../../qetproject.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QPointer>
|
||||
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
class QSpinBox;
|
||||
|
||||
namespace Ui {
|
||||
@@ -58,6 +60,9 @@ class AutoNumberingDockWidget : public QDockWidget
|
||||
void refreshValueFields();
|
||||
|
||||
void on_m_configure_pb_clicked();
|
||||
void applyElementSchemeToSelection();
|
||||
void updateApplyEnabled();
|
||||
void followSelectionOf(DiagramView *view);
|
||||
|
||||
void on_m_conductor_reset_start_pb_clicked();
|
||||
void on_m_element_reset_start_pb_clicked();
|
||||
@@ -126,6 +131,8 @@ class AutoNumberingDockWidget : public QDockWidget
|
||||
/// this replaces refreshValueField() at each of them.
|
||||
void refreshRow(AutoNumCategory category);
|
||||
|
||||
QPushButton *m_element_apply_pb = nullptr;
|
||||
QPointer<Diagram> m_selection_diagram; ///< the folio whose selection enables the apply button
|
||||
Ui::AutoNumberingDockWidget *ui;
|
||||
QETProject* m_project = nullptr;
|
||||
ProjectView* m_project_view = nullptr;
|
||||
|
||||
@@ -73,8 +73,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/view-refresh.png</normaloff>:/ico/16x16/view-refresh.png</iconset>
|
||||
<iconset theme="view-refresh"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -161,8 +160,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/view-refresh.png</normaloff>:/ico/16x16/view-refresh.png</iconset>
|
||||
<iconset theme="view-refresh"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -238,8 +236,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="view-refresh" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/view-refresh.png</normaloff>:/ico/16x16/view-refresh.png</iconset>
|
||||
<iconset theme="view-refresh"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -319,8 +316,7 @@
|
||||
<string>Configurer</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="configure" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/configure.png</normaloff>:/ico/16x16/configure.png</iconset>
|
||||
<iconset theme="configure"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "autonumberingmanagementw.h"
|
||||
#include "../elementautonumschemecommand.h"
|
||||
#include "renumberpreviewdialog.h"
|
||||
|
||||
#include "../../diagram.h"
|
||||
#include "../../qetgraphicsitem/element.h"
|
||||
#include "../../qetproject.h"
|
||||
#include "../numerotationcontextcommands.h"
|
||||
#include "formulaautonumberingw.h"
|
||||
@@ -122,7 +125,42 @@ void AutoNumberingManagementW::on_m_renumber_elements_pb_clicked()
|
||||
RenumberElementsDialog dlg(titles, this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
|
||||
project_->renumberElementsBySchemeTitle(dlg.selectedSchemeTitle());
|
||||
const QString title = dlg.selectedSchemeTitle();
|
||||
QVector<Element *> frozen;
|
||||
auto *cmd = ElementAutoNumSchemeCommand::renumber(
|
||||
project_, title, &frozen,
|
||||
title.isEmpty() ? tr("Renuméroter les éléments")
|
||||
: tr("Renuméroter les éléments (%1)").arg(title));
|
||||
if (!cmd)
|
||||
{
|
||||
QMessageBox::information(
|
||||
this, tr("Renuméroter les éléments"),
|
||||
frozen.isEmpty()
|
||||
? tr("Aucun élément ne suit cette numérotation.")
|
||||
: tr("Les %n élément(s) qui suivent cette numérotation ont un nom "
|
||||
"figé : rien n'est renuméroté.", "", frozen.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
const int renumbered = static_cast<int>(cmd->changes().size());
|
||||
const int changed = RenumberPreviewDialog::changedLabelCount(cmd->changes());
|
||||
if (!RenumberPreviewDialog::confirm(
|
||||
this, tr("Renuméroter les éléments"),
|
||||
tr("%n élément(s) vont être renumérotés, à partir du premier numéro, "
|
||||
"dans l'ordre des folios et des positions.", "", renumbered),
|
||||
cmd->changes(), frozen)) {
|
||||
delete cmd;
|
||||
return;
|
||||
}
|
||||
project_->undoStack()->push(cmd);
|
||||
|
||||
QString summary = tr("%n élément(s) renumérotés, dont %1 avec un nouveau nom.", "", renumbered)
|
||||
.arg(changed);
|
||||
if (!frozen.isEmpty()) {
|
||||
summary += QLatin1Char('\n') + tr("%n élément(s) au nom figé n'ont pas été touchés, "
|
||||
"et leur numéro n'a pas été redonné.", "", frozen.size());
|
||||
}
|
||||
QMessageBox::information(this, tr("Renuméroter les éléments"), summary);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "counterwarning.h"
|
||||
|
||||
#include "../elementautonumschemecommand.h"
|
||||
#include "../../qetmessagebox.h"
|
||||
|
||||
/**
|
||||
@brief CounterWarning::confirm
|
||||
@param title : the element numbering
|
||||
@param proposed : its definition, with the counter to give it
|
||||
@return true if the counter meets no number in use, or the user goes
|
||||
on; false if the user gives up (and, with nobody to ask, always)
|
||||
*/
|
||||
bool CounterWarning::confirm(QWidget *parent,
|
||||
const QETProject *project,
|
||||
const QString &title,
|
||||
const NumerotationContext &proposed)
|
||||
{
|
||||
const auto conflict = ElementAutoNumSchemeCommand::counterConflict(project, title, proposed);
|
||||
if (!conflict) {
|
||||
return true;
|
||||
}
|
||||
const auto answer = QET::QetMessageBox::question(
|
||||
parent,
|
||||
tr("Compteur de la numérotation"),
|
||||
tr("Le prochain numéro serait %1, mais %n élément(s) de la numérotation « %2 » "
|
||||
"ont déjà un numéro égal ou supérieur (jusqu'à %3).", "", conflict->count)
|
||||
.arg(conflict->counter).arg(title).arg(conflict->highest)
|
||||
+ tr("\nLes nouveaux éléments sauteront les numéros déjà pris : ils ne recevront "
|
||||
"pas forcément les numéros à partir de %1.\n\nContinuer ?").arg(conflict->counter),
|
||||
QMessageBox::Yes | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel);
|
||||
return answer == QMessageBox::Yes;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef COUNTERWARNING_H
|
||||
#define COUNTERWARNING_H
|
||||
|
||||
#include "../numerotationcontext.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
class QETProject;
|
||||
class QWidget;
|
||||
|
||||
/**
|
||||
@brief The CounterWarning class
|
||||
Asks before the counter of an element numbering is set to a number which
|
||||
elements of it have already: the next elements skip the numbers in use,
|
||||
so the next number is not the one asked for. The user may go on or give
|
||||
up.
|
||||
*/
|
||||
class CounterWarning
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(CounterWarning)
|
||||
|
||||
public:
|
||||
static bool confirm(QWidget *parent,
|
||||
const QETProject *project,
|
||||
const QString &title,
|
||||
const NumerotationContext &proposed);
|
||||
};
|
||||
|
||||
#endif // COUNTERWARNING_H
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "pastenumberingimport.h"
|
||||
|
||||
#include "../../diagram.h"
|
||||
#include "../../diagramcommands.h"
|
||||
#include "../../qetmessagebox.h"
|
||||
#include "../../qetproject.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
/// @return the numberings a copy carries, which pasted elements follow
|
||||
QList<ElementAutoNumSchemeCommand::Scheme> PasteNumberingImport::copiedBy(const QDomDocument &clipboard)
|
||||
{
|
||||
return ElementAutoNumSchemeCommand::copiedSchemes(clipboard.documentElement());
|
||||
}
|
||||
|
||||
/**
|
||||
@brief PasteNumberingImport::push
|
||||
Push the paste of @p content on the undo stack of @p diagram, after
|
||||
asking whether to import the numberings of @p copied which the pasted
|
||||
elements follow and the project does not have.
|
||||
@param parent : parent of the question
|
||||
@param copied : the numberings the copy carries
|
||||
@param extra : commands the copy brings beside the paste itself
|
||||
(the cable lines of a fragment, for example); they are pushed inside
|
||||
the same macro, so one Ctrl+Z undoes all of it at once.
|
||||
*/
|
||||
void PasteNumberingImport::push(QWidget *parent,
|
||||
Diagram *diagram,
|
||||
const DiagramContent &content,
|
||||
const QList<ElementAutoNumSchemeCommand::Scheme> &copied,
|
||||
const QList<QUndoCommand *> &extra)
|
||||
{
|
||||
QETProject *project = diagram->project();
|
||||
auto *paste = new PasteDiagramCommand(diagram, content);
|
||||
|
||||
//The paste and the commands beside it are one step: only the
|
||||
//macros really need more than the single push.
|
||||
const auto push_all = [&]() {
|
||||
if (extra.isEmpty()) {
|
||||
diagram->undoStack().push(paste);
|
||||
return;
|
||||
}
|
||||
diagram->undoStack().beginMacro(paste->text());
|
||||
diagram->undoStack().push(paste);
|
||||
for (QUndoCommand *cmd : extra) {
|
||||
diagram->undoStack().push(cmd);
|
||||
}
|
||||
diagram->undoStack().endMacro();
|
||||
};
|
||||
|
||||
QList<ElementAutoNumSchemeCommand::Scheme> missing;
|
||||
if (project && !copied.isEmpty()
|
||||
&& QSettings().value("diagramcommands/autonumber-pasted-elements", true).toBool()) {
|
||||
missing = ElementAutoNumSchemeCommand::missingForPaste(project, copied, content.m_elements);
|
||||
}
|
||||
if (missing.isEmpty()) {
|
||||
push_all();
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList names;
|
||||
for (const auto &scheme : std::as_const(missing)) {
|
||||
names << QStringLiteral("« %1 »").arg(scheme.title);
|
||||
}
|
||||
const auto answer = QET::QetMessageBox::question(
|
||||
parent,
|
||||
tr("Numérotation absente de ce projet"),
|
||||
tr("Les éléments collés suivent %n numérotation(s) qui n'existe(nt) pas dans ce projet : %1.\n\n"
|
||||
"Les importer ? Les éléments recevront alors les prochains numéros, à partir de 1. "
|
||||
"Sinon ils seront collés sans numérotation.", "", static_cast<int>(missing.size()))
|
||||
.arg(names.join(QStringLiteral(", "))),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::Yes);
|
||||
if (answer != QMessageBox::Yes) {
|
||||
push_all();
|
||||
return;
|
||||
}
|
||||
|
||||
diagram->undoStack().beginMacro(paste->text());
|
||||
for (const auto &scheme : std::as_const(missing))
|
||||
{
|
||||
//Under its own name, or one which is free here
|
||||
QString title = scheme.title;
|
||||
for (int n = 2 ; !project->elementAutoNumNameClash(title).isEmpty() ; ++n) {
|
||||
title = QStringLiteral("%1 (%2)").arg(scheme.title).arg(n);
|
||||
}
|
||||
if (auto *cmd = ElementAutoNumSchemeCommand::create(
|
||||
project, title,
|
||||
ElementAutoNumSchemeCommand::resetForRenumber(scheme.context),
|
||||
scheme.id, false)) {
|
||||
diagram->undoStack().push(cmd);
|
||||
}
|
||||
}
|
||||
diagram->undoStack().push(paste);
|
||||
for (QUndoCommand *cmd : extra) {
|
||||
diagram->undoStack().push(cmd);
|
||||
}
|
||||
diagram->undoStack().endMacro();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PASTENUMBERINGIMPORT_H
|
||||
#define PASTENUMBERINGIMPORT_H
|
||||
|
||||
#include "../elementautonumschemecommand.h"
|
||||
#include "../../diagramcontent.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QUndoCommand>
|
||||
|
||||
class Diagram;
|
||||
class QWidget;
|
||||
|
||||
/**
|
||||
@brief The PasteNumberingImport class
|
||||
Pastes elements copied from another project, which may follow element
|
||||
numberings this project does not have.
|
||||
|
||||
Such an element would be left with a formula which names no numbering
|
||||
here, and with a label nothing explains. So the user is asked, once
|
||||
for all the numberings missing, whether to import them. Imported, they
|
||||
number the pasted elements from their first number (a number of the other
|
||||
project means nothing here); not imported, the elements are pasted
|
||||
without a numbering.
|
||||
|
||||
The import and the paste are one undo step.
|
||||
|
||||
A paste which brings more than itself (the cable lines of the copy,
|
||||
for instance, which are no part of a DiagramContent) hands those
|
||||
commands over through @p extra: they are pushed inside the very
|
||||
same macro, so one Ctrl+Z still takes the whole of it back.
|
||||
*/
|
||||
class PasteNumberingImport
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(PasteNumberingImport)
|
||||
|
||||
public:
|
||||
static void push(QWidget *parent,
|
||||
Diagram *diagram,
|
||||
const DiagramContent &content,
|
||||
const QList<ElementAutoNumSchemeCommand::Scheme> &copied,
|
||||
const QList<QUndoCommand *> &extra = QList<QUndoCommand *>());
|
||||
|
||||
static QList<ElementAutoNumSchemeCommand::Scheme> copiedBy(const QDomDocument &clipboard);
|
||||
};
|
||||
|
||||
#endif // PASTENUMBERINGIMPORT_H
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "renumberpreviewdialog.h"
|
||||
|
||||
#include "../../diagram.h"
|
||||
#include "../../qetgraphicsitem/element.h"
|
||||
#include "../../qetinformation.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFont>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QTableWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace {
|
||||
QString labelOf(const DiagramContext &info)
|
||||
{
|
||||
return info.value(QETInformation::ELMT_LABEL).toString();
|
||||
}
|
||||
|
||||
QString folioOf(const Element *element)
|
||||
{
|
||||
return element && element->diagram()
|
||||
? QString::number(element->diagram()->folioIndex() + 1)
|
||||
: QString();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
@brief RenumberPreviewDialog::changedLabelCount
|
||||
@return how many of @p changes give their element another label
|
||||
*/
|
||||
int RenumberPreviewDialog::changedLabelCount(
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes)
|
||||
{
|
||||
int count = 0;
|
||||
for (const auto &change : changes) {
|
||||
if (labelOf(change.old_infos) != labelOf(change.new_infos)) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief RenumberPreviewDialog::ask
|
||||
@param intro : text above the list
|
||||
@param changes : what the operation would do to elements
|
||||
@param left_alone : the elements it leaves as they are, each with the
|
||||
reason shown in place of its new name
|
||||
@param replace_text : when not empty, a third button of that text
|
||||
which goes on and also replaces the elements left alone
|
||||
@return what the user chose
|
||||
*/
|
||||
RenumberPreviewDialog::Answer RenumberPreviewDialog::ask(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &intro,
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes,
|
||||
const QVector<LeftAlone> &left_alone,
|
||||
const QString &replace_text)
|
||||
{
|
||||
QDialog dialog(parent);
|
||||
dialog.setWindowTitle(title);
|
||||
dialog.resize(640, 460);
|
||||
auto *layout = new QVBoxLayout(&dialog);
|
||||
|
||||
const int changed = changedLabelCount(changes);
|
||||
QString text = intro;
|
||||
if (changes.size() > changed) {
|
||||
text += QLatin1Char('\n') + tr("%n élément(s) gardent le nom qu'ils ont.", "", changes.size() - changed);
|
||||
}
|
||||
if (!left_alone.isEmpty()) {
|
||||
text += QLatin1Char('\n') + tr("%n élément(s) restent comme ils sont.", "", left_alone.size());
|
||||
}
|
||||
auto *intro_label = new QLabel(text, &dialog);
|
||||
intro_label->setWordWrap(true);
|
||||
layout->addWidget(intro_label);
|
||||
|
||||
auto *table = new QTableWidget(&dialog);
|
||||
table->setColumnCount(4);
|
||||
table->setHorizontalHeaderLabels({tr("Folio"), tr("Élément"), tr("Nom actuel"), tr("Nouveau nom")});
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
table->verticalHeader()->setVisible(false);
|
||||
table->horizontalHeader()->setStretchLastSection(true);
|
||||
table->setAlternatingRowColors(true);
|
||||
|
||||
const auto add_row = [table](const QStringList &cells, bool grey) {
|
||||
const int row = table->rowCount();
|
||||
table->insertRow(row);
|
||||
for (int column = 0 ; column < cells.size() ; ++column) {
|
||||
auto *item = new QTableWidgetItem(cells.at(column));
|
||||
if (grey) {
|
||||
QFont font = item->font();
|
||||
font.setItalic(true);
|
||||
item->setFont(font);
|
||||
item->setForeground(QBrush(Qt::gray));
|
||||
}
|
||||
table->setItem(row, column, item);
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto &change : changes) {
|
||||
const QString before = labelOf(change.old_infos);
|
||||
const QString after = labelOf(change.new_infos);
|
||||
if (before != after) {
|
||||
add_row({folioOf(change.element),
|
||||
change.element ? change.element->name() : QString(),
|
||||
before, after}, false);
|
||||
}
|
||||
}
|
||||
for (const LeftAlone &left : left_alone) {
|
||||
if (left.element) {
|
||||
add_row({folioOf(left.element), left.element->name(),
|
||||
labelOf(left.element->elementInformations()), left.note}, true);
|
||||
}
|
||||
}
|
||||
table->resizeColumnsToContents();
|
||||
layout->addWidget(table, 1);
|
||||
|
||||
//With no label to change, OK would do nothing: only Cancel (and, where
|
||||
//there is one, the button which replaces what is left alone) is offered
|
||||
const bool something_to_do = !changes.isEmpty();
|
||||
auto *buttons = new QDialogButtonBox(
|
||||
something_to_do ? (QDialogButtonBox::Ok | QDialogButtonBox::Cancel)
|
||||
: QDialogButtonBox::Cancel, &dialog);
|
||||
Answer answer = Answer::Cancel;
|
||||
QPushButton *replace = nullptr;
|
||||
if (!replace_text.isEmpty()) {
|
||||
replace = buttons->addButton(replace_text, QDialogButtonBox::ActionRole);
|
||||
}
|
||||
QObject::connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||
QObject::connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||
if (replace) {
|
||||
QObject::connect(replace, &QPushButton::clicked, &dialog, [&]() {
|
||||
answer = Answer::GoAndReplace;
|
||||
dialog.accept();
|
||||
});
|
||||
}
|
||||
layout->addWidget(buttons);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted && answer != Answer::GoAndReplace) {
|
||||
answer = Answer::Go;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief RenumberPreviewDialog::confirm
|
||||
@param intro : text above the list
|
||||
@param changes : what the operation would do to elements
|
||||
@param frozen : the elements it leaves as they are, a frozen label
|
||||
@return true if the user agrees to go on
|
||||
*/
|
||||
bool RenumberPreviewDialog::confirm(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &intro,
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes,
|
||||
const QVector<Element *> &frozen)
|
||||
{
|
||||
QVector<LeftAlone> left;
|
||||
for (Element *el : frozen) {
|
||||
left.append({el, tr("(figé)")});
|
||||
}
|
||||
return ask(parent, title, intro, changes, left) == Answer::Go;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef RENUMBERPREVIEWDIALOG_H
|
||||
#define RENUMBERPREVIEWDIALOG_H
|
||||
|
||||
#include "../renumberelementscommand.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QVector>
|
||||
|
||||
class Element;
|
||||
class QWidget;
|
||||
|
||||
/**
|
||||
@brief The RenumberPreviewDialog class
|
||||
Shows what a numbering operation is about to do to the labels of
|
||||
elements -- each changed element with its label now and the one it
|
||||
would get -- and the elements with a frozen label it leaves as they are,
|
||||
and asks to go on or not. Nothing is changed by the dialog itself.
|
||||
*/
|
||||
class RenumberPreviewDialog
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(RenumberPreviewDialog)
|
||||
|
||||
public:
|
||||
/// An element an operation leaves as it is, and why
|
||||
struct LeftAlone
|
||||
{
|
||||
Element *element = nullptr;
|
||||
QString note;
|
||||
};
|
||||
enum class Answer { Cancel, Go, GoAndReplace };
|
||||
|
||||
static Answer ask(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &intro,
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes,
|
||||
const QVector<LeftAlone> &left_alone,
|
||||
const QString &replace_text = QString());
|
||||
|
||||
static bool confirm(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &intro,
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes,
|
||||
const QVector<Element *> &frozen);
|
||||
|
||||
static int changedLabelCount(
|
||||
const QVector<RenumberElementsCommand::ElementChange> &changes);
|
||||
};
|
||||
|
||||
#endif // RENUMBERPREVIEWDIALOG_H
|
||||
@@ -18,14 +18,17 @@
|
||||
#include "selectautonumw.h"
|
||||
|
||||
#include "../assignvariables.h"
|
||||
#include "../numerotationcontextcommands.h"
|
||||
#include "formulaautonumberingw.h"
|
||||
#include "numparteditorw.h"
|
||||
#include "ui_formulaautonumberingw.h"
|
||||
#include "ui_selectautonumw.h"
|
||||
|
||||
#include "../../qeticons.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QToolButton>
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::SelectAutonumW
|
||||
@@ -40,6 +43,24 @@ SelectAutonumW::SelectAutonumW(int type, QWidget *parent) :
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->m_comboBox->lineEdit()->setClearButtonEnabled(true);
|
||||
|
||||
//The add button goes under the last part, at the left; each part
|
||||
//has its own remove and move buttons at its right. The one remove
|
||||
//button above the parts, which could only remove the last one, is
|
||||
//not needed any more.
|
||||
ui->remove_button->hide();
|
||||
ui->horizontalLayout->removeWidget(ui->add_button);
|
||||
m_add_row = new QWidget(this);
|
||||
auto *add_layout = new QHBoxLayout(m_add_row);
|
||||
add_layout->setContentsMargins(0, 0, 0, 0);
|
||||
ui->add_button->setParent(m_add_row);
|
||||
add_layout->addWidget(ui->add_button);
|
||||
add_layout->addStretch();
|
||||
ui->editor_layout->addWidget(m_add_row);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->setText(tr("Annuler"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->setToolTip(
|
||||
tr("Revenir à la définition enregistrée"));
|
||||
|
||||
if (m_edited_type == 0)
|
||||
{
|
||||
m_feaw = new FormulaAutonumberingW();
|
||||
@@ -104,35 +125,132 @@ void SelectAutonumW::setContext(const NumerotationContext &context)
|
||||
{
|
||||
m_context = context;
|
||||
|
||||
qDeleteAll(num_part_list_);
|
||||
num_part_list_.clear();
|
||||
clearPartRows();
|
||||
|
||||
if (m_context.size() == 0) { //@context contain nothing, build a default numPartEditor
|
||||
on_add_button_clicked();
|
||||
insertPartRow(new NumPartEditorW(m_edited_type, this));
|
||||
}
|
||||
else {
|
||||
for (int i=0; i<m_context.size(); ++i) { //build with the content of @context
|
||||
NumPartEditorW *part= new NumPartEditorW(m_context, i, m_edited_type, this);
|
||||
connect(part, &NumPartEditorW::changed, this, [this]() {
|
||||
m_dirty = true;
|
||||
applyEnable();
|
||||
emit contextEdited();
|
||||
});
|
||||
num_part_list_ << part;
|
||||
ui -> editor_layout -> addWidget(part);
|
||||
insertPartRow(new NumPartEditorW(m_context, i, m_edited_type, this));
|
||||
}
|
||||
}
|
||||
|
||||
num_part_list_.size() == 1 ?
|
||||
ui -> remove_button -> setDisabled(true):
|
||||
ui -> remove_button -> setEnabled (true);
|
||||
|
||||
updatePartButtons();
|
||||
applyEnable(false);
|
||||
//Everything the rule held before is read now, so nothing of it
|
||||
//is left to write: what is on show is what there is.
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::insertPartRow
|
||||
Show @p part as the last part of the definition, with the buttons which
|
||||
remove it and move it up or down at its right.
|
||||
*/
|
||||
void SelectAutonumW::insertPartRow(NumPartEditorW *part)
|
||||
{
|
||||
connect(part, &NumPartEditorW::changed, this, [this]() {
|
||||
m_dirty = true;
|
||||
applyEnable();
|
||||
emit contextEdited();
|
||||
});
|
||||
|
||||
PartRow r;
|
||||
r.part = part;
|
||||
r.row = new QWidget(this);
|
||||
auto *layout = new QHBoxLayout(r.row);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(2);
|
||||
part->setParent(r.row);
|
||||
layout->addWidget(part, 1);
|
||||
|
||||
const auto make_button = [&](const QIcon &icon, const QString &tip) {
|
||||
auto *button = new QToolButton(r.row);
|
||||
button->setIcon(icon);
|
||||
button->setToolTip(tip);
|
||||
button->setAutoRaise(true);
|
||||
layout->addWidget(button);
|
||||
return button;
|
||||
};
|
||||
r.up = make_button(QET::Icons::GoUp, tr("Monter cette variable"));
|
||||
r.down = make_button(QET::Icons::GoDown, tr("Descendre cette variable"));
|
||||
r.remove = make_button(QET::Icons::EditDelete, tr("Supprimer cette variable"));
|
||||
QWidget *row = r.row;
|
||||
connect(r.up, &QToolButton::clicked, this, [this, row]() { movePartRow(row, -1); });
|
||||
connect(r.down, &QToolButton::clicked, this, [this, row]() { movePartRow(row, +1); });
|
||||
connect(r.remove, &QToolButton::clicked, this, [this, row]() { removePartRow(row); });
|
||||
|
||||
m_rows << r;
|
||||
num_part_list_ << part;
|
||||
//Before the add button, which stays under the last part
|
||||
ui->editor_layout->insertWidget(ui->editor_layout->count() - 1, r.row);
|
||||
updatePartButtons();
|
||||
}
|
||||
|
||||
/// Take away every part of the definition shown
|
||||
void SelectAutonumW::clearPartRows()
|
||||
{
|
||||
for (const PartRow &r : std::as_const(m_rows)) {
|
||||
delete r.row; //with the part, which it holds
|
||||
}
|
||||
m_rows.clear();
|
||||
num_part_list_.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::updatePartButtons
|
||||
The first part cannot move up, the last cannot move down, and the only
|
||||
one cannot be removed: those buttons are greyed out.
|
||||
*/
|
||||
void SelectAutonumW::updatePartButtons()
|
||||
{
|
||||
for (int i = 0 ; i < m_rows.size() ; ++i) {
|
||||
m_rows.at(i).up->setEnabled(i > 0);
|
||||
m_rows.at(i).down->setEnabled(i < m_rows.size() - 1);
|
||||
m_rows.at(i).remove->setEnabled(m_rows.size() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the part shown in @p row; the definition keeps at least one
|
||||
void SelectAutonumW::removePartRow(QWidget *row)
|
||||
{
|
||||
if (m_rows.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0 ; i < m_rows.size() ; ++i) {
|
||||
if (m_rows.at(i).row == row) {
|
||||
const PartRow r = m_rows.takeAt(i);
|
||||
num_part_list_.removeAll(r.part);
|
||||
delete r.row; //with the part, which it holds
|
||||
break;
|
||||
}
|
||||
}
|
||||
updatePartButtons();
|
||||
applyEnable();
|
||||
}
|
||||
|
||||
/// Move the part shown in @p row up (-1) or down (+1)
|
||||
void SelectAutonumW::movePartRow(QWidget *row, int step)
|
||||
{
|
||||
for (int i = 0 ; i < m_rows.size() ; ++i) {
|
||||
if (m_rows.at(i).row != row) {
|
||||
continue;
|
||||
}
|
||||
const int to = i + step;
|
||||
if (to < 0 || to >= m_rows.size()) {
|
||||
return;
|
||||
}
|
||||
m_rows.swapItemsAt(i, to);
|
||||
num_part_list_.swapItemsAt(i, to);
|
||||
ui->editor_layout->removeWidget(row);
|
||||
ui->editor_layout->insertWidget(1 + to, row); //after the header of the columns
|
||||
break;
|
||||
}
|
||||
updatePartButtons();
|
||||
applyEnable();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::toNumContext
|
||||
@return the content to num_part_list to NumerotationContext
|
||||
@@ -151,17 +269,10 @@ NumerotationContext SelectAutonumW::toNumContext() const
|
||||
*/
|
||||
void SelectAutonumW::on_add_button_clicked()
|
||||
{
|
||||
applyEnable(false);
|
||||
insertPartRow(new NumPartEditorW(m_edited_type, this));
|
||||
m_dirty = true;
|
||||
NumPartEditorW *part = new NumPartEditorW(m_edited_type, this);
|
||||
connect(part, &NumPartEditorW::changed, this, [this]() {
|
||||
m_dirty = true;
|
||||
applyEnable();
|
||||
emit contextEdited();
|
||||
});
|
||||
num_part_list_ << part;
|
||||
ui -> editor_layout -> addWidget(part);
|
||||
ui -> remove_button -> setEnabled(true);
|
||||
applyEnable();
|
||||
emit contextEdited();
|
||||
}
|
||||
|
||||
@@ -174,9 +285,7 @@ void SelectAutonumW::on_remove_button_clicked()
|
||||
//remove if @num_part_list contains more than one item
|
||||
if (num_part_list_.size() > 1) {
|
||||
m_dirty = true;
|
||||
NumPartEditorW *part = num_part_list_.takeLast();
|
||||
// deliberately not disconnecting as not possible to resolve with lambda and will happen automatically when the object "part" is destroyed.
|
||||
delete part;
|
||||
removePartRow(m_rows.last().row);
|
||||
if (num_part_list_.size() == 1) {
|
||||
ui -> remove_button -> setDisabled(true);
|
||||
}
|
||||
@@ -409,6 +518,8 @@ void SelectAutonumW::on_buttonBox_clicked(QAbstractButton *button)
|
||||
*/
|
||||
void SelectAutonumW::applyEnable(bool b)
|
||||
{
|
||||
//Apply and Cancel both stand for a change: grey until there is one
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(b);
|
||||
if (b){
|
||||
bool valid= true;
|
||||
foreach (NumPartEditorW *npe, num_part_list_)
|
||||
@@ -448,28 +559,6 @@ void SelectAutonumW::contextToFormula()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::on_m_next_pb_clicked
|
||||
Increase NumerotationContext
|
||||
*/
|
||||
void SelectAutonumW::on_m_next_pb_clicked()
|
||||
{
|
||||
NumerotationContextCommands ncc (toNumContext());
|
||||
setContext(ncc.next());
|
||||
applyEnable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::on_m_previous_pb_clicked
|
||||
Decrease NumerotationContext
|
||||
*/
|
||||
void SelectAutonumW::on_m_previous_pb_clicked()
|
||||
{
|
||||
NumerotationContextCommands ncc (toNumContext());
|
||||
setContext(ncc.previous());
|
||||
applyEnable(true);
|
||||
}
|
||||
|
||||
void SelectAutonumW::on_m_comboBox_currentTextChanged(const QString &arg1)
|
||||
{
|
||||
Q_UNUSED(arg1);
|
||||
@@ -480,3 +569,29 @@ void SelectAutonumW::on_m_remove_pb_clicked()
|
||||
{
|
||||
emit removeClicked();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief SelectAutonumW::setExplicitNaming
|
||||
Make the list of numberings a plain choice: no typing a name into it
|
||||
(an easy way to create a numbering by accident, or one with an empty
|
||||
name), but a button to create a numbering and one to rename the shown
|
||||
one, which emit newClicked() and renameClicked() for the owner to ask
|
||||
for the name.
|
||||
*/
|
||||
void SelectAutonumW::setExplicitNaming()
|
||||
{
|
||||
ui->m_comboBox->setEditable(false);
|
||||
auto *row = ui->horizontalLayout_2;
|
||||
const int index = row->indexOf(ui->m_remove_pb);
|
||||
|
||||
auto *new_pb = new QPushButton(QET::Icons::Add, QString(), this);
|
||||
new_pb->setToolTip(tr("Nouvelle numérotation…"));
|
||||
connect(new_pb, &QPushButton::clicked, this, &SelectAutonumW::newClicked);
|
||||
|
||||
auto *rename_pb = new QPushButton(QET::Icons::EditRename, QString(), this);
|
||||
rename_pb->setToolTip(tr("Renommer la numérotation…"));
|
||||
connect(rename_pb, &QPushButton::clicked, this, &SelectAutonumW::renameClicked);
|
||||
|
||||
row->insertWidget(index, rename_pb);
|
||||
row->insertWidget(index, new_pb);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class QAbstractButton;
|
||||
class FormulaAutonumberingW;
|
||||
class QComboBox;
|
||||
class QPushButton;
|
||||
class QToolButton;
|
||||
class QHBoxLayout;
|
||||
|
||||
namespace Ui {
|
||||
class SelectAutonumW;
|
||||
@@ -89,6 +91,7 @@ class SelectAutonumW : public QWidget
|
||||
@param can_remove true when a rule is really there
|
||||
*/
|
||||
void setRuleRemovable(bool can_remove);
|
||||
void setExplicitNaming();
|
||||
|
||||
signals:
|
||||
void applyPressed();
|
||||
@@ -101,6 +104,9 @@ class SelectAutonumW : public QWidget
|
||||
write now.
|
||||
*/
|
||||
void contextEdited();
|
||||
/// Only with setExplicitNaming()
|
||||
void newClicked();
|
||||
void renameClicked();
|
||||
|
||||
//SLOT
|
||||
private slots:
|
||||
@@ -108,16 +114,30 @@ class SelectAutonumW : public QWidget
|
||||
void on_remove_button_clicked();
|
||||
void on_buttonBox_clicked(QAbstractButton *);
|
||||
void applyEnable (bool = true);
|
||||
void on_m_next_pb_clicked();
|
||||
void on_m_previous_pb_clicked();
|
||||
void on_m_comboBox_currentTextChanged(const QString &arg1);
|
||||
|
||||
//ATTRIBUTES
|
||||
void on_m_remove_pb_clicked();
|
||||
|
||||
|
||||
private:
|
||||
/// A part of the definition, with the buttons at its right
|
||||
struct PartRow
|
||||
{
|
||||
QWidget *row = nullptr;
|
||||
NumPartEditorW *part = nullptr;
|
||||
QToolButton *up = nullptr;
|
||||
QToolButton *down = nullptr;
|
||||
QToolButton *remove = nullptr;
|
||||
};
|
||||
void insertPartRow(NumPartEditorW *part);
|
||||
void removePartRow(QWidget *row);
|
||||
void movePartRow(QWidget *row, int step);
|
||||
void updatePartButtons();
|
||||
void clearPartRows();
|
||||
Ui::SelectAutonumW *ui;
|
||||
QList <NumPartEditorW *> num_part_list_;
|
||||
QList <PartRow> m_rows;
|
||||
QWidget *m_add_row = nullptr; ///< holds the add button, under the last part
|
||||
NumerotationContext m_context;
|
||||
FormulaAutonumberingW *m_feaw;
|
||||
FormulaAutonumberingW *m_fcaw;
|
||||
|
||||
@@ -63,8 +63,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="edit-delete" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/edit-delete.png</normaloff>:/ico/16x16/edit-delete.png</iconset>
|
||||
<iconset theme="edit-delete"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -136,8 +135,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-remove" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/22x22/list-remove.png</normaloff>:/ico/22x22/list-remove.png</iconset>
|
||||
<iconset theme="list-remove"/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
@@ -153,42 +151,13 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="list-add" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/22x22/list-add.png</normaloff>:/ico/22x22/list-add.png</iconset>
|
||||
<iconset theme="list-add"/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_previous_pb">
|
||||
<property name="toolTip">
|
||||
<string>Précédent</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="arrow-left" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/arrow-left.png</normaloff>:/ico/16x16/arrow-left.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_next_pb">
|
||||
<property name="toolTip">
|
||||
<string>Suivant</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="arrow-right" resource="../../../qelectrotech.qrc">
|
||||
<normaloff>:/ico/16x16/arrow-right.png</normaloff>:/ico/16x16/arrow-right.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
@@ -232,6 +201,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="value_label">
|
||||
<property name="toolTip">
|
||||
<string>Pour un numéro : le prochain numéro attribué. Pour un texte : le texte fixe.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Valeur</string>
|
||||
</property>
|
||||
|
||||
Reference in New Issue
Block a user