mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-11 22:54:12 +02:00
Revert "Add cable management: drawing, cores, numbering, cross-references and cable list"
This commit is contained in:
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
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 "cablerenumber.h"
|
||||
|
||||
#include "cable.h"
|
||||
#include "../autoNum/assignvariables.h"
|
||||
#include "../autoNum/numerotationcontextcommands.h"
|
||||
#include "../diagram.h"
|
||||
#include "../qetproject.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QSet>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
@brief One cable of the project, and where it stands so that the
|
||||
cables can be laid out in an order everybody can see again.
|
||||
*/
|
||||
struct OrderedCable
|
||||
{
|
||||
Cable *cable = nullptr;
|
||||
///The lowest folio the cable is drawn on
|
||||
int folio = 0;
|
||||
///How far it reaches to the left and how far to the top on
|
||||
///that folio
|
||||
qreal left = 0.0;
|
||||
qreal top = 0.0;
|
||||
///The folio the rule is read on for this cable
|
||||
Diagram *diagram = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
@brief Read a rule once, the way the numbering of a cable reads it.
|
||||
|
||||
The rule is read on a copy, since reading it fills in what its
|
||||
folio-bound parts are worth on that one folio, and that must not
|
||||
creep into the rule itself.
|
||||
@param context the rule as it stands at this point of the numbering
|
||||
@param diagram the folio the number is worked out on
|
||||
@param key the name the rule is kept under in the project
|
||||
@return the number, empty when the rule says nothing here
|
||||
*/
|
||||
QString readRule(NumerotationContext context, Diagram *diagram, const QString &key)
|
||||
{
|
||||
const QString formula = autonum::numerotationContextToFormula(context);
|
||||
autonum::sequentialNumbers seq;
|
||||
autonum::setSequential(formula, seq, context, diagram, key);
|
||||
return autonum::AssignVariables::formulaToLabel(formula, seq, diagram);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
@brief CableRenumber::byHandCount
|
||||
@param project
|
||||
@return how many cables of that project carry a name typed in by hand
|
||||
*/
|
||||
int CableRenumber::byHandCount(QETProject *project)
|
||||
{
|
||||
if (!project) return 0;
|
||||
|
||||
int count = 0;
|
||||
for (Cable *cable : project->cables())
|
||||
{
|
||||
if (cable && cable->designationByHand()) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief CableRenumber::plan
|
||||
Work the number of every cable of the project out, without writing
|
||||
anywhere. The cables are put in the order they are numbered in --
|
||||
folio by folio, and on each folio along whichever axis leads -- and
|
||||
the rule is then read from its beginning once for each of them, so
|
||||
that the numbering runs on without a hole.
|
||||
@param project the project whose cables are numbered
|
||||
@param rule the numbering rule to read
|
||||
@param x_axis_first true when the leftmost cable of a folio comes first
|
||||
@param include_by_hand false to leave the names typed in by hand alone
|
||||
@return the numbers, or what stopped the numbering
|
||||
*/
|
||||
CableRenumberPlan CableRenumber::plan(QETProject *project,
|
||||
const NumerotationContext &rule,
|
||||
bool x_axis_first,
|
||||
bool include_by_hand)
|
||||
{
|
||||
CableRenumberPlan result;
|
||||
if (!project)
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber", "No project is open.");
|
||||
return result;
|
||||
}
|
||||
if (project->isReadOnly())
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"This project is read-only: its cables cannot be "
|
||||
"renumbered.");
|
||||
return result;
|
||||
}
|
||||
//The rule may be one the numbering window is drawing right now
|
||||
//and has not written into the project yet: the numbering writes
|
||||
//it together with the numbers themselves, so the project does
|
||||
//not have to hold it beforehand. What the counters are kept
|
||||
//under is the name the rule is stored with, which for cables is
|
||||
//fixed either way -- so numbering starts from a project which
|
||||
//has no rule saved yet just as well.
|
||||
QString key = project->cableCurrentAutoNum();
|
||||
if (key.isEmpty()) {
|
||||
key = QETProject::cableAutoNumRuleName();
|
||||
}
|
||||
if (rule.isEmpty())
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"No cable numbering rule is defined for this "
|
||||
"project. Define one in this window before "
|
||||
"renumbering its cables.");
|
||||
return result;
|
||||
}
|
||||
|
||||
//Where every cable stands, and which ones are left alone: their
|
||||
//names stay as they are, so the numbering must not hand the
|
||||
//same number out again
|
||||
QList<OrderedCable> ordered;
|
||||
QSet<QString> taken;
|
||||
for (Cable *cable : project->cables())
|
||||
{
|
||||
if (!cable) continue;
|
||||
if (!include_by_hand && cable->designationByHand())
|
||||
{
|
||||
if (!cable->designation().isEmpty()) {
|
||||
taken.insert(cable->designation());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
OrderedCable entry;
|
||||
entry.cable = cable;
|
||||
|
||||
for (const CablePartData &part : cable->parts())
|
||||
{
|
||||
Diagram *diagram = project->diagramByUuid(part.diagram);
|
||||
if (!diagram) continue;
|
||||
|
||||
const int index = project->folioIndex(diagram);
|
||||
const qreal left = qMin(part.p1.x(), part.p2.x());
|
||||
const qreal top = qMin(part.p1.y(), part.p2.y());
|
||||
|
||||
if (!entry.diagram || index < entry.folio)
|
||||
{
|
||||
entry.folio = index;
|
||||
entry.diagram = diagram;
|
||||
entry.left = left;
|
||||
entry.top = top;
|
||||
} else if (index == entry.folio) {
|
||||
entry.left = qMin(entry.left, left);
|
||||
entry.top = qMin(entry.top, top);
|
||||
}
|
||||
}
|
||||
//A cable which stands on no folio the project still knows
|
||||
//is numbered last rather than first by accident
|
||||
if (!entry.diagram) {
|
||||
entry.folio = std::numeric_limits<int>::max();
|
||||
}
|
||||
ordered.append(entry);
|
||||
}
|
||||
|
||||
//Folio by folio, and on each folio along the axis which leads:
|
||||
//the other axis is only asked when the leading one says two
|
||||
//cables are level, so that the numbering never depends on the
|
||||
//order the cables happen to be stored in
|
||||
std::sort(ordered.begin(), ordered.end(),
|
||||
[x_axis_first](const OrderedCable &a, const OrderedCable &b)
|
||||
{
|
||||
if (a.folio != b.folio) return a.folio < b.folio;
|
||||
|
||||
const qreal a_first = x_axis_first ? a.left : a.top;
|
||||
const qreal b_first = x_axis_first ? b.left : b.top;
|
||||
if (a_first != b_first) return a_first < b_first;
|
||||
|
||||
const qreal a_second = x_axis_first ? a.top : a.left;
|
||||
const qreal b_second = x_axis_first ? b.top : b.left;
|
||||
if (a_second != b_second) return a_second < b_second;
|
||||
|
||||
return a.cable->uuid().toString() < b.cable->uuid().toString();
|
||||
});
|
||||
|
||||
//Read the rule from the beginning, once for each cable: its
|
||||
//counters are put back first, since numbering a project over
|
||||
//starts at the beginning whatever the last number was
|
||||
NumerotationContext context = autonum::resetContextCounters(rule);
|
||||
int current_folio = -1;
|
||||
|
||||
for (const OrderedCable &entry : std::as_const(ordered))
|
||||
{
|
||||
if (!entry.diagram)
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"A cable is not on any sheet of the project: "
|
||||
"nothing was changed.");
|
||||
return result;
|
||||
}
|
||||
|
||||
//A counter bound to the folio counts from the beginning of
|
||||
//that folio: the first cable of a folio gets the first
|
||||
//number of it, and the folios after it start again rather
|
||||
//than carrying the number of the folio before on
|
||||
if (entry.folio != current_folio)
|
||||
{
|
||||
context = autonum::resetFolioCounters(context);
|
||||
current_folio = entry.folio;
|
||||
}
|
||||
|
||||
const QString candidate = readRule(context, entry.diagram, key);
|
||||
if (candidate.isEmpty())
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"The current rule gives no number here: "
|
||||
"nothing was changed.");
|
||||
return result;
|
||||
}
|
||||
//A rule which does not count hands out the same number
|
||||
//twice, and two cables of one project may not be called
|
||||
//the same thing
|
||||
if (result.designations.contains(candidate))
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"The current rule gives the same number (%1) twice: "
|
||||
"it must count to renumber a whole project. "
|
||||
"Nothing was changed.")
|
||||
.arg(candidate);
|
||||
return result;
|
||||
}
|
||||
//A name which stays because it was typed in keeps its
|
||||
//number, and the numbering may not hand that number out
|
||||
if (taken.contains(candidate))
|
||||
{
|
||||
result.error = QCoreApplication::translate(
|
||||
"CableRenumber",
|
||||
"Number %1 is already used by a cable whose name "
|
||||
"is left as it is: nothing was changed.")
|
||||
.arg(candidate);
|
||||
return result;
|
||||
}
|
||||
|
||||
taken.insert(candidate);
|
||||
result.cables.append(entry.cable);
|
||||
result.designations.append(candidate);
|
||||
|
||||
//Step the rule on for the next cable; a rule which cannot
|
||||
//step stays where it is and is caught by the check above
|
||||
NumerotationContextCommands ncc(context, entry.diagram);
|
||||
const NumerotationContext following = ncc.next();
|
||||
if (following.size() == context.size()) {
|
||||
context = following;
|
||||
}
|
||||
}
|
||||
|
||||
//Where the rule stands after the last cable has been numbered:
|
||||
//the caller writes that into the project, so numbering goes on
|
||||
//from there instead of from wherever the rule happened to stand
|
||||
//before this numbering ran
|
||||
result.after = context;
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user