mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-27 12:34:14 +02:00
Compare commits
14 Commits
acf2320f68
...
c1694f2b4f
| Author | SHA1 | Date | |
|---|---|---|---|
| c1694f2b4f | |||
| 2d99ba67f1 | |||
| bb61dde811 | |||
| e91bab14fe | |||
| eb140dac60 | |||
| f7a79e75af | |||
| 25effbd137 | |||
| 3bc2e8e712 | |||
| b446074731 | |||
| a4d75c4d8c | |||
| 68c260342e | |||
| 0fa2591c4f | |||
| 4c1f82f814 | |||
| 80fcd4283d |
@@ -699,6 +699,8 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/ui/importelementdialog.h
|
||||
${QET_DIR}/sources/ui/importelementtextpatterndialog.cpp
|
||||
${QET_DIR}/sources/ui/importelementtextpatterndialog.h
|
||||
${QET_DIR}/sources/ui/jumptoelementdialog.cpp
|
||||
${QET_DIR}/sources/ui/jumptoelementdialog.h
|
||||
${QET_DIR}/sources/ui/inditextpropertieswidget.cpp
|
||||
${QET_DIR}/sources/ui/inditextpropertieswidget.h
|
||||
${QET_DIR}/sources/ui/linksingleelementwidget.cpp
|
||||
|
||||
@@ -43,6 +43,14 @@ ElementsTreeView::ElementsTreeView(QWidget *parent) :
|
||||
{
|
||||
// force du noir sur une alternance de blanc (comme le schema) et de gris
|
||||
// clair, avec du blanc sur bleu pas trop fonce pour la selection
|
||||
//
|
||||
// Element icons are rendered with colors read directly from each .elmt
|
||||
// file (almost always black linework, matching printed-schematic
|
||||
// convention) onto a transparent background -- so this view must keep
|
||||
// a light background regardless of the OS/desktop theme, or the icons
|
||||
// become invisible on dark themes. QAbstractItemView paints its rows
|
||||
// using the viewport's palette, not the view's own, so the palette
|
||||
// must be applied to both to actually take effect under every style.
|
||||
QPalette qp = palette();
|
||||
qp.setColor(QPalette::Text, Qt::black);
|
||||
qp.setColor(QPalette::Base, Qt::white);
|
||||
@@ -50,6 +58,7 @@ ElementsTreeView::ElementsTreeView(QWidget *parent) :
|
||||
qp.setColor(QPalette::Highlight, QColor("#678db2"));
|
||||
qp.setColor(QPalette::HighlightedText, Qt::black);
|
||||
setPalette(qp);
|
||||
viewport()->setPalette(qp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace autonum
|
||||
ten_folio = other.ten_folio;
|
||||
hundred = other.hundred;
|
||||
hundred_folio = other.hundred_folio;
|
||||
alpha = other.alpha;
|
||||
}
|
||||
|
||||
sequentialNumbers::~sequentialNumbers()
|
||||
@@ -61,6 +62,7 @@ namespace autonum
|
||||
ten_folio = other.ten_folio;
|
||||
hundred = other.hundred;
|
||||
hundred_folio = other.hundred_folio;
|
||||
alpha = other.alpha;
|
||||
|
||||
return (*this);
|
||||
}
|
||||
@@ -72,7 +74,8 @@ namespace autonum
|
||||
ten == other.ten && \
|
||||
ten_folio == other.ten_folio && \
|
||||
hundred == other.hundred && \
|
||||
hundred_folio == other.hundred_folio)
|
||||
hundred_folio == other.hundred_folio && \
|
||||
alpha == other.alpha)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@@ -129,6 +132,11 @@ namespace autonum
|
||||
document,
|
||||
"hundredFolio",
|
||||
hundred_folio.join(";")));
|
||||
if(!alpha.isEmpty())
|
||||
element.appendChild(QETXML::textToDomElement(
|
||||
document,
|
||||
"alpha",
|
||||
alpha.join(";")));
|
||||
|
||||
return element;
|
||||
}
|
||||
@@ -162,6 +170,9 @@ namespace autonum
|
||||
|
||||
from = element.firstChildElement("hundredFolio");
|
||||
hundred_folio = from.text().split(";");
|
||||
|
||||
from = element.firstChildElement("alpha");
|
||||
alpha = from.text().split(";");
|
||||
}
|
||||
|
||||
//Clear this sequence
|
||||
@@ -173,6 +184,7 @@ namespace autonum
|
||||
ten_folio.clear();
|
||||
hundred.clear();
|
||||
hundred_folio.clear();
|
||||
alpha.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,6 +292,11 @@ namespace autonum
|
||||
str.replace("%{plc_function}", dc.value("plc_function").toString());
|
||||
str.replace("%{plc_comment}", dc.value("plc_comment").toString());
|
||||
str.replace("%{plc_crossref}", dc.value("plc_crossref").toString());
|
||||
str.replace("%{plc_tc}", dc.value("plc_tc").toString());
|
||||
str.replace("%{plc_t1}", dc.value("plc_t1").toString());
|
||||
str.replace("%{plc_t2}", dc.value("plc_t2").toString());
|
||||
str.replace("%{plc_t3}", dc.value("plc_t3").toString());
|
||||
str.replace("%{plc_t4}", dc.value("plc_t4").toString());
|
||||
|
||||
return str;
|
||||
}
|
||||
@@ -414,8 +431,10 @@ namespace autonum
|
||||
m_seq_struct.ten_folio.size()),
|
||||
qMax(m_seq_struct.hundred_folio.size(),
|
||||
m_seq_struct.unit.size())),
|
||||
qMax(m_seq_struct.hundred.size(),
|
||||
m_seq_struct.ten.size())
|
||||
qMax(
|
||||
qMax(m_seq_struct.hundred.size(),
|
||||
m_seq_struct.ten.size()),
|
||||
m_seq_struct.alpha.size())
|
||||
);
|
||||
|
||||
for (int i=1; i<=max ; i++)
|
||||
@@ -438,6 +457,9 @@ namespace autonum
|
||||
if (m_assigned_label.contains("%seqhf_" + QString::number(i)) && m_seq_struct.hundred_folio.size() >= i) {
|
||||
m_assigned_label.replace("%seqhf_" + QString::number(i),m_seq_struct.hundred_folio.at(i-1));
|
||||
}
|
||||
if (m_assigned_label.contains("%seqa_" + QString::number(i)) && m_seq_struct.alpha.size() >= i) {
|
||||
m_assigned_label.replace("%seqa_" + QString::number(i),m_seq_struct.alpha.at(i-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,6 +484,9 @@ namespace autonum
|
||||
number = QString("%1").arg(context.itemAt(i).at(1).toInt(), 2, 10, QChar('0'));
|
||||
else if (type == "hundred" || type == "hundredfolio")
|
||||
number = QString("%1").arg(context.itemAt(i).at(1).toInt(), 3, 10, QChar('0'));
|
||||
else if (type == "alpha")
|
||||
//Alphabetic value, not an integer -- used as-is.
|
||||
number = context.itemAt(i).at(1);
|
||||
else number = QString::number(context.itemAt(i).at(1).toInt());
|
||||
list.append(number);
|
||||
}
|
||||
@@ -551,6 +576,10 @@ namespace autonum
|
||||
autonum::setSequentialToList(seqStruct.hundred_folio, context,"hundredfolio");
|
||||
autonum::setFolioSequentialToHash(seqStruct.hundred_folio, diagram->m_elmt_hundredfolio_max, hashKey);
|
||||
}
|
||||
if (label.contains("%seqa_"))
|
||||
{
|
||||
autonum::setSequentialToList(seqStruct.alpha, context,"alpha");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +599,7 @@ namespace autonum
|
||||
int count_tenf = 0;
|
||||
int count_hundred = 0;
|
||||
int count_hundredf = 0;
|
||||
int count_alpha = 0;
|
||||
|
||||
for(int i=0 ; i<nc.size() ; i++)
|
||||
{
|
||||
@@ -626,6 +656,10 @@ namespace autonum
|
||||
count_hundredf++;
|
||||
formula.append("%seqhf_" + QString::number(count_hundredf));
|
||||
}
|
||||
else if (type == "alpha") {
|
||||
count_alpha++;
|
||||
formula.append("%seqa_" + QString::number(count_alpha));
|
||||
}
|
||||
}
|
||||
|
||||
return formula;
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace autonum
|
||||
QStringList ten_folio;
|
||||
QStringList hundred;
|
||||
QStringList hundred_folio;
|
||||
QStringList alpha;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,12 +51,14 @@ void NumerotationContext::clear ()
|
||||
@param value the value itself
|
||||
@param increase the increase number of value
|
||||
@param initialvalue
|
||||
@param modulus wrap-and-carry modulus (0 means "not a wrapping part")
|
||||
@return true if value is append
|
||||
*/
|
||||
bool NumerotationContext::addValue(const QString &type,
|
||||
const QVariant &value,
|
||||
const int increase,
|
||||
const int initialvalue) {
|
||||
const int initialvalue,
|
||||
const int modulus) {
|
||||
if (!keyIsAcceptable(type) && !value.canConvert<QString>())
|
||||
return false;
|
||||
if (keyIsNumber(type) && !value.canConvert<int>())
|
||||
@@ -70,7 +72,9 @@ bool NumerotationContext::addValue(const QString &type,
|
||||
+ "|"
|
||||
+ QString::number(increase)
|
||||
+ "|"
|
||||
+ QString::number(initialvalue);
|
||||
+ QString::number(initialvalue)
|
||||
+ "|"
|
||||
+ QString::number(modulus);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -125,7 +129,7 @@ QStringList NumerotationContext::itemAt(const int i) const
|
||||
*/
|
||||
QString NumerotationContext::validRegExpNum () const
|
||||
{
|
||||
return ("unit|unitfolio|ten|tenfolio|hundred|hundredfolio|string|idfolio|folio|plant|locmach|elementline|elementcolumn|elementprefix");
|
||||
return ("unit|unitfolio|ten|tenfolio|hundred|hundredfolio|wrap|alpha|string|idfolio|folio|plant|locmach|elementline|elementcolumn|elementprefix");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +138,7 @@ QString NumerotationContext::validRegExpNum () const
|
||||
*/
|
||||
QString NumerotationContext::validRegExpNumber() const
|
||||
{
|
||||
return ("unit|unitfolio|ten|tenfolio|hundred|hundredfolio");
|
||||
return ("unit|unitfolio|ten|tenfolio|hundred|hundredfolio|wrap");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,6 +176,9 @@ QDomElement NumerotationContext::toXml(QDomDocument &d, const QString& str) {
|
||||
strl.at(0) == ("hundredfolio")) {
|
||||
part.setAttribute("initialvalue", strl.at(3));
|
||||
}
|
||||
if (strl.at(0) == ("wrap") && strl.size() > 4) {
|
||||
part.setAttribute("modulus", strl.at(4));
|
||||
}
|
||||
num_auto.appendChild(part);
|
||||
}
|
||||
return num_auto;
|
||||
@@ -183,7 +190,7 @@ QDomElement NumerotationContext::toXml(QDomDocument &d, const QString& str) {
|
||||
*/
|
||||
void NumerotationContext::fromXml(QDomElement &e) {
|
||||
clear();
|
||||
foreach(QDomElement qde, QET::findInDomElement(e, "part")) addValue(qde.attribute("type"), qde.attribute("value"), qde.attribute("increase").toInt(), qde.attribute("initialvalue").toInt());
|
||||
foreach(QDomElement qde, QET::findInDomElement(e, "part")) addValue(qde.attribute("type"), qde.attribute("value"), qde.attribute("increase").toInt(), qde.attribute("initialvalue").toInt(), qde.attribute("modulus").toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,10 +200,11 @@ void NumerotationContext::fromXml(QDomElement &e) {
|
||||
@param content to replace current value
|
||||
*/
|
||||
void NumerotationContext::replaceValue(int index, QString content) {
|
||||
QString sep = "|";
|
||||
QString type = content_[index].split("|").at(0);
|
||||
QStringList strl = content_[index].split("|");
|
||||
QString type = strl.at(0);
|
||||
const QString& value = std::move(content);
|
||||
QString increase = content_[index].split("|").at(2);
|
||||
QString initvalue = content_[index].split("|").at(3);
|
||||
content_[index].replace(content_[index], type + "|" + value + "|" + increase + "|" + initvalue);
|
||||
QString increase = strl.at(2);
|
||||
QString initvalue = strl.at(3);
|
||||
QString modulus = strl.size() > 4 ? strl.at(4) : QStringLiteral("0");
|
||||
content_[index] = type + "|" + value + "|" + increase + "|" + initvalue + "|" + modulus;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class NumerotationContext
|
||||
bool addValue(const QString &,
|
||||
const QVariant & = QVariant(1),
|
||||
const int = 1,
|
||||
const int = 0,
|
||||
const int = 0);
|
||||
QString operator[] (const int &) const;
|
||||
void operator << (const NumerotationContext &);
|
||||
|
||||
@@ -48,6 +48,15 @@ NumerotationContext NumerotationContextCommands::next()
|
||||
QStringList str = context_.itemAt(i);
|
||||
setNumStrategy(str.at(0));
|
||||
contextnum << strategy_ -> next(context_, i);
|
||||
|
||||
//Wrap-and-carry: str still holds the pre-increment value, so
|
||||
//this checks the same condition WrapNum::next() used to decide
|
||||
//whether to wrap its own value back to 0.
|
||||
if (str.at(0) == "wrap" && str.size() > 4) {
|
||||
int modulus = str.at(4).toInt();
|
||||
if (modulus > 0 && (str.at(1).toInt() + str.at(2).toInt()) >= modulus)
|
||||
carry(contextnum, i - 1);
|
||||
}
|
||||
}
|
||||
return contextnum;
|
||||
}
|
||||
@@ -64,10 +73,80 @@ NumerotationContext NumerotationContextCommands::previous()
|
||||
QStringList str = context_.itemAt(i);
|
||||
setNumStrategy(str.at(0));
|
||||
contextnum << strategy_ -> previous(context_, i);
|
||||
|
||||
if (str.at(0) == "wrap" && str.size() > 4) {
|
||||
int modulus = str.at(4).toInt();
|
||||
if (modulus > 0 && (str.at(1).toInt() - str.at(2).toInt()) < 0)
|
||||
borrow(contextnum, i - 1);
|
||||
}
|
||||
}
|
||||
return contextnum;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief NumerotationContextCommands::carry
|
||||
Add one unit to the nearest numeric part at or before from_index in
|
||||
contextnum, skipping non-numeric parts (e.g. a "." string separator)
|
||||
along the way. If that part is itself a wrap part and this pushes it
|
||||
to (or past) its own modulus, it wraps back to 0 and the carry
|
||||
cascades further back -- so wrap parts can be chained (e.g. seconds
|
||||
wrapping into minutes wrapping into hours).
|
||||
@param contextnum the context being built by next(); already contains
|
||||
entries for every index <= from_index
|
||||
@param from_index index to start looking from, going backwards
|
||||
*/
|
||||
void NumerotationContextCommands::carry(NumerotationContext &contextnum, int from_index)
|
||||
{
|
||||
for (int j = from_index; j >= 0; --j) {
|
||||
QStringList strl = contextnum.itemAt(j);
|
||||
if (!contextnum.keyIsNumber(strl.at(0)))
|
||||
continue;
|
||||
|
||||
int value = strl.at(1).toInt() + 1;
|
||||
if (strl.at(0) == "wrap" && strl.size() > 4) {
|
||||
int modulus = strl.at(4).toInt();
|
||||
if (modulus > 0 && value >= modulus) {
|
||||
contextnum.replaceValue(j, QString::number(value - modulus));
|
||||
carry(contextnum, j - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
contextnum.replaceValue(j, QString::number(value));
|
||||
return;
|
||||
}
|
||||
//No preceding numeric part: the carry has nowhere to go and is dropped,
|
||||
//same as any other counter in this engine has no overflow tracking
|
||||
//beyond the parts the user actually configured.
|
||||
}
|
||||
|
||||
/**
|
||||
@brief NumerotationContextCommands::borrow
|
||||
Inverse of carry(): subtract one unit from the nearest numeric part at
|
||||
or before from_index. If that part is itself a wrap part and this
|
||||
takes it below 0, it wraps to (modulus - 1) and the borrow cascades
|
||||
further back.
|
||||
*/
|
||||
void NumerotationContextCommands::borrow(NumerotationContext &contextnum, int from_index)
|
||||
{
|
||||
for (int j = from_index; j >= 0; --j) {
|
||||
QStringList strl = contextnum.itemAt(j);
|
||||
if (!contextnum.keyIsNumber(strl.at(0)))
|
||||
continue;
|
||||
|
||||
int value = strl.at(1).toInt() - 1;
|
||||
if (strl.at(0) == "wrap" && strl.size() > 4) {
|
||||
int modulus = strl.at(4).toInt();
|
||||
if (modulus > 0 && value < 0) {
|
||||
contextnum.replaceValue(j, QString::number(value + modulus));
|
||||
borrow(contextnum, j - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
contextnum.replaceValue(j, QString::number(value));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief NumerotationContextCommands::toFinalString
|
||||
@return the string represented by the numerotation context
|
||||
@@ -117,10 +196,18 @@ void NumerotationContextCommands::setNumStrategy(const QString &str) {
|
||||
strategy_ = new HundredFNum (diagram_);
|
||||
return;
|
||||
}
|
||||
else if (str == "wrap") {
|
||||
strategy_ = new WrapNum (diagram_);
|
||||
return;
|
||||
}
|
||||
else if (str == "string") {
|
||||
strategy_ = new StringNum (diagram_);
|
||||
return;
|
||||
}
|
||||
else if (str == "alpha") {
|
||||
strategy_ = new AlphaNum (diagram_);
|
||||
return;
|
||||
}
|
||||
else if (str == "idfolio") {
|
||||
strategy_ = new IdFolioNum (diagram_);
|
||||
return;
|
||||
@@ -431,6 +518,62 @@ NumerotationContext HundredFNum::previous(const NumerotationContext &nc, const i
|
||||
return (previousNumber(nc, i));
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
WrapNum::WrapNum (Diagram *d):
|
||||
NumStrategy (d)
|
||||
{}
|
||||
|
||||
/**
|
||||
@brief WrapNum::toRepresentedString
|
||||
@return the represented string of num
|
||||
*/
|
||||
QString WrapNum::toRepresentedString(const QString num) const
|
||||
{
|
||||
return (num);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief WrapNum::next
|
||||
Wraps this part's own value back to 0 every `modulus` values (carrying
|
||||
into the adjacent part is handled by NumerotationContextCommands::next(),
|
||||
which has visibility into the other parts).
|
||||
@return the next NumerotationContext nc at position i
|
||||
*/
|
||||
NumerotationContext WrapNum::next (const NumerotationContext &nc, const int i) const
|
||||
{
|
||||
QStringList strl = nc.itemAt(i);
|
||||
NumerotationContext newnc;
|
||||
int increase = strl.at(2).toInt();
|
||||
int modulus = strl.size() > 4 ? strl.at(4).toInt() : 0;
|
||||
int new_value = strl.at(1).toInt() + increase;
|
||||
if (modulus > 0)
|
||||
new_value %= modulus;
|
||||
newnc.addValue(strl.at(0), QString::number(new_value), increase, strl.at(3).toInt(), modulus);
|
||||
return (newnc);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief WrapNum::previous
|
||||
@return the previous NumerotationContext nc at posiiton i
|
||||
*/
|
||||
NumerotationContext WrapNum::previous(const NumerotationContext &nc, const int i) const
|
||||
{
|
||||
QStringList strl = nc.itemAt(i);
|
||||
NumerotationContext newnc;
|
||||
int increase = strl.at(2).toInt();
|
||||
int modulus = strl.size() > 4 ? strl.at(4).toInt() : 0;
|
||||
int new_value = strl.at(1).toInt() - increase;
|
||||
if (modulus > 0) {
|
||||
new_value %= modulus;
|
||||
if (new_value < 0)
|
||||
new_value += modulus;
|
||||
}
|
||||
newnc.addValue(strl.at(0), QString::number(new_value), increase, strl.at(3).toInt(), modulus);
|
||||
return (newnc);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
@@ -465,6 +608,120 @@ NumerotationContext StringNum::previous(const NumerotationContext &nc, const int
|
||||
return (nextString(nc, i));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* @brief incrementAlpha
|
||||
* Base-26 letter increment (a, b, ... z, aa, ab, ... az, ba, ...),
|
||||
* the same algorithm as incrementing a spreadsheet column name.
|
||||
* Carries right-to-left on 'z'/'Z' overflow; if the whole string
|
||||
* overflows, a new leading letter is prepended (lowercase 'a').
|
||||
* @param value : current alphabetic value; treated as "a" if empty.
|
||||
* @return the next value.
|
||||
*/
|
||||
QString incrementAlpha(QString value)
|
||||
{
|
||||
if (value.isEmpty()) {
|
||||
return QStringLiteral("a");
|
||||
}
|
||||
|
||||
int i = value.length() - 1;
|
||||
while (i >= 0 && (value.at(i) == QLatin1Char('z') || value.at(i) == QLatin1Char('Z'))) {
|
||||
value[i] = value.at(i).isUpper() ? QLatin1Char('A') : QLatin1Char('a');
|
||||
--i;
|
||||
}
|
||||
if (i < 0) {
|
||||
value.prepend(QLatin1Char('a'));
|
||||
} else {
|
||||
value[i] = QChar(value.at(i).unicode() + 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decrementAlpha
|
||||
* Inverse of incrementAlpha(): borrows right-to-left on 'a'/'A'
|
||||
* underflow. Symmetric shrink case (e.g. "aa" -> "z"): once every
|
||||
* position has borrowed, the leading letter is dropped rather than
|
||||
* left as an extra 'z'. A single-letter value already at "a"/"A" has
|
||||
* no representable predecessor and is left unchanged, the same way
|
||||
* the numeric parts don't clamp but a blank label would be worse
|
||||
* here than a value that stops decreasing.
|
||||
* @param value : current alphabetic value; treated as "a" if empty.
|
||||
* @return the previous value.
|
||||
*/
|
||||
QString decrementAlpha(QString value)
|
||||
{
|
||||
if (value.isEmpty()) {
|
||||
return QStringLiteral("a");
|
||||
}
|
||||
if (value.length() == 1) {
|
||||
//A single letter has no representable predecessor once it
|
||||
//reaches "a"/"A" -- clamp rather than mutate, since the loop
|
||||
//below would otherwise turn it into "z"/"Z" (borrowing past
|
||||
//the only position there is).
|
||||
if (value.at(0) == QLatin1Char('a') || value.at(0) == QLatin1Char('A')) {
|
||||
return value;
|
||||
}
|
||||
return QChar(value.at(0).unicode() - 1);
|
||||
}
|
||||
|
||||
int i = value.length() - 1;
|
||||
while (i >= 0 && (value.at(i) == QLatin1Char('a') || value.at(i) == QLatin1Char('A'))) {
|
||||
value[i] = value.at(i).isUpper() ? QLatin1Char('Z') : QLatin1Char('z');
|
||||
--i;
|
||||
}
|
||||
if (i < 0) {
|
||||
//Every position borrowed: the whole value was "a...a", whose
|
||||
//predecessor is one fewer "z" (e.g. "aa" -> "z").
|
||||
value.remove(0, 1);
|
||||
} else {
|
||||
value[i] = QChar(value.at(i).unicode() - 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
AlphaNum::AlphaNum (Diagram *d):
|
||||
NumStrategy (d)
|
||||
{}
|
||||
|
||||
/**
|
||||
@brief AlphaNum::toRepresentedString
|
||||
@return the represented string of str
|
||||
*/
|
||||
QString AlphaNum::toRepresentedString(const QString str) const
|
||||
{
|
||||
return (str);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AlphaNum::next
|
||||
@return the next NumerotationContext nc at position i
|
||||
*/
|
||||
NumerotationContext AlphaNum::next (const NumerotationContext &nc, const int i) const
|
||||
{
|
||||
QStringList strl = nc.itemAt(i);
|
||||
NumerotationContext newnc;
|
||||
newnc.addValue(strl.at(0), incrementAlpha(strl.at(1)), strl.at(2).toInt());
|
||||
return (newnc);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief AlphaNum::previous
|
||||
@return the previous NumerotationContext nc at posiiton i
|
||||
*/
|
||||
NumerotationContext AlphaNum::previous(const NumerotationContext &nc, const int i) const
|
||||
{
|
||||
QStringList strl = nc.itemAt(i);
|
||||
NumerotationContext newnc;
|
||||
newnc.addValue(strl.at(0), decrementAlpha(strl.at(1)), strl.at(2).toInt());
|
||||
return (newnc);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,8 @@ class NumerotationContextCommands
|
||||
|
||||
private:
|
||||
void setNumStrategy (const QString &);
|
||||
static void carry(NumerotationContext &contextnum, int from_index);
|
||||
static void borrow(NumerotationContext &contextnum, int from_index);
|
||||
|
||||
Diagram *diagram_;
|
||||
NumerotationContext context_;
|
||||
@@ -115,6 +117,24 @@ class HundredFNum: public NumStrategy
|
||||
NumerotationContext previous (const NumerotationContext &, const int) const override;
|
||||
};
|
||||
|
||||
/**
|
||||
@brief The WrapNum class
|
||||
A counter that wraps back to 0 (borrowing from initialvalue on the
|
||||
way down) every `modulus` values, instead of counting up forever like
|
||||
UnitNum/TenNum/HundredNum. Its own next()/previous() only computes its
|
||||
own wrapped value; carrying into (or borrowing from) the preceding
|
||||
numeric part is handled by NumerotationContextCommands::next()/
|
||||
previous(), since only the composition loop can see adjacent parts.
|
||||
*/
|
||||
class WrapNum: public NumStrategy
|
||||
{
|
||||
public:
|
||||
WrapNum (Diagram *);
|
||||
QString toRepresentedString(const QString) const override;
|
||||
NumerotationContext next (const NumerotationContext &, const int) const override;
|
||||
NumerotationContext previous (const NumerotationContext &, const int) const override;
|
||||
};
|
||||
|
||||
class StringNum: public NumStrategy
|
||||
{
|
||||
public:
|
||||
@@ -124,6 +144,23 @@ class StringNum: public NumStrategy
|
||||
NumerotationContext previous (const NumerotationContext &, const int) const override;
|
||||
};
|
||||
|
||||
/**
|
||||
@brief The AlphaNum class
|
||||
Alphabetic auto-numbering (a, b, ... z, aa, ab, ...). Unlike StringNum
|
||||
(a fixed, non-incrementing text segment), this is a real base-26
|
||||
counter: next()/previous() carry/borrow entirely within this part's
|
||||
own value, the same self-contained shape every other incrementing
|
||||
NumStrategy already has.
|
||||
*/
|
||||
class AlphaNum: public NumStrategy
|
||||
{
|
||||
public:
|
||||
AlphaNum (Diagram *);
|
||||
QString toRepresentedString(const QString) const override;
|
||||
NumerotationContext next (const NumerotationContext &, const int) const override;
|
||||
NumerotationContext previous (const NumerotationContext &, const int) const override;
|
||||
};
|
||||
|
||||
class IdFolioNum: public NumStrategy
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "numparteditorw.h"
|
||||
#include "ui_numparteditorw.h"
|
||||
|
||||
#include <QRegularExpressionValidator>
|
||||
|
||||
/**
|
||||
@brief NumPartEditorW::NumPartEditorW
|
||||
Constructor
|
||||
@@ -28,6 +30,7 @@ NumPartEditorW::NumPartEditorW(int type, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::NumPartEditorW),
|
||||
intValidator (new QIntValidator(0,99999,this)),
|
||||
alphaValidator (new QRegularExpressionValidator(QRegularExpression("[A-Za-z]+"), this)),
|
||||
m_edited_type(type)
|
||||
{
|
||||
ui -> setupUi(this);
|
||||
@@ -51,6 +54,7 @@ NumPartEditorW::NumPartEditorW (NumerotationContext &context,
|
||||
QWidget(parent),
|
||||
ui(new Ui::NumPartEditorW),
|
||||
intValidator (new QIntValidator(0,99999,this)),
|
||||
alphaValidator (new QRegularExpressionValidator(QRegularExpression("[A-Za-z]+"), this)),
|
||||
m_edited_type(type)
|
||||
{
|
||||
ui -> setupUi(this);
|
||||
@@ -71,6 +75,10 @@ NumPartEditorW::NumPartEditorW (NumerotationContext &context,
|
||||
setType(NumPartEditorW::hundred, true);
|
||||
else if (strl.at(0)=="hundredfolio")
|
||||
setType(NumPartEditorW::hundredfolio, true);
|
||||
else if (strl.at(0)=="wrap")
|
||||
setType(NumPartEditorW::wrap, true);
|
||||
else if (strl.at(0)=="alpha")
|
||||
setType(NumPartEditorW::alpha);
|
||||
else if (strl.at(0)=="string")
|
||||
setType(NumPartEditorW::string);
|
||||
else if (strl.at(0)=="idfolio")
|
||||
@@ -89,6 +97,8 @@ NumPartEditorW::NumPartEditorW (NumerotationContext &context,
|
||||
setType(NumPartEditorW::elementprefix);
|
||||
ui -> value_field -> setText(strl.at(1));
|
||||
ui -> increase_spinBox -> setValue(strl.at(2).toInt());
|
||||
if (strl.at(0)=="wrap" && strl.size() > 4)
|
||||
ui -> modulus_spinBox -> setValue(strl.at(4).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +108,7 @@ NumPartEditorW::NumPartEditorW (NumerotationContext &context,
|
||||
NumPartEditorW::~NumPartEditorW()
|
||||
{
|
||||
delete intValidator;
|
||||
delete alphaValidator;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@@ -110,6 +121,8 @@ void NumPartEditorW::setVisibleItems()
|
||||
items << tr("Chiffre 1")
|
||||
<< tr("Chiffre 01")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Alphabétique")
|
||||
<< tr("Texte");
|
||||
}
|
||||
else if (m_edited_type == 1)
|
||||
@@ -120,6 +133,8 @@ void NumPartEditorW::setVisibleItems()
|
||||
<< tr("Chiffre 01 - Folio")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Chiffre 001 - Folio")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Alphabétique")
|
||||
<< tr("Texte")
|
||||
<< tr("N° folio")
|
||||
<< tr("Folio")
|
||||
@@ -133,6 +148,8 @@ void NumPartEditorW::setVisibleItems()
|
||||
<< tr("Chiffre 01 - Folio")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Chiffre 001 - Folio")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Alphabétique")
|
||||
<< tr("Texte")
|
||||
<< tr("N° folio")
|
||||
<< tr("Folio")
|
||||
@@ -195,6 +212,12 @@ NumerotationContext NumPartEditorW::toNumContext()
|
||||
case elementprefix:
|
||||
type_str = "elementprefix";
|
||||
break;
|
||||
case wrap:
|
||||
type_str = "wrap";
|
||||
break;
|
||||
case alpha:
|
||||
type_str = "alpha";
|
||||
break;
|
||||
}
|
||||
if (type_str == "unitfolio"
|
||||
|| type_str == "tenfolio"
|
||||
@@ -203,6 +226,12 @@ NumerotationContext NumPartEditorW::toNumContext()
|
||||
ui -> value_field -> displayText(),
|
||||
ui -> increase_spinBox -> value(),
|
||||
ui->value_field->displayText().toInt());
|
||||
else if (type_str == "wrap")
|
||||
nc.addValue(type_str,
|
||||
ui -> value_field -> displayText(),
|
||||
ui -> increase_spinBox -> value(),
|
||||
0,
|
||||
ui -> modulus_spinBox -> value());
|
||||
else
|
||||
nc.addValue(type_str,
|
||||
ui -> value_field -> displayText(),
|
||||
@@ -260,6 +289,10 @@ void NumPartEditorW::on_type_cb_activated(int) {
|
||||
setType(elementcolumn);
|
||||
else if (ui->type_cb->currentText() == tr("Element Prefix"))
|
||||
setType(elementprefix);
|
||||
else if (ui->type_cb->currentText() == tr("Cyclique (modulo)"))
|
||||
setType(wrap);
|
||||
else if (ui->type_cb->currentText() == tr("Alphabétique"))
|
||||
setType(alpha);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
@@ -280,6 +313,14 @@ void NumPartEditorW::on_increase_spinBox_valueChanged(int) {
|
||||
if (!ui -> value_field -> text().isEmpty()) emit changed();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief NumPartEditorW::on_modulus_spinBox_valueChanged
|
||||
emit changed when modulus_spinBox value changed
|
||||
*/
|
||||
void NumPartEditorW::on_modulus_spinBox_valueChanged(int) {
|
||||
if (!ui -> value_field -> text().isEmpty()) emit changed();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief NumPartEditorW::setType
|
||||
Set good behavior by type t
|
||||
@@ -299,6 +340,7 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
|| t==tenfolio
|
||||
|| t==hundred
|
||||
|| t==hundredfolio
|
||||
|| t==wrap
|
||||
)
|
||||
&& (type_==string
|
||||
|| type_==folio
|
||||
@@ -317,9 +359,12 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
ui -> value_field -> setValidator(intValidator);
|
||||
ui -> increase_spinBox -> setEnabled(true);
|
||||
ui -> increase_spinBox -> setValue(1);
|
||||
if (t == wrap)
|
||||
ui -> modulus_spinBox -> setValue(8);
|
||||
}
|
||||
//@t isn't a numeric type
|
||||
else if (t == string
|
||||
|| t == alpha
|
||||
|| t == folio
|
||||
|| t == idfolio
|
||||
|| t == elementline
|
||||
@@ -333,6 +378,13 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
ui -> value_field -> setValidator(nullptr);
|
||||
ui -> value_field -> setEnabled(true);
|
||||
}
|
||||
else if (t==alpha) {
|
||||
//Alphabetic step is always exactly one letter (a, b, ...);
|
||||
//there is no numeric "increase" to configure, unlike the
|
||||
//digit-based part types.
|
||||
ui -> value_field -> setValidator(alphaValidator);
|
||||
ui -> value_field -> setEnabled(true);
|
||||
}
|
||||
else if (t==folio) {
|
||||
ui -> value_field -> setDisabled(true);
|
||||
ui -> increase_spinBox -> setDisabled(true);
|
||||
@@ -362,6 +414,7 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
ui -> increase_spinBox -> setDisabled(true);
|
||||
}
|
||||
}
|
||||
ui -> modulus_spinBox -> setEnabled(t == wrap);
|
||||
type_= t;
|
||||
}
|
||||
|
||||
@@ -384,6 +437,8 @@ void NumPartEditorW::setCurrentIndex(NumPartEditorW::type t) {
|
||||
i = ui->type_cb->findText(tr("Chiffre 001"));
|
||||
else if (t == hundredfolio)
|
||||
i = ui->type_cb->findText(tr("Chiffre 001 - Folio"));
|
||||
else if (t == alpha)
|
||||
i = ui->type_cb->findText(tr("Alphabétique"));
|
||||
else if (t == string)
|
||||
i = ui->type_cb->findText(tr("Texte"));
|
||||
else if (t == idfolio)
|
||||
@@ -400,5 +455,7 @@ void NumPartEditorW::setCurrentIndex(NumPartEditorW::type t) {
|
||||
i = ui->type_cb->findText(tr("Element Column"));
|
||||
else if (t == elementprefix)
|
||||
i = ui->type_cb->findText(tr("Element Prefix"));
|
||||
else if (t == wrap)
|
||||
i = ui->type_cb->findText(tr("Cyclique (modulo)"));
|
||||
ui->type_cb->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,10 @@ class NumPartEditorW : public QWidget
|
||||
~NumPartEditorW() override;
|
||||
|
||||
enum type {unit,unitfolio,ten,tenfolio, hundred, hundredfolio,
|
||||
alpha,
|
||||
string,idfolio,folio,plant,locmach,
|
||||
elementline,elementcolumn,elementprefix,
|
||||
wrap,
|
||||
};
|
||||
NumerotationContext toNumContext();
|
||||
bool isValid ();
|
||||
@@ -63,6 +65,7 @@ class NumPartEditorW : public QWidget
|
||||
void on_type_cb_activated(int);
|
||||
void on_value_field_textEdited();
|
||||
void on_increase_spinBox_valueChanged(int);
|
||||
void on_modulus_spinBox_valueChanged(int);
|
||||
void setType (NumPartEditorW::type t, bool=false);
|
||||
|
||||
signals:
|
||||
@@ -71,6 +74,7 @@ class NumPartEditorW : public QWidget
|
||||
private:
|
||||
Ui::NumPartEditorW *ui;
|
||||
QValidator *intValidator;
|
||||
QValidator *alphaValidator;
|
||||
int m_edited_type = -1; ///<0 == element : 1 == conductor : 2 == folio
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,9 @@
|
||||
<property name="wrapping">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Mettre à 0 pour un chiffre qui n'avance que par le report d'un chiffre cyclique suivant (ex: le "0" de "0.7")</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
@@ -88,7 +91,38 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="modulus_spinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Valeur à laquelle ce chiffre revient à 0 en incrémentant le chiffre précédent (0 = pas de cycle)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>mod. </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -388,9 +388,15 @@ void projectDataBase::createElementNomenclatureView()
|
||||
"ei.supplier_auxiliary4 AS supplier_auxiliary4,"
|
||||
"ei.quantity_auxiliary4 AS quantity_auxiliary4,"
|
||||
"ei.unity_auxiliary4 AS unity_auxiliary4,"
|
||||
"ei.exclude_from_bom AS exclude_from_bom,"
|
||||
|
||||
"d.pos AS diagram_position,"
|
||||
"ei.exclude_from_bom AS exclude_from_bom,"
|
||||
|
||||
"ei.plc_type AS plc_type,"
|
||||
"ei.plc_address AS plc_address,"
|
||||
"ei.plc_function AS plc_function,"
|
||||
"ei.plc_comment AS plc_comment,"
|
||||
"ei.plc_crossref AS plc_crossref,"
|
||||
|
||||
"d.pos AS diagram_position,"
|
||||
"e.type AS element_type,"
|
||||
"e.sub_type AS element_sub_type,"
|
||||
"di.title AS title,"
|
||||
|
||||
@@ -47,6 +47,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
|
||||
m_button_group.addButton(ui->m_coil_cb, 4);
|
||||
m_button_group.addButton(ui->m_protection_cb, 5);
|
||||
m_button_group.addButton(ui->m_thumbnail_cb, 6);
|
||||
m_button_group.addButton(ui->m_plc_cb, 7);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // ### Qt 6: remove
|
||||
connect(&m_button_group, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), [this](int id)
|
||||
#else
|
||||
@@ -76,7 +77,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
|
||||
else
|
||||
{
|
||||
int checked = 0;
|
||||
for (int i=1 ; i<7 ; ++i) {
|
||||
for (int i=1 ; i<8 ; ++i) {
|
||||
if (m_button_group.button(i)->isChecked()) {++checked;}
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
|
||||
case 0 :
|
||||
check_box->setCheckState(Qt::Unchecked);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
check_box->setCheckState(Qt::Checked);
|
||||
break;
|
||||
default:
|
||||
@@ -187,12 +188,16 @@ void ElementQueryWidget::setQuery(const QString &query)
|
||||
if (ui->m_protection_cb) {
|
||||
++c;
|
||||
}
|
||||
ui->m_thumbnail_cb->setChecked (str_type.contains(ElementData::typeToString(ElementData::Thumbnail)) ? true : false);
|
||||
if (ui->m_thumbnail_cb->isChecked()) {
|
||||
++c;
|
||||
}
|
||||
ui->m_thumbnail_cb->setChecked (str_type.contains(ElementData::typeToString(ElementData::Thumbnail)) ? true : false);
|
||||
if (ui->m_thumbnail_cb->isChecked()) {
|
||||
++c;
|
||||
}
|
||||
ui->m_plc_cb->setChecked (str_type.contains(ElementData::masterTypeToString(ElementData::PLC)) ? true : false);
|
||||
if (ui->m_plc_cb->isChecked()) {
|
||||
++c;
|
||||
}
|
||||
|
||||
if (c == 6) {
|
||||
if (c == 7) {
|
||||
ui->m_all_cb->setCheckState(Qt::Checked);
|
||||
} else if (c > 0) {
|
||||
ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
|
||||
@@ -366,6 +371,11 @@ QString ElementQueryWidget::queryStr() const
|
||||
if (ui->m_protection_cb->isChecked()) {
|
||||
if (b) where +=" OR";
|
||||
where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::Protection) += "'";
|
||||
b = true;
|
||||
}
|
||||
if (ui->m_plc_cb->isChecked()) {
|
||||
if (b) where +=" OR";
|
||||
where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::PLC) += "'";
|
||||
}
|
||||
where.append(")");
|
||||
|
||||
|
||||
@@ -234,86 +234,96 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Type d'éléments</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="m_simple_cb">
|
||||
<property name="text">
|
||||
<string>Simples</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="m_protection_cb">
|
||||
<property name="text">
|
||||
<string>Organes de protection</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="m_all_cb">
|
||||
<property name="text">
|
||||
<string>Tous</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="m_button_cb">
|
||||
<property name="text">
|
||||
<string>Boutons et commutateurs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_terminal_cb">
|
||||
<property name="text">
|
||||
<string>Borniers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_thumbnail_cb">
|
||||
<property name="text">
|
||||
<string>Vignettes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="m_coil_cb">
|
||||
<property name="text">
|
||||
<string>Contacteurs et relais</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Type d'éléments</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="m_all_cb">
|
||||
<property name="text">
|
||||
<string>Tous</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="m_simple_cb">
|
||||
<property name="text">
|
||||
<string>Simples</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_terminal_cb">
|
||||
<property name="text">
|
||||
<string>Borniers</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="m_protection_cb">
|
||||
<property name="text">
|
||||
<string>Organes de protection</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_coil_cb">
|
||||
<property name="text">
|
||||
<string>Contacteurs et relais</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="m_thumbnail_cb">
|
||||
<property name="text">
|
||||
<string>Vignettes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="m_button_cb">
|
||||
<property name="text">
|
||||
<string>Boutons et commutateurs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="m_plc_cb">
|
||||
<property name="text">
|
||||
<string>Automates (MAE/SPS)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -240,7 +240,12 @@ void DynamicTextFieldEditor::fillInfoComboBox()
|
||||
QETInformation::ELMT_PLC_ADDRESS,
|
||||
QETInformation::ELMT_PLC_FUNCTION,
|
||||
QETInformation::ELMT_PLC_COMMENT,
|
||||
QETInformation::ELMT_PLC_CROSSREF
|
||||
QETInformation::ELMT_PLC_CROSSREF,
|
||||
QETInformation::ELMT_PLC_TC,
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
};
|
||||
strl = plc_keys + strl;
|
||||
} else {
|
||||
@@ -249,6 +254,11 @@ void DynamicTextFieldEditor::fillInfoComboBox()
|
||||
strl.removeAll(QETInformation::ELMT_PLC_FUNCTION);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_COMMENT);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_CROSSREF);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_TC);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_T1);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_T2);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_T3);
|
||||
strl.removeAll(QETInformation::ELMT_PLC_T4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -683,7 +683,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
|
||||
m_plc_table->horizontalHeader()->resizeSection(2, 150);
|
||||
m_plc_table->horizontalHeader()->resizeSection(3, 150);
|
||||
m_plc_table->horizontalHeader()->resizeSection(4, 100);
|
||||
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_plc_table->setMinimumHeight(200);
|
||||
tables_splitter->addWidget(m_plc_table);
|
||||
@@ -697,7 +697,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
|
||||
m_plc_terminal_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
|
||||
m_plc_terminal_table->horizontalHeader()->resizeSection(0, 50);
|
||||
m_plc_terminal_table->horizontalHeader()->resizeSection(1, 80);
|
||||
m_plc_terminal_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_plc_terminal_table->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
m_plc_terminal_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_plc_terminal_table->setMinimumHeight(200);
|
||||
tables_splitter->addWidget(m_plc_terminal_table);
|
||||
@@ -780,7 +780,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
|
||||
|
||||
auto *sb = new QSpinBox(m_plc_gb);
|
||||
sb->setMinimum(10);
|
||||
sb->setMaximum(200);
|
||||
sb->setMaximum(500);
|
||||
sb->setValue(40);
|
||||
sb->setSuffix(tr(" mm"));
|
||||
m_plc_col_width_spinboxes.append(sb);
|
||||
|
||||
@@ -56,6 +56,14 @@ ElementsPanel::ElementsPanel(QWidget *parent) :
|
||||
|
||||
// force du noir sur une alternance de blanc (comme le schema) et de gris
|
||||
// clair, avec du blanc sur bleu pas trop fonce pour la selection
|
||||
//
|
||||
// Element icons are rendered with colors read directly from each .elmt
|
||||
// file (almost always black linework, matching printed-schematic
|
||||
// convention) onto a transparent background -- so this view must keep
|
||||
// a light background regardless of the OS/desktop theme, or the icons
|
||||
// become invisible on dark themes. QAbstractItemView paints its rows
|
||||
// using the viewport's palette, not the view's own, so the palette
|
||||
// must be applied to both to actually take effect under every style.
|
||||
QPalette qp = palette();
|
||||
qp.setColor(QPalette::Text, Qt::black);
|
||||
qp.setColor(QPalette::Base, Qt::white);
|
||||
@@ -63,6 +71,7 @@ ElementsPanel::ElementsPanel(QWidget *parent) :
|
||||
qp.setColor(QPalette::Highlight, QColor("#678db2"));
|
||||
qp.setColor(QPalette::HighlightedText, Qt::black);
|
||||
setPalette(qp);
|
||||
viewport()->setPalette(qp);
|
||||
|
||||
// we handle double click on items ourselves
|
||||
connect(this, &ElementsPanel::itemDoubleClicked, this, &ElementsPanel::slot_doubleClick);
|
||||
|
||||
@@ -40,10 +40,12 @@
|
||||
#include "recentfiles.h"
|
||||
#include "shortcutmanager.h"
|
||||
#include "ui/bomexportdialog.h"
|
||||
#include "ui/jumptoelementdialog.h"
|
||||
#include "ui/diagrampropertieseditordockwidget.h"
|
||||
#include "ui/backupdialog.h"
|
||||
#include "ui/dialogwaiting.h"
|
||||
#include "undocommand/addelementtextcommand.h"
|
||||
#include "utils/qetutils.h"
|
||||
#include "undocommand/rotateselectioncommand.h"
|
||||
#include "undocommand/rotatetextscommand.h"
|
||||
#include "diagram.h"
|
||||
@@ -748,6 +750,19 @@ void QETDiagramEditor::setUpActions()
|
||||
this->m_search_and_replace_widget.setHidden(!m_search_and_replace_widget.isHidden());
|
||||
}
|
||||
});
|
||||
|
||||
m_jump_to_element = new QAction(tr("Atteindre un élément"), this);
|
||||
m_jump_to_element->setShortcut(Qt::CTRL | Qt::Key_G);
|
||||
m_jump_to_element->setStatusTip(tr("Recherche et sélectionne rapidement un élément du folio", "status bar tip"));
|
||||
connect(m_jump_to_element, &QAction::triggered, [this]()
|
||||
{
|
||||
DiagramView *diagram_view = this->currentDiagramView();
|
||||
if (!diagram_view || !diagram_view->diagram()) {
|
||||
return;
|
||||
}
|
||||
JumpToElementDialog dialog(diagram_view->diagram(), this);
|
||||
dialog.exec();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -862,6 +877,7 @@ void QETDiagramEditor::setUpMenu()
|
||||
menu_edition -> addActions(m_depth_action_group->actions());
|
||||
menu_edition -> addSeparator();
|
||||
menu_edition -> addAction(m_find);
|
||||
menu_edition -> addAction(m_jump_to_element);
|
||||
|
||||
// menu Projet
|
||||
menu_project -> addAction(m_project_edit_properties);
|
||||
@@ -1169,6 +1185,13 @@ bool QETDiagramEditor::openAndAddProject(
|
||||
//Create the project
|
||||
DialogWaiting::instance(this);
|
||||
|
||||
//Per-project window for the font counters reported below; the folios
|
||||
//(and with them the stored font descriptions) are built between here
|
||||
//and the end of addProject(). RAII, because DialogWaiting pumps the
|
||||
//event loop during the load: a nested openAndAddProject() gets its
|
||||
//own window and this one resumes unharmed.
|
||||
QETUtils::FontRestorationScope font_scope;
|
||||
|
||||
QETProject *project = new QETProject(filepath);
|
||||
if (project -> state() != QETProject::Ok)
|
||||
{
|
||||
@@ -1195,6 +1218,42 @@ bool QETDiagramEditor::openAndAddProject(
|
||||
addProject(project);
|
||||
DialogWaiting::dropInstance();
|
||||
|
||||
//Report font descriptions which could not be read as-is (written by
|
||||
//an incompatible Qt version or corrupted), so the user learns about
|
||||
//it from somewhere else than the console. See issue #553.
|
||||
const int salvaged_fonts = font_scope.salvaged();
|
||||
const int unreadable_fonts = font_scope.unreadable();
|
||||
if (salvaged_fonts || unreadable_fonts)
|
||||
{
|
||||
qInfo().nospace() << "Project font descriptions: "
|
||||
<< salvaged_fonts << " salvaged from a foreign format, "
|
||||
<< unreadable_fonts << " unreadable (default font applies)";
|
||||
}
|
||||
if (interactive && (salvaged_fonts || unreadable_fonts))
|
||||
{
|
||||
QStringList details;
|
||||
if (salvaged_fonts) {
|
||||
details << tr("%n description(s) de police écrite(s) dans un "
|
||||
"format étranger ou corrompu ont été restaurée(s). "
|
||||
"Elles seront réécrites dans un format stable au "
|
||||
"prochain enregistrement du projet.",
|
||||
"message box content",
|
||||
salvaged_fonts);
|
||||
}
|
||||
if (unreadable_fonts) {
|
||||
details << tr("%n description(s) de police n'ont pas pu être "
|
||||
"lue(s) ; la police par défaut sera utilisée pour "
|
||||
"ces textes.",
|
||||
"message box content",
|
||||
unreadable_fonts);
|
||||
}
|
||||
QET::QetMessageBox::information(
|
||||
this,
|
||||
tr("Polices du projet", "message box title"),
|
||||
details.join("\n\n")
|
||||
);
|
||||
}
|
||||
|
||||
BackupDialog backup_dialog(this);
|
||||
if (backup_dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
|
||||
@@ -222,7 +222,8 @@ class QETDiagramEditor : public QETMainWindow
|
||||
*m_close_file, ///< Close current project file
|
||||
*m_save_file, ///< Save current project
|
||||
*m_save_file_as, ///< Save current project as a specific file
|
||||
*m_find = nullptr;
|
||||
*m_find = nullptr,
|
||||
*m_jump_to_element = nullptr; ///< Open the "jump to element" quick-open popup
|
||||
|
||||
QList <QAction *> m_zoom_action_toolBar; ///Only zoom action must displayed in the toolbar
|
||||
|
||||
|
||||
@@ -1396,6 +1396,27 @@ void Element::setElementInformations(DiagramContext dc)
|
||||
m_data.m_informations.addValue(QStringLiteral("label"), actual_label); //Update the label if there is a formula
|
||||
}
|
||||
emit elementInfoChange(old_info, m_data.m_informations);
|
||||
|
||||
// Propagate label change to linked PLC slaves (label is changed via
|
||||
// setElementInformations through the undo stack, not via setElementData)
|
||||
if (m_data.m_type == ElementData::Master && m_data.m_master_type == ElementData::PLC)
|
||||
{
|
||||
if (!m_group_index_map.isEmpty())
|
||||
{
|
||||
const QString new_label = actualLabel();
|
||||
for (auto it = m_group_index_map.constBegin(); it != m_group_index_map.constEnd(); ++it)
|
||||
{
|
||||
Element *slave = it.key();
|
||||
if (!slave)
|
||||
continue;
|
||||
if (slave->elementInformations().value(QETInformation::ELMT_LABEL).toString() == new_label)
|
||||
continue;
|
||||
DiagramContext ctx = slave->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_LABEL, new_label);
|
||||
slave->setElementInformations(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1433,7 +1454,9 @@ void Element::setElementData(ElementData data)
|
||||
{
|
||||
const auto &new_plc = m_data.plcMasterData();
|
||||
bool plc_changed = (old_plc.ios != new_plc.ios);
|
||||
if (plc_changed && !m_group_index_map.isEmpty())
|
||||
bool label_changed = (old_info.value(QStringLiteral("label")) !=
|
||||
m_data.m_informations.value(QStringLiteral("label")));
|
||||
if (!m_group_index_map.isEmpty() && (plc_changed || label_changed))
|
||||
{
|
||||
for (auto it = m_group_index_map.constBegin(); it != m_group_index_map.constEnd(); ++it)
|
||||
{
|
||||
@@ -1442,24 +1465,64 @@ void Element::setElementData(ElementData data)
|
||||
if (!slave || io_idx < 0 || io_idx >= new_plc.ios.size())
|
||||
continue;
|
||||
const auto &io = new_plc.ios.at(io_idx);
|
||||
DiagramContext ctx = slave->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TYPE,
|
||||
ElementData::translatedPlcIOType(io.type));
|
||||
ctx.addValue(QETInformation::ELMT_PLC_ADDRESS, io.address);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_FUNCTION, io.functionText);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_COMMENT, io.comment);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_CROSSREF,
|
||||
[&]() -> QString {
|
||||
if (!diagram() || !diagram()->project())
|
||||
return QString();
|
||||
XRefProperties xrp = diagram()->project()
|
||||
->defaultXRefProperties("plc");
|
||||
autonum::sequentialNumbers seq;
|
||||
return autonum::AssignVariables::formulaToLabel(
|
||||
xrp.slaveLabel(), seq, diagram(), this);
|
||||
}());
|
||||
ctx.addValue(QETInformation::ELMT_LABEL, actualLabel());
|
||||
slave->setElementInformations(ctx);
|
||||
|
||||
if (plc_changed)
|
||||
{
|
||||
DiagramContext ctx = slave->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TYPE,
|
||||
ElementData::translatedPlcIOType(io.type));
|
||||
ctx.addValue(QETInformation::ELMT_PLC_ADDRESS, io.address);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_FUNCTION, io.functionText);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_COMMENT, io.comment);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_CROSSREF,
|
||||
[&]() -> QString {
|
||||
if (!diagram() || !diagram()->project())
|
||||
return QString();
|
||||
XRefProperties xrp = diagram()->project()
|
||||
->defaultXRefProperties("plc");
|
||||
autonum::sequentialNumbers seq;
|
||||
return autonum::AssignVariables::formulaToLabel(
|
||||
xrp.slaveLabel(), seq, diagram(), this);
|
||||
}());
|
||||
ctx.addValue(QETInformation::ELMT_LABEL, actualLabel());
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TC,
|
||||
QString::number(io.terminalCount));
|
||||
for (int t = 0; t < io.terminalCount && t < 4; ++t)
|
||||
{
|
||||
QString val = (t < io.terminals.size())
|
||||
? io.terminals.at(t) : QString();
|
||||
ctx.addValue(
|
||||
QStringList({
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
}).at(t), val);
|
||||
}
|
||||
slave->setElementInformations(ctx);
|
||||
|
||||
// Update master labels on slave terminals
|
||||
QList<Terminal *> slave_terms = slave->terminals();
|
||||
for (int t = 0; t < slave_terms.size(); ++t)
|
||||
{
|
||||
if (t < io.terminals.size())
|
||||
{
|
||||
slave_terms.at(t)->setUseMasterLabel(true);
|
||||
slave_terms.at(t)->setMasterLabelIndex(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
slave_terms.at(t)->setUseMasterLabel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (label_changed)
|
||||
{
|
||||
// Only label changed, update the label on the slave
|
||||
DiagramContext ctx = slave->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_LABEL, actualLabel());
|
||||
slave->setElementInformations(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1900,7 +1963,10 @@ void Element::drawPlcTable(QPainter *painter)
|
||||
}
|
||||
|
||||
QRectF text_rect = cr.adjusted(1, 0, -1, 0);
|
||||
painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter, cell_text);
|
||||
painter->save();
|
||||
painter->setClipRect(text_rect, Qt::IntersectClip);
|
||||
painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, cell_text);
|
||||
painter->restore();
|
||||
|
||||
cx += col_widths[col];
|
||||
}
|
||||
|
||||
@@ -289,8 +289,17 @@ void Terminal::paint(
|
||||
painter->save();
|
||||
painter->translate(label_pos);
|
||||
painter->rotate(d->m_label_rotation);
|
||||
QRectF text_rect(-text_size.width()/2.0, -text_size.height()/2.0,
|
||||
text_size.width(), text_size.height());
|
||||
|
||||
qreal rx = 0, ry = 0;
|
||||
if (d->m_label_halignment & Qt::AlignLeft) rx = 0;
|
||||
else if (d->m_label_halignment & Qt::AlignHCenter) rx = -text_size.width() / 2.0;
|
||||
else if (d->m_label_halignment & Qt::AlignRight) rx = -text_size.width();
|
||||
|
||||
if (d->m_label_valignment & Qt::AlignTop) ry = 0;
|
||||
else if (d->m_label_valignment & Qt::AlignVCenter) ry = -text_size.height() / 2.0;
|
||||
else if (d->m_label_valignment & Qt::AlignBottom) ry = -text_size.height();
|
||||
|
||||
QRectF text_rect(QPointF(rx, ry), text_size);
|
||||
painter->drawText(text_rect, static_cast<int>(d->m_label_halignment | d->m_label_valignment), display_name);
|
||||
painter->restore();
|
||||
} else {
|
||||
@@ -307,7 +316,7 @@ void Terminal::paint(
|
||||
if (d->m_label_frame) {
|
||||
painter->drawRect(text_rect.adjusted(-1, -1, 1, 1));
|
||||
}
|
||||
painter->drawText(text_rect, static_cast<int>(Qt::AlignLeft | Qt::AlignTop), display_name);
|
||||
painter->drawText(text_rect, static_cast<int>(d->m_label_halignment | d->m_label_valignment), display_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -816,12 +825,24 @@ QString Terminal::name() const
|
||||
if (elmt->linkType() == Element::Master) {
|
||||
int group_idx = elmt->groupIndexForElement(parent_element_);
|
||||
if (group_idx >= 0) {
|
||||
const auto &groups = elmt->elementData().m_slave_contact_groups;
|
||||
if (group_idx < groups.size()) {
|
||||
int label_idx = d->m_master_label_index;
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
if (label_idx >= 0 && label_idx < labels.size()) {
|
||||
return labels.at(label_idx);
|
||||
// For PLC masters, use io.terminals as labels
|
||||
if (elmt->elementData().m_master_type == ElementData::PLC) {
|
||||
const auto &plc_data = elmt->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size()) {
|
||||
int label_idx = d->m_master_label_index;
|
||||
const QStringList &labels = plc_data.ios.at(group_idx).terminals;
|
||||
if (label_idx >= 0 && label_idx < labels.size()) {
|
||||
return labels.at(label_idx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto &groups = elmt->elementData().m_slave_contact_groups;
|
||||
if (group_idx < groups.size()) {
|
||||
int label_idx = d->m_master_label_index;
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
if (label_idx >= 0 && label_idx < labels.size()) {
|
||||
return labels.at(label_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -832,6 +853,16 @@ QString Terminal::name() const
|
||||
return d->m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Terminal::baseName
|
||||
Return the original terminal name (T1, T2...) without master label override.
|
||||
Used for sorting when linking.
|
||||
*/
|
||||
QString Terminal::baseName() const
|
||||
{
|
||||
return d->m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Terminal::terminalType
|
||||
@return the type of this terminal (Generic, Inner, Outer, No, Nc, Common)
|
||||
|
||||
@@ -76,6 +76,7 @@ class Terminal : public QGraphicsObject
|
||||
Element *parentElement () const;
|
||||
QUuid uuid () const;
|
||||
QString name () const;
|
||||
QString baseName () const;
|
||||
TerminalData::Type terminalType() const;
|
||||
bool useMasterLabel() const { return d->m_use_master_label; }
|
||||
void setUseMasterLabel(bool use);
|
||||
|
||||
@@ -130,6 +130,11 @@ namespace QETInformation
|
||||
static QString ELMT_PLC_FUNCTION = "plc_function";
|
||||
static QString ELMT_PLC_COMMENT = "plc_comment";
|
||||
static QString ELMT_PLC_CROSSREF = "plc_crossref";
|
||||
static QString ELMT_PLC_TC = "plc_tc";
|
||||
static QString ELMT_PLC_T1 = "plc_t1";
|
||||
static QString ELMT_PLC_T2 = "plc_t2";
|
||||
static QString ELMT_PLC_T3 = "plc_t3";
|
||||
static QString ELMT_PLC_T4 = "plc_t4";
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
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 "jumptoelementdialog.h"
|
||||
|
||||
#include "../diagram.h"
|
||||
#include "../qetgraphicsitem/element.h"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
/**
|
||||
@brief JumpToElementDialog::JumpToElementDialog
|
||||
@param diagram : the diagram whose elements can be jumped to
|
||||
@param parent
|
||||
*/
|
||||
JumpToElementDialog::JumpToElementDialog(Diagram *diagram, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
m_diagram(diagram)
|
||||
{
|
||||
setWindowTitle(tr("Atteindre un élément", "window title"));
|
||||
|
||||
m_filter_edit = new QLineEdit(this);
|
||||
m_filter_edit->setPlaceholderText(tr("Nom, label ou information de l'élément…"));
|
||||
m_filter_edit->installEventFilter(this);
|
||||
|
||||
m_result_list = new QListWidget(this);
|
||||
m_result_list->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
auto *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_filter_edit);
|
||||
layout->addWidget(m_result_list);
|
||||
setLayout(layout);
|
||||
resize(420, 320);
|
||||
|
||||
connect(m_filter_edit, &QLineEdit::textChanged, this, &JumpToElementDialog::updateFilteredList);
|
||||
connect(m_result_list, &QListWidget::itemActivated, this, &JumpToElementDialog::activateCurrentItem);
|
||||
|
||||
buildCandidates();
|
||||
updateFilteredList(QString());
|
||||
m_filter_edit->setFocus();
|
||||
}
|
||||
|
||||
JumpToElementDialog::~JumpToElementDialog()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
@brief JumpToElementDialog::buildCandidates
|
||||
Collect every element on m_diagram into m_candidates, along with the
|
||||
searchable text used to filter it (its type name, its label, and its
|
||||
other element informations).
|
||||
*/
|
||||
void JumpToElementDialog::buildCandidates()
|
||||
{
|
||||
m_candidates.clear();
|
||||
if (!m_diagram) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto item : m_diagram->items()) {
|
||||
Element *element = qgraphicsitem_cast<Element *>(item);
|
||||
if (!element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QString label = element->elementInformations().value(QStringLiteral("label")).toString();
|
||||
const QString name = element->name();
|
||||
|
||||
Candidate candidate;
|
||||
candidate.element = element;
|
||||
candidate.display_text = label.isEmpty() ? name : (label + QStringLiteral(" — ") + name);
|
||||
|
||||
QStringList search_parts;
|
||||
search_parts << label << name;
|
||||
const DiagramContext infos = element->elementInformations();
|
||||
for (const QString &key : infos.keys()) {
|
||||
search_parts << infos.value(key).toString();
|
||||
}
|
||||
candidate.search_text = search_parts.join(QLatin1Char(' ')).toLower();
|
||||
|
||||
m_candidates << candidate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief JumpToElementDialog::updateFilteredList
|
||||
Refill m_result_list with every candidate whose search text contains
|
||||
@a filter_text (case-insensitive), and select the first match.
|
||||
@param filter_text
|
||||
*/
|
||||
void JumpToElementDialog::updateFilteredList(const QString &filter_text)
|
||||
{
|
||||
m_result_list->clear();
|
||||
|
||||
const QString needle = filter_text.trimmed().toLower();
|
||||
for (int i = 0; i < m_candidates.size(); ++i) {
|
||||
const Candidate &candidate = m_candidates.at(i);
|
||||
if (!candidate.element) {
|
||||
continue;
|
||||
}
|
||||
if (!needle.isEmpty() && !candidate.search_text.contains(needle)) {
|
||||
continue;
|
||||
}
|
||||
auto *list_item = new QListWidgetItem(candidate.display_text, m_result_list);
|
||||
list_item->setData(Qt::UserRole, i);
|
||||
}
|
||||
|
||||
if (m_result_list->count() > 0) {
|
||||
m_result_list->setCurrentRow(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief JumpToElementDialog::activateCurrentItem
|
||||
Select the element corresponding to the currently highlighted result
|
||||
on the diagram, scroll it into view, and close this dialog.
|
||||
*/
|
||||
void JumpToElementDialog::activateCurrentItem()
|
||||
{
|
||||
QListWidgetItem *current = m_result_list->currentItem();
|
||||
if (!current || !m_diagram) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
const int index = current->data(Qt::UserRole).toInt();
|
||||
if (index < 0 || index >= m_candidates.size()) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
Element *element = m_candidates.at(index).element;
|
||||
if (!element) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
m_diagram->clearSelection();
|
||||
element->setSelected(true);
|
||||
element->ensureVisible();
|
||||
accept();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief JumpToElementDialog::eventFilter
|
||||
Redirect Up/Down/Enter/Escape typed in the filter field to the result
|
||||
list, so the user never has to leave the text field to navigate or
|
||||
confirm a choice.
|
||||
*/
|
||||
bool JumpToElementDialog::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == m_filter_edit && event->type() == QEvent::KeyPress) {
|
||||
auto *key_event = static_cast<QKeyEvent *>(event);
|
||||
switch (key_event->key()) {
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Up: {
|
||||
const int row_count = m_result_list->count();
|
||||
if (row_count == 0) {
|
||||
return true;
|
||||
}
|
||||
int row = m_result_list->currentRow();
|
||||
row = key_event->key() == Qt::Key_Down
|
||||
? (row + 1) % row_count
|
||||
: (row - 1 + row_count) % row_count;
|
||||
m_result_list->setCurrentRow(row);
|
||||
return true;
|
||||
}
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
activateCurrentItem();
|
||||
return true;
|
||||
case Qt::Key_Escape:
|
||||
reject();
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QDialog::eventFilter(watched, event);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
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 JUMPTOELEMENTDIALOG_H
|
||||
#define JUMPTOELEMENTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPointer>
|
||||
|
||||
class Diagram;
|
||||
class Element;
|
||||
class QLineEdit;
|
||||
class QListWidget;
|
||||
|
||||
/**
|
||||
@brief The JumpToElementDialog class
|
||||
A lightweight, transient "quick open" popup: type part of an element's
|
||||
label or other information to live-filter the elements on a diagram,
|
||||
then Enter to select the chosen element on the diagram and scroll it
|
||||
into view. Up/Down move through the filtered list, Escape cancels
|
||||
without changing the current selection.
|
||||
*/
|
||||
class JumpToElementDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit JumpToElementDialog(Diagram *diagram, QWidget *parent = nullptr);
|
||||
~JumpToElementDialog() override;
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void updateFilteredList(const QString &filter_text);
|
||||
void activateCurrentItem();
|
||||
|
||||
private:
|
||||
void buildCandidates();
|
||||
|
||||
struct Candidate {
|
||||
QPointer<Element> element;
|
||||
QString display_text;
|
||||
QString search_text;
|
||||
};
|
||||
|
||||
QPointer<Diagram> m_diagram;
|
||||
QList<Candidate> m_candidates;
|
||||
QLineEdit *m_filter_edit;
|
||||
QListWidget *m_result_list;
|
||||
};
|
||||
|
||||
#endif // JUMPTOELEMENTDIALOG_H
|
||||
@@ -216,6 +216,16 @@ void MasterPropertiesWidget::reset()
|
||||
*/
|
||||
QUndoCommand* MasterPropertiesWidget::associatedUndo() const
|
||||
{
|
||||
// PLC masters manage their slave links via the IO table (setElementData),
|
||||
// not via the link tree widget. The link tree is always empty for PLC
|
||||
// masters, so we must not create an unlinkAll command.
|
||||
if (m_element &&
|
||||
m_element->elementData().m_type == ElementData::Master &&
|
||||
m_element->elementData().m_master_type == ElementData::PLC)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList <Element *> to_link;
|
||||
QList <Element *> linked_ = m_element->linkedElements();
|
||||
|
||||
@@ -880,6 +890,8 @@ void MasterPropertiesWidget::plcRemoveRow()
|
||||
if (selected.isEmpty())
|
||||
return;
|
||||
|
||||
m_plc_updating = true;
|
||||
|
||||
// Remove from bottom to top to preserve indices
|
||||
std::sort(selected.begin(), selected.end(),
|
||||
[](const QModelIndex &a, const QModelIndex &b) { return a.row() > b.row(); });
|
||||
@@ -887,6 +899,9 @@ void MasterPropertiesWidget::plcRemoveRow()
|
||||
for (const QModelIndex &idx : selected) {
|
||||
m_plc_table->removeRow(idx.row());
|
||||
}
|
||||
|
||||
m_plc_updating = false;
|
||||
plcUpdateDisplaySettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -902,6 +917,8 @@ void MasterPropertiesWidget::plcMoveRowUp()
|
||||
if (row <= 0)
|
||||
return;
|
||||
|
||||
m_plc_updating = true;
|
||||
|
||||
// Swap with row above
|
||||
for (int col = 0; col < m_plc_table->columnCount(); ++col) {
|
||||
QWidget *w1 = m_plc_table->cellWidget(row, col);
|
||||
@@ -916,6 +933,8 @@ void MasterPropertiesWidget::plcMoveRowUp()
|
||||
}
|
||||
|
||||
m_plc_table->setCurrentCell(row - 1, m_plc_table->currentColumn());
|
||||
m_plc_updating = false;
|
||||
plcUpdateDisplaySettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,6 +950,8 @@ void MasterPropertiesWidget::plcMoveRowDown()
|
||||
if (row < 0 || row >= m_plc_table->rowCount() - 1)
|
||||
return;
|
||||
|
||||
m_plc_updating = true;
|
||||
|
||||
// Swap with row below
|
||||
for (int col = 0; col < m_plc_table->columnCount(); ++col) {
|
||||
QWidget *w1 = m_plc_table->cellWidget(row, col);
|
||||
@@ -945,6 +966,8 @@ void MasterPropertiesWidget::plcMoveRowDown()
|
||||
}
|
||||
|
||||
m_plc_table->setCurrentCell(row + 1, m_plc_table->currentColumn());
|
||||
m_plc_updating = false;
|
||||
plcUpdateDisplaySettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -978,7 +1001,14 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
|
||||
ElementData::PlcMasterData plc_data = ed.plcMasterData();
|
||||
plc_data.ios.clear();
|
||||
|
||||
// Read IOs from table
|
||||
// Build address -> original IO lookup to correctly reattach terminal data
|
||||
// after row reorder (move up/down) or row removal
|
||||
QHash<QString, int> addr_to_orig_idx;
|
||||
for (int i = 0; i < ed.plcMasterData().ios.size(); ++i) {
|
||||
addr_to_orig_idx[ed.plcMasterData().ios.at(i).address] = i;
|
||||
}
|
||||
|
||||
// Read IOs from table, preserving terminal data from original IOs
|
||||
for (int row = 0; row < m_plc_table->rowCount(); ++row) {
|
||||
ElementData::PlcIO io;
|
||||
|
||||
@@ -1002,6 +1032,13 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
|
||||
if (crossref_item)
|
||||
io.crossRef = crossref_item->text();
|
||||
|
||||
// Preserve terminal data by looking up original IO via address
|
||||
if (addr_to_orig_idx.contains(io.address)) {
|
||||
const auto &orig_io = ed.plcMasterData().ios.at(addr_to_orig_idx.value(io.address));
|
||||
io.terminalCount = orig_io.terminalCount;
|
||||
io.terminals = orig_io.terminals;
|
||||
}
|
||||
|
||||
plc_data.ios.append(io);
|
||||
}
|
||||
|
||||
|
||||
@@ -406,22 +406,46 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
elmt->setGroupIndexForElement(m_element, group_idx);
|
||||
|
||||
// Set master labels on slave terminals
|
||||
const auto &groups = elmt->elementData().m_slave_contact_groups;
|
||||
if (group_idx < groups.size())
|
||||
if (elmt->elementData().m_master_type == ElementData::PLC)
|
||||
{
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
QList<Terminal *> slave_terms = m_element->terminals();
|
||||
// Sort terminals by name (T1, T2, T3...) to match label order
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->name() < b->name();
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
// For PLC masters, use io.terminals as labels
|
||||
const auto &plc_data = elmt->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size())
|
||||
{
|
||||
if (i < labels.size())
|
||||
const QStringList &labels = plc_data.ios.at(group_idx).terminals;
|
||||
QList<Terminal *> slave_terms = m_element->terminals();
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->baseName() < b->baseName();
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
slave_terms.at(i)->setUseMasterLabel(true);
|
||||
slave_terms.at(i)->setMasterLabelIndex(i);
|
||||
if (i < labels.size())
|
||||
{
|
||||
slave_terms.at(i)->setUseMasterLabel(true);
|
||||
slave_terms.at(i)->setMasterLabelIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &groups = elmt->elementData().m_slave_contact_groups;
|
||||
if (group_idx < groups.size())
|
||||
{
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
QList<Terminal *> slave_terms = m_element->terminals();
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->baseName() < b->baseName();
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
if (i < labels.size())
|
||||
{
|
||||
slave_terms.at(i)->setUseMasterLabel(true);
|
||||
slave_terms.at(i)->setMasterLabelIndex(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -443,6 +467,20 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
plcCrossRefText(elmt, m_element));
|
||||
ctx.addValue(QETInformation::ELMT_LABEL,
|
||||
elmt->actualLabel());
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TC,
|
||||
QString::number(io.terminalCount));
|
||||
for (int t = 0; t < io.terminalCount && t < 4; ++t)
|
||||
{
|
||||
QString val = (t < io.terminals.size())
|
||||
? io.terminals.at(t) : QString();
|
||||
ctx.addValue(
|
||||
QStringList({
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
}).at(t), val);
|
||||
}
|
||||
m_element->setElementInformations(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,12 @@ void QETUtils::pixelSizedFont(QFont &font)
|
||||
|
||||
namespace
|
||||
{
|
||||
/* Counters for fontFromString(), reset per project load so the editor
|
||||
* can report how many stored font descriptions needed salvaging or were
|
||||
* unreadable. Font parsing only happens on the main thread. */
|
||||
int salvaged_font_count = 0;
|
||||
int unreadable_font_count = 0;
|
||||
|
||||
/**
|
||||
* Legacy (Qt 5) weight <- OpenType weight, closest match,
|
||||
* same table Qt uses when parsing a 10/11 field string.
|
||||
@@ -235,6 +241,10 @@ QString QETUtils::fontToString(const QFont &font)
|
||||
*/
|
||||
bool QETUtils::fontFromString(QFont &font, const QString &description)
|
||||
{
|
||||
if (description.trimmed().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QFont parsed(font);
|
||||
if (parsed.fromString(description)) {
|
||||
font = parsed;
|
||||
@@ -271,8 +281,10 @@ bool QETUtils::fontFromString(QFont &font, const QString &description)
|
||||
|
||||
if (parsed.fromString(legacy)) {
|
||||
font = parsed;
|
||||
++salvaged_font_count;
|
||||
return true;
|
||||
}
|
||||
++unreadable_font_count;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -284,7 +296,50 @@ bool QETUtils::fontFromString(QFont &font, const QString &description)
|
||||
if (count > 11
|
||||
&& parsed.fromString(QStringList(l.mid(0, 11)).join(comma))) {
|
||||
font = parsed;
|
||||
++salvaged_font_count;
|
||||
return true;
|
||||
}
|
||||
++unreadable_font_count;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QETUtils::FontRestorationScope::FontRestorationScope
|
||||
* Open a fresh counting window: the enclosing window's counts are kept
|
||||
* aside and restored by the destructor, so a project load nested inside
|
||||
* another one (through the event loop) reports its own numbers only.
|
||||
*/
|
||||
QETUtils::FontRestorationScope::FontRestorationScope() :
|
||||
m_outer_salvaged(salvaged_font_count),
|
||||
m_outer_unreadable(unreadable_font_count)
|
||||
{
|
||||
salvaged_font_count = 0;
|
||||
unreadable_font_count = 0;
|
||||
}
|
||||
|
||||
QETUtils::FontRestorationScope::~FontRestorationScope()
|
||||
{
|
||||
salvaged_font_count = m_outer_salvaged;
|
||||
unreadable_font_count = m_outer_unreadable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QETUtils::FontRestorationScope::salvaged
|
||||
* @return How many font descriptions fontFromString() restored from a
|
||||
* foreign or corrupt format since this window was opened. Such descriptions
|
||||
* are rewritten in the stable format on the next save.
|
||||
*/
|
||||
int QETUtils::FontRestorationScope::salvaged() const
|
||||
{
|
||||
return salvaged_font_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QETUtils::FontRestorationScope::unreadable
|
||||
* @return How many font descriptions fontFromString() could not restore at
|
||||
* all since this window was opened (the caller's default font applies).
|
||||
*/
|
||||
int QETUtils::FontRestorationScope::unreadable() const
|
||||
{
|
||||
return unreadable_font_count;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,29 @@ namespace QETUtils
|
||||
QString fontToString (const QFont &font);
|
||||
bool fontFromString (QFont &font, const QString &description);
|
||||
|
||||
/**
|
||||
RAII counting window for the font descriptions fontFromString()
|
||||
salvages or fails to read: construction opens a fresh window, the
|
||||
destructor restores the enclosing one. Windows nest strictly LIFO,
|
||||
which covers project loads re-entered through the event loop
|
||||
(DialogWaiting pumps it while the folios are built).
|
||||
*/
|
||||
class FontRestorationScope
|
||||
{
|
||||
public:
|
||||
FontRestorationScope();
|
||||
~FontRestorationScope();
|
||||
FontRestorationScope(const FontRestorationScope &) = delete;
|
||||
FontRestorationScope &operator=(const FontRestorationScope &) = delete;
|
||||
|
||||
int salvaged() const;
|
||||
int unreadable() const;
|
||||
|
||||
private:
|
||||
int m_outer_salvaged;
|
||||
int m_outer_unreadable;
|
||||
};
|
||||
|
||||
bool sortBeginIntString(const QString &str_a, const QString &str_b);
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user