mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-06 03:04:13 +02:00
d76f3528ae
Schemas now get saved with a UUID and do not have to be looked up according to the form. They can be renamed and it gets reflected in existing elements. The GUI for editing them is now much easier, e.g. forms can be reshuffled. A formula can be applied. Many options now also for conductors and sheets.
882 lines
30 KiB
C++
882 lines
30 KiB
C++
/*
|
|
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 "autonumberingdockwidget.h"
|
|
|
|
#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"
|
|
#include "../../ui/projectpropertiesdialog.h"
|
|
#include "../numerotationcontext.h"
|
|
#include "../numerotationcontextcommands.h"
|
|
#include "ui_autonumberingdockwidget.h"
|
|
#include "../../undocommand/changetitleblockcommand.h"
|
|
|
|
#include <QComboBox>
|
|
#include <QHBoxLayout>
|
|
#include <QLineEdit>
|
|
#include <QMessageBox>
|
|
#include <QPushButton>
|
|
#include <QSignalBlocker>
|
|
#include <QSpinBox>
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::AutoNumberingDockWidget
|
|
Constructor
|
|
@param parent : parent widget
|
|
*/
|
|
AutoNumberingDockWidget::AutoNumberingDockWidget(QWidget *parent) :
|
|
QDockWidget(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
|
|
*/
|
|
AutoNumberingDockWidget::~AutoNumberingDockWidget()
|
|
{
|
|
this->disconnect();
|
|
delete ui;
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::clear
|
|
Remove all combo box values
|
|
*/
|
|
void AutoNumberingDockWidget::clear()
|
|
{
|
|
ui->m_conductor_cb->clear();
|
|
ui->m_element_cb->clear();
|
|
ui->m_folio_cb->clear();
|
|
ui->m_conductor_value_le->clear();
|
|
ui->m_element_value_le->clear();
|
|
ui->m_folio_value_le->clear();
|
|
ui->m_conductor_next_le->clear();
|
|
ui->m_element_next_le->clear();
|
|
ui->m_folio_next_le->clear();
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::rowFor
|
|
@return the combo/value/increase/next widgets that make up category's row.
|
|
*/
|
|
AutoNumberingDockWidget::Row AutoNumberingDockWidget::rowFor(AutoNumCategory category) const
|
|
{
|
|
switch (category) {
|
|
case AutoNumCategory::Conductor:
|
|
return {ui->m_conductor_cb, ui->m_conductor_value_le,
|
|
ui->m_conductor_increase_sb, ui->m_conductor_next_le};
|
|
case AutoNumCategory::Element:
|
|
return {ui->m_element_cb, ui->m_element_value_le,
|
|
ui->m_element_increase_sb, ui->m_element_next_le};
|
|
case AutoNumCategory::Folio:
|
|
return {ui->m_folio_cb, ui->m_folio_value_le,
|
|
ui->m_folio_increase_sb, ui->m_folio_next_le};
|
|
}
|
|
return {nullptr, nullptr, nullptr, nullptr};
|
|
}
|
|
|
|
void AutoNumberingDockWidget::projectClosed()
|
|
{
|
|
m_project = nullptr;
|
|
m_project_view = nullptr;
|
|
clear();
|
|
this->setDisabled(true);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::setProject
|
|
@param project: project to be setted
|
|
@param projectview: projectview to be setted
|
|
assign Project and ProjectView, connect all signals and setContext
|
|
*/
|
|
void AutoNumberingDockWidget::setProject(QETProject *project,
|
|
ProjectView *projectview)
|
|
{
|
|
//Disconnect previous project
|
|
if (m_project && m_project_view)
|
|
{
|
|
disconnect(m_project, &QETProject::conductorAutoNumChanged, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
|
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);
|
|
disconnect(m_project, &QETProject::elementAutoNumAdded, this, &AutoNumberingDockWidget::elementAutoNumChanged);
|
|
|
|
//Folio Signals
|
|
disconnect(m_project, &QETProject::folioAutoNumRemoved, this, qOverload<>(&AutoNumberingDockWidget::folioAutoNumChanged));
|
|
disconnect(m_project, &QETProject::folioAutoNumAdded, this, qOverload<>(&AutoNumberingDockWidget::folioAutoNumChanged));
|
|
disconnect(m_project, &QETProject::defaultTitleBlockPropertiesChanged, this, &AutoNumberingDockWidget::setActive);
|
|
|
|
//Conductor, Element and Folio Signals
|
|
disconnect(m_project, &QETProject::autoNumContextUpdated,
|
|
this, &AutoNumberingDockWidget::refreshValueFields);
|
|
disconnect(m_project, &QETProject::destroyed,
|
|
this, &AutoNumberingDockWidget::projectClosed);
|
|
}
|
|
|
|
m_project = project;
|
|
m_project_view = projectview;
|
|
this->setEnabled(true);
|
|
|
|
connect(m_project, &QETProject::conductorAutoNumChanged, this, &AutoNumberingDockWidget::conductorAutoNumChanged);
|
|
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);
|
|
connect(m_project, &QETProject::elementAutoNumAdded, this, &AutoNumberingDockWidget::elementAutoNumChanged);
|
|
|
|
//Folio Signals
|
|
connect(m_project, &QETProject::folioAutoNumRemoved, this, qOverload<>(&AutoNumberingDockWidget::folioAutoNumChanged));
|
|
connect(m_project, &QETProject::folioAutoNumAdded, this, qOverload<>(&AutoNumberingDockWidget::folioAutoNumChanged));
|
|
connect(m_project, &QETProject::defaultTitleBlockPropertiesChanged, this, &AutoNumberingDockWidget::setActive);
|
|
|
|
//Conductor, Element and Folio Signals
|
|
connect(m_project, &QETProject::autoNumContextUpdated,
|
|
this, &AutoNumberingDockWidget::refreshValueFields);
|
|
connect(m_project, &QETProject::destroyed,
|
|
this, &AutoNumberingDockWidget::projectClosed);
|
|
|
|
//Set Combobox Context
|
|
setContext();
|
|
|
|
ShortcutManager::instance().registerAction(ui->m_configure_pb, "autonum.configure",
|
|
tr("Autonumérotation"), Qt::CTRL | Qt::SHIFT | Qt::Key_P);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::setContext
|
|
Add all itens to comboboxes
|
|
*/
|
|
void AutoNumberingDockWidget::setContext()
|
|
{
|
|
|
|
this->clear();
|
|
|
|
//Conductor Combobox
|
|
ui->m_conductor_cb->addItem("");
|
|
QList <QString> keys_conductor = m_project->conductorAutoNum().keys();
|
|
if (!keys_conductor.isEmpty()) {
|
|
foreach (QString str, keys_conductor)
|
|
{ ui->m_conductor_cb-> addItem(str); }
|
|
}
|
|
|
|
//Element Combobox
|
|
ui->m_element_cb->addItem("");
|
|
QList <QString> keys_element = m_project->elementAutoNum().keys();
|
|
if (!keys_element.isEmpty()) {
|
|
foreach (QString str, keys_element)
|
|
{ui->m_element_cb -> addItem(str);}
|
|
}
|
|
|
|
//Folio Combobox
|
|
ui->m_folio_cb->addItem("");
|
|
QList <QString> keys_folio = m_project->folioAutoNum().keys();
|
|
if (!keys_folio.isEmpty()) {
|
|
foreach (QString str, keys_folio)
|
|
{ ui->m_folio_cb -> addItem(str);}
|
|
}
|
|
|
|
//The combo boxes have just been repopulated, so the value fields next
|
|
//to them are showing whatever the previous project left there.
|
|
refreshRow(AutoNumCategory::Conductor);
|
|
refreshRow(AutoNumCategory::Element);
|
|
refreshRow(AutoNumCategory::Folio);
|
|
|
|
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
|
|
*/
|
|
void AutoNumberingDockWidget::setConductorActive(DiagramView* dv) {
|
|
if (dv!=nullptr) {
|
|
QString conductor_autonum = dv->diagram()->conductorsAutonumName();
|
|
int conductor_index = ui->m_conductor_cb->findText(conductor_autonum);
|
|
ui->m_conductor_cb->setCurrentIndex(conductor_index);
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::setActive
|
|
Set current used autonumberings
|
|
*/
|
|
void AutoNumberingDockWidget::setActive()
|
|
{
|
|
|
|
if (m_project_view!=nullptr) {
|
|
//Conductor
|
|
if (m_project_view->currentDiagram()) {
|
|
QString conductor_autonum = m_project_view->currentDiagram()->diagram()->conductorsAutonumName();
|
|
int conductor_index = ui->m_conductor_cb->findText(conductor_autonum);
|
|
ui->m_conductor_cb->setCurrentIndex(conductor_index);
|
|
}
|
|
|
|
//Element
|
|
QString element_formula = m_project->elementAutoNumCurrentFormula();
|
|
QString active_element_autonum = m_project->elementCurrentAutoNum();
|
|
int el_index = ui->m_element_cb->findText(active_element_autonum);
|
|
ui->m_element_cb->setCurrentIndex(el_index);
|
|
|
|
//Folio
|
|
if (m_project->defaultTitleBlockProperties().folio == "%autonum") {
|
|
QString page_autonum = m_project->defaultTitleBlockProperties().auto_page_num;
|
|
int folio_index = ui->m_folio_cb->findText(page_autonum);
|
|
ui->m_folio_cb->setCurrentIndex(folio_index);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::conductorAutoNumChanged
|
|
Add new or remove conductor auto num from combobox
|
|
*/
|
|
void AutoNumberingDockWidget::conductorAutoNumChanged()
|
|
{
|
|
ui->m_conductor_cb->clear();
|
|
|
|
//Conductor Combobox
|
|
ui->m_conductor_cb->addItem("");
|
|
QList <QString> keys_conductor = m_project->conductorAutoNum().keys();
|
|
if (!keys_conductor.isEmpty()) {
|
|
foreach (QString str, keys_conductor)
|
|
{ ui->m_conductor_cb-> addItem(str); }
|
|
}
|
|
setActive();
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::on_m_conductor_cb_activated
|
|
Set new conductor AutoNum
|
|
*/
|
|
void AutoNumberingDockWidget::on_m_conductor_cb_activated(int)
|
|
{
|
|
QString current_autonum = ui->m_conductor_cb->currentText();
|
|
|
|
m_project->setCurrentConductorAutoNum(current_autonum);
|
|
m_project_view->currentDiagram()->diagram()->setConductorsAutonumName(current_autonum);
|
|
m_project_view->currentDiagram()->diagram()->loadCndFolioSeq();
|
|
refreshRow(AutoNumCategory::Conductor);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::elementAutoNumChanged
|
|
Add new or remove element auto num from combobox
|
|
*/
|
|
void AutoNumberingDockWidget::elementAutoNumChanged()
|
|
{
|
|
|
|
ui->m_element_cb->clear();
|
|
|
|
//Element Combobox
|
|
ui->m_element_cb->addItem("");
|
|
QList <QString> keys_element = m_project->elementAutoNum().keys();
|
|
if (!keys_element.isEmpty()) {
|
|
foreach (QString str, keys_element) {ui->m_element_cb -> addItem(str);}
|
|
}
|
|
setActive();
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::on_m_element_cb_activated
|
|
Set new element AutoNum
|
|
*/
|
|
void AutoNumberingDockWidget::on_m_element_cb_activated(int)
|
|
{
|
|
m_project->setCurrrentElementAutonum(ui->m_element_cb->currentText());
|
|
m_project_view->currentDiagram()->diagram()->loadElmtFolioSeq();
|
|
refreshRow(AutoNumCategory::Element);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::folioAutoNumChanged
|
|
Add new or remove folio auto num from combobox
|
|
*/
|
|
void AutoNumberingDockWidget::folioAutoNumChanged()
|
|
{
|
|
|
|
ui->m_folio_cb->clear();
|
|
|
|
//Folio Combobox
|
|
ui->m_folio_cb->addItem("");
|
|
QList <QString> keys_folio = m_project->folioAutoNum().keys();
|
|
if (!keys_folio.isEmpty()) {
|
|
foreach (QString str, keys_folio) { ui->m_folio_cb -> addItem(str);}
|
|
}
|
|
setActive();
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::on_m_folio_cb_activated
|
|
Set new folio AutoNum
|
|
*/
|
|
void AutoNumberingDockWidget::on_m_folio_cb_activated(int) {
|
|
QString current_autonum = ui->m_folio_cb->currentText();
|
|
TitleBlockProperties ip = m_project -> defaultTitleBlockProperties();
|
|
if (current_autonum != "") {
|
|
ip.setAutoPageNum(current_autonum);
|
|
ip.folio = "%autonum";
|
|
m_project->setDefaultTitleBlockProperties(ip);
|
|
}
|
|
else {
|
|
ip.folio = "%id/%total";
|
|
m_project->setDefaultTitleBlockProperties(ip);
|
|
}
|
|
|
|
if (m_project_view && m_project_view->currentDiagram()) {
|
|
Diagram *diagram = m_project_view->currentDiagram()->diagram();
|
|
TitleBlockProperties old_properties = diagram->border_and_titleblock.exportTitleBlock();
|
|
TitleBlockProperties new_properties = old_properties;
|
|
new_properties.auto_page_num = ip.auto_page_num;
|
|
new_properties.folio = ip.folio;
|
|
if (new_properties != old_properties)
|
|
diagram->undoStack().push(new ChangeTitleBlockCommand(diagram, old_properties, new_properties));
|
|
}
|
|
refreshRow(AutoNumCategory::Folio);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_configure_pb_clicked()
|
|
{
|
|
if (m_project)
|
|
{
|
|
ProjectPropertiesDialog ppd (m_project, this);
|
|
ppd.setCurrentPage(ProjectPropertiesDialog::Autonum);
|
|
ppd.exec();
|
|
}
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_conductor_reset_start_pb_clicked()
|
|
{
|
|
resetAutoNum(ui->m_conductor_cb, AutoNumCategory::Conductor);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_element_reset_start_pb_clicked()
|
|
{
|
|
resetAutoNum(ui->m_element_cb, AutoNumCategory::Element);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_folio_reset_start_pb_clicked()
|
|
{
|
|
resetAutoNum(ui->m_folio_cb, AutoNumCategory::Folio);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_conductor_value_le_editingFinished()
|
|
{
|
|
applyValueField(ui->m_conductor_cb, ui->m_conductor_value_le, AutoNumCategory::Conductor);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_element_value_le_editingFinished()
|
|
{
|
|
applyValueField(ui->m_element_cb, ui->m_element_value_le, AutoNumCategory::Element);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_folio_value_le_editingFinished()
|
|
{
|
|
applyValueField(ui->m_folio_cb, ui->m_folio_value_le, AutoNumCategory::Folio);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_conductor_increase_sb_valueChanged(int)
|
|
{
|
|
applyIncreaseField(ui->m_conductor_cb, ui->m_conductor_increase_sb, AutoNumCategory::Conductor);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_element_increase_sb_valueChanged(int)
|
|
{
|
|
applyIncreaseField(ui->m_element_cb, ui->m_element_increase_sb, AutoNumCategory::Element);
|
|
}
|
|
|
|
void AutoNumberingDockWidget::on_m_folio_increase_sb_valueChanged(int)
|
|
{
|
|
applyIncreaseField(ui->m_folio_cb, ui->m_folio_increase_sb, AutoNumCategory::Folio);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::contextFor
|
|
@return the numerotation context named by combo_box, for category
|
|
*/
|
|
NumerotationContext AutoNumberingDockWidget::contextFor(QComboBox *combo_box, AutoNumCategory category) const
|
|
{
|
|
const QString key = combo_box->currentText();
|
|
switch (category) {
|
|
case AutoNumCategory::Conductor: return m_project->conductorAutoNum(key);
|
|
case AutoNumCategory::Element: return m_project->elementAutoNum(key);
|
|
case AutoNumCategory::Folio: return m_project->folioAutoNum(key);
|
|
}
|
|
return NumerotationContext();
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::storeContext
|
|
Write context back under the name selected in combo_box and flag the
|
|
project as modified -- without that last step the change is not saved
|
|
and the user is never asked to save it on close.
|
|
*/
|
|
void AutoNumberingDockWidget::storeContext(QComboBox *combo_box, AutoNumCategory category, const NumerotationContext &context)
|
|
{
|
|
const QString key = combo_box->currentText();
|
|
switch (category) {
|
|
case AutoNumCategory::Conductor: m_project->addConductorAutoNum(key, context); break;
|
|
case AutoNumCategory::Element: m_project->addElementAutoNum(key, context); break;
|
|
case AutoNumCategory::Folio: m_project->addFolioAutoNum(key, context); break;
|
|
}
|
|
m_project->setModified(true);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::counterIndex
|
|
@return the index of the part the value field shows: the last one that
|
|
actually progresses, i.e. the least significant digit of the number.
|
|
-1 when the context has no progressing part at all.
|
|
*/
|
|
int AutoNumberingDockWidget::counterIndex(const NumerotationContext &context)
|
|
{
|
|
for (int i = context.size() - 1 ; i >= 0 ; --i)
|
|
{
|
|
const QString type = context.itemAt(i).at(0);
|
|
if (type == QLatin1String("unit")
|
|
|| type == QLatin1String("ten")
|
|
|| type == QLatin1String("hundred")
|
|
|| type == QLatin1String("unitfolio")
|
|
|| type == QLatin1String("tenfolio")
|
|
|| type == QLatin1String("hundredfolio")
|
|
|| type == QLatin1String("wrap")
|
|
|| type == QLatin1String("alpha"))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::refreshValueFields
|
|
Re-read all three value fields from the project. Called whenever a
|
|
numerotation context's values change, which includes every element or
|
|
conductor that consumes the next number -- without this the field only
|
|
caught up when the user re-picked a rule from the combo box, because
|
|
the combo's activated() signal fires on user interaction alone.
|
|
*/
|
|
void AutoNumberingDockWidget::refreshValueFields()
|
|
{
|
|
//Leave alone a row the user is typing in: numbering an element
|
|
//refreshes all three rows, and overwriting a half-typed value or
|
|
//increment under the cursor is worse than showing it a moment out
|
|
//of date. Only this automatic path skips; an explicit refresh after
|
|
//a reset or an edit still writes, so the row always ends up
|
|
//canonical. The next-value preview has no such guard: it is
|
|
//read-only, so there is nothing a refresh could clobber.
|
|
for (AutoNumCategory category : {AutoNumCategory::Conductor,
|
|
AutoNumCategory::Element,
|
|
AutoNumCategory::Folio})
|
|
{
|
|
const Row row = rowFor(category);
|
|
if (!row.value->hasFocus() && !row.increase->hasFocus())
|
|
refreshRow(category);
|
|
}
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::refreshValueField
|
|
Show the current value of the selected context's counter, so the field
|
|
always reflects where the numbering has actually got to.
|
|
*/
|
|
void AutoNumberingDockWidget::refreshValueField(QComboBox *combo_box, QLineEdit *line_edit, AutoNumCategory category)
|
|
{
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
{
|
|
line_edit->clear();
|
|
line_edit->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
const NumerotationContext context = contextFor(combo_box, category);
|
|
const int index = counterIndex(context);
|
|
line_edit->setEnabled(index >= 0);
|
|
line_edit->setText(index >= 0 ? context.itemAt(index).at(1) : QString());
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::applyValueField
|
|
Write the value typed in line_edit to the counter it displays. An empty
|
|
field is treated as "no change" rather than as an empty value, so
|
|
clearing the box by accident cannot wipe the counter.
|
|
*/
|
|
void AutoNumberingDockWidget::applyValueField(QComboBox *combo_box, QLineEdit *line_edit, AutoNumCategory category)
|
|
{
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
return;
|
|
|
|
NumerotationContext context = contextFor(combo_box, category);
|
|
const int index = counterIndex(context);
|
|
if (index < 0)
|
|
return;
|
|
|
|
const QString typed = line_edit->text();
|
|
if (typed.isEmpty() || typed == context.itemAt(index).at(1))
|
|
{
|
|
refreshRow(category);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::refreshIncreaseField
|
|
Show the counter's current step size (bug #331: previously only
|
|
reachable from the full configuration dialog, via "Configurer").
|
|
*/
|
|
void AutoNumberingDockWidget::refreshIncreaseField(QComboBox *combo_box, QSpinBox *increase_sb, AutoNumCategory category)
|
|
{
|
|
//QSpinBox::setValue() emits valueChanged() even when called
|
|
//programmatically. Without blocking it, this refresh would
|
|
//immediately re-trigger on_..._increase_sb_valueChanged() ->
|
|
//applyIncreaseField() -> storeContext() -> the project's
|
|
//autoNumContextUpdated signal -> refreshValueFields() -> back here.
|
|
const QSignalBlocker blocker(increase_sb);
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
{
|
|
increase_sb->setEnabled(false);
|
|
increase_sb->setValue(increase_sb->minimum());
|
|
return;
|
|
}
|
|
|
|
const NumerotationContext context = contextFor(combo_box, category);
|
|
const int index = counterIndex(context);
|
|
increase_sb->setEnabled(index >= 0);
|
|
increase_sb->setValue(index >= 0 ? context.itemAt(index).at(2).toInt()
|
|
: increase_sb->minimum());
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::applyIncreaseField
|
|
Write the spin box's step size to the counter it displays (bug #331).
|
|
*/
|
|
void AutoNumberingDockWidget::applyIncreaseField(QComboBox *combo_box, QSpinBox *increase_sb, AutoNumCategory category)
|
|
{
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
return;
|
|
|
|
NumerotationContext context = contextFor(combo_box, category);
|
|
const int index = counterIndex(context);
|
|
if (index < 0)
|
|
return;
|
|
|
|
if (increase_sb->value() == context.itemAt(index).at(2).toInt())
|
|
return;
|
|
|
|
context.replaceIncrease(index, increase_sb->value());
|
|
storeContext(combo_box, category, context);
|
|
refreshRow(category);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::refreshNextField
|
|
Show what this counter will read after one more step (bug #331: "visualiser
|
|
la prochaine numérotation qui sera appliquée"). Advances a copy of the
|
|
whole context through NumerotationContextCommands -- the same engine the
|
|
Suivant button in the full configuration dialog uses to step a context --
|
|
so wrap-and-carry into this part from a following part, or out of it into
|
|
a preceding one, comes out identical to what will actually happen when the
|
|
number is next consumed.
|
|
*/
|
|
void AutoNumberingDockWidget::refreshNextField(QComboBox *combo_box, QLineEdit *next_edit, AutoNumCategory category)
|
|
{
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
{
|
|
next_edit->clear();
|
|
next_edit->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
const NumerotationContext context = contextFor(combo_box, category);
|
|
const int index = counterIndex(context);
|
|
if (index < 0)
|
|
{
|
|
next_edit->clear();
|
|
next_edit->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
Diagram *diagram = (m_project_view && m_project_view->currentDiagram())
|
|
? m_project_view->currentDiagram()->diagram()
|
|
: nullptr;
|
|
NumerotationContextCommands ncc(context, diagram);
|
|
const NumerotationContext next_context = ncc.next();
|
|
|
|
next_edit->setEnabled(true);
|
|
next_edit->setText(NumerotationContext::formatValue(next_context.itemAt(index)));
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::refreshRow
|
|
Refresh a category's value, increment and next-value preview together --
|
|
every call site that used to refresh just the value field needs the
|
|
other two kept in step with it as well.
|
|
*/
|
|
void AutoNumberingDockWidget::refreshRow(AutoNumCategory category)
|
|
{
|
|
const Row row = rowFor(category);
|
|
refreshValueField(row.combo, row.value, category);
|
|
refreshIncreaseField(row.combo, row.increase, category);
|
|
refreshNextField(row.combo, row.next, category);
|
|
}
|
|
|
|
/**
|
|
@brief AutoNumberingDockWidget::resetAutoNum
|
|
Reset the numerotation context currently selected in combo_box back to
|
|
a per-type starting value, then write it back. Does nothing if no
|
|
context is selected.
|
|
|
|
Only parts that actually progress are touched: folio-anchored numeric
|
|
types go back to their own stored initialvalue, plain numeric types go
|
|
back to "1", a wrap part goes back to "0" because a modulo counter
|
|
cycles over [0, modulus) -- a PLC card addressed %IX0.0..%IX0.31 starts
|
|
at 0, not 1 -- and alpha goes back to "a". Non-incrementing types
|
|
(string, plant, locmach, idfolio, folio, elementline, elementcolumn,
|
|
elementprefix) are left alone: there is no "start" for them distinct
|
|
from the fixed or contextual value the user configured.
|
|
*/
|
|
void AutoNumberingDockWidget::resetAutoNum(QComboBox *combo_box, AutoNumCategory category)
|
|
{
|
|
if (!m_project || combo_box->currentText().isEmpty())
|
|
return;
|
|
|
|
NumerotationContext context = contextFor(combo_box, category);
|
|
|
|
for (int i = 0 ; i < context.size() ; ++i)
|
|
{
|
|
const QStringList item = context.itemAt(i);
|
|
const QString &type = item.at(0);
|
|
if (type == QLatin1String("unitfolio")
|
|
|| type == QLatin1String("tenfolio")
|
|
|| type == QLatin1String("hundredfolio"))
|
|
context.replaceValue(i, item.size() > 3 ? item.at(3) : QStringLiteral("1"));
|
|
else if (type == QLatin1String("unit")
|
|
|| type == QLatin1String("ten")
|
|
|| type == QLatin1String("hundred"))
|
|
context.replaceValue(i, QStringLiteral("1"));
|
|
else if (type == QLatin1String("wrap"))
|
|
context.replaceValue(i, QStringLiteral("0"));
|
|
else if (type == QLatin1String("alpha"))
|
|
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);
|
|
}
|