mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-03 18:44:13 +02:00
Merge pull request #593 from ispyisail/feature-wrap-and-carry-autonum
Add wrap-and-carry (cyclic/modulo) auto-numbering
This commit is contained in:
@@ -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|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,6 +196,10 @@ 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;
|
||||
@@ -431,6 +514,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
|
||||
*/
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -71,6 +71,8 @@ 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)=="string")
|
||||
setType(NumPartEditorW::string);
|
||||
else if (strl.at(0)=="idfolio")
|
||||
@@ -89,6 +91,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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +114,7 @@ void NumPartEditorW::setVisibleItems()
|
||||
items << tr("Chiffre 1")
|
||||
<< tr("Chiffre 01")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Texte");
|
||||
}
|
||||
else if (m_edited_type == 1)
|
||||
@@ -120,6 +125,7 @@ void NumPartEditorW::setVisibleItems()
|
||||
<< tr("Chiffre 01 - Folio")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Chiffre 001 - Folio")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Texte")
|
||||
<< tr("N° folio")
|
||||
<< tr("Folio")
|
||||
@@ -133,6 +139,7 @@ void NumPartEditorW::setVisibleItems()
|
||||
<< tr("Chiffre 01 - Folio")
|
||||
<< tr("Chiffre 001")
|
||||
<< tr("Chiffre 001 - Folio")
|
||||
<< tr("Cyclique (modulo)")
|
||||
<< tr("Texte")
|
||||
<< tr("N° folio")
|
||||
<< tr("Folio")
|
||||
@@ -195,6 +202,9 @@ NumerotationContext NumPartEditorW::toNumContext()
|
||||
case elementprefix:
|
||||
type_str = "elementprefix";
|
||||
break;
|
||||
case wrap:
|
||||
type_str = "wrap";
|
||||
break;
|
||||
}
|
||||
if (type_str == "unitfolio"
|
||||
|| type_str == "tenfolio"
|
||||
@@ -203,6 +213,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 +276,8 @@ 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);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
@@ -280,6 +298,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 +325,7 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
|| t==tenfolio
|
||||
|| t==hundred
|
||||
|| t==hundredfolio
|
||||
|| t==wrap
|
||||
)
|
||||
&& (type_==string
|
||||
|| type_==folio
|
||||
@@ -317,6 +344,8 @@ 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
|
||||
@@ -362,6 +391,7 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) {
|
||||
ui -> increase_spinBox -> setDisabled(true);
|
||||
}
|
||||
}
|
||||
ui -> modulus_spinBox -> setEnabled(t == wrap);
|
||||
type_= t;
|
||||
}
|
||||
|
||||
@@ -400,5 +430,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);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ class NumPartEditorW : public QWidget
|
||||
enum type {unit,unitfolio,ten,tenfolio, hundred, hundredfolio,
|
||||
string,idfolio,folio,plant,locmach,
|
||||
elementline,elementcolumn,elementprefix,
|
||||
wrap,
|
||||
};
|
||||
NumerotationContext toNumContext();
|
||||
bool isValid ();
|
||||
@@ -63,6 +64,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:
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user