diff --git a/sources/autoNum/assignvariables.cpp b/sources/autoNum/assignvariables.cpp index ecdd53907..8e2d465ec 100644 --- a/sources/autoNum/assignvariables.cpp +++ b/sources/autoNum/assignvariables.cpp @@ -39,6 +39,7 @@ namespace autonum sequentialNumbers::sequentialNumbers(const sequentialNumbers &other) { unit = other.unit; + wrap = other.wrap; unit_folio = other.unit_folio; ten = other.ten; ten_folio = other.ten_folio; @@ -57,6 +58,7 @@ namespace autonum return (*this); unit = other.unit; + wrap = other.wrap; unit_folio = other.unit_folio; ten = other.ten; ten_folio = other.ten_folio; @@ -70,6 +72,7 @@ namespace autonum bool sequentialNumbers::operator==(const sequentialNumbers &other) const { if (unit == other.unit && \ + wrap == other.wrap && \ unit_folio == other.unit_folio && \ ten == other.ten && \ ten_folio == other.ten_folio && \ @@ -107,6 +110,11 @@ namespace autonum document, "unit", unit.join(";"))); + if (!wrap.isEmpty()) + element.appendChild(QETXML::textToDomElement( + document, + "wrap", + wrap.join(";"))); if (!unit_folio.isEmpty()) element.appendChild(QETXML::textToDomElement( document, @@ -156,6 +164,11 @@ namespace autonum from = element.firstChildElement("unit"); unit = from.text().split(";"); + //Absent from files written before cyclic parts could be + //rendered; an empty list is the correct reading of that. + from = element.firstChildElement("wrap"); + wrap = from.text().split(";"); + from = element.firstChildElement("unitFolio"); unit_folio = from.text().split(";"); @@ -179,6 +192,7 @@ namespace autonum void sequentialNumbers::clear() { unit.clear(); + wrap.clear(); unit_folio.clear(); ten.clear(); ten_folio.clear(); @@ -434,7 +448,8 @@ namespace autonum qMax( qMax(m_seq_struct.hundred.size(), m_seq_struct.ten.size()), - m_seq_struct.alpha.size()) + qMax(m_seq_struct.alpha.size(), + m_seq_struct.wrap.size())) ); for (int i=1; i<=max ; i++) @@ -442,6 +457,9 @@ namespace autonum if (m_assigned_label.contains("%sequ_" + QString::number(i)) && m_seq_struct.unit.size() >= i) { m_assigned_label.replace("%sequ_" + QString::number(i),m_seq_struct.unit.at(i-1)); } + if (m_assigned_label.contains("%seqw_" + QString::number(i)) && m_seq_struct.wrap.size() >= i) { + m_assigned_label.replace("%seqw_" + QString::number(i),m_seq_struct.wrap.at(i-1)); + } if (m_assigned_label.contains("%seqt_" + QString::number(i)) && m_seq_struct.ten.size() >= i) { m_assigned_label.replace("%seqt_" + QString::number(i),m_seq_struct.ten.at(i-1)); } @@ -479,15 +497,26 @@ namespace autonum { if (context.itemAt(i).at(0) == type) { + const QStringList item = context.itemAt(i); + //A zero-padding mask, spreadsheet style: its length is the + //minimum number of digits. It overrides the width implied + //by the part type, so "Chiffre 01" with a mask of "0000" + //pads to four. An absent mask -- which is every context + //written before the field existed -- falls through to the + //type's own width, so nothing about existing projects + //changes. + const QString mask = NumerotationContext::formatOf(item); QString number; - if (type == "ten" || type == "tenfolio") - 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") + 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()); + number = item.at(1); + else if (!mask.isEmpty()) + number = QString("%1").arg(item.at(1).toInt(), mask.length(), 10, QChar('0')); + else if (type == "ten" || type == "tenfolio") + number = QString("%1").arg(item.at(1).toInt(), 2, 10, QChar('0')); + else if (type == "hundred" || type == "hundredfolio") + number = QString("%1").arg(item.at(1).toInt(), 3, 10, QChar('0')); + else number = QString::number(item.at(1).toInt()); list.append(number); } } @@ -553,6 +582,10 @@ namespace autonum { autonum::setSequentialToList(seqStruct.unit, context,"unit"); } + if (label.contains("%seqw_")) + { + autonum::setSequentialToList(seqStruct.wrap, context,"wrap"); + } if (label.contains("%sequf_")) { autonum::setSequentialToList(seqStruct.unit_folio, context,"unitfolio"); @@ -594,6 +627,7 @@ namespace autonum QString value; QString formula; int count_unit = 0; + int count_wrap = 0; int count_unitf = 0; int count_ten = 0; int count_tenf = 0; @@ -636,6 +670,10 @@ namespace autonum count_unit++; formula.append("%sequ_" + QString::number(count_unit)); } + else if (type == "wrap") { + count_wrap++; + formula.append("%seqw_" + QString::number(count_wrap)); + } else if (type == "unitfolio") { count_unitf++; formula.append("%sequf_" + QString::number(count_unitf)); diff --git a/sources/autoNum/assignvariables.h b/sources/autoNum/assignvariables.h index 15678d019..5fffdf43f 100644 --- a/sources/autoNum/assignvariables.h +++ b/sources/autoNum/assignvariables.h @@ -47,6 +47,8 @@ namespace autonum void clear(); QStringList unit; + /// Values of the cyclic (modulo) parts, referenced by %seqw_N. + QStringList wrap; QStringList unit_folio; QStringList ten; QStringList ten_folio; diff --git a/sources/autoNum/numerotationcontext.cpp b/sources/autoNum/numerotationcontext.cpp index fe7200ab8..a8f3b11f4 100644 --- a/sources/autoNum/numerotationcontext.cpp +++ b/sources/autoNum/numerotationcontext.cpp @@ -52,13 +52,18 @@ void NumerotationContext::clear () @param increase the increase number of value @param initialvalue @param modulus wrap-and-carry modulus (0 means "not a wrapping part") + @param format zero-padding mask, spreadsheet style: "00" pads to two + digits, "000" to three. Empty keeps the part type's natural width, so + an absent format reproduces exactly the behaviour of every context + written before this field existed. @return true if value is append */ bool NumerotationContext::addValue(const QString &type, const QVariant &value, const int increase, const int initialvalue, - const int modulus) { + const int modulus, + const QString &format) { if (!keyIsAcceptable(type) && !value.canConvert()) return false; if (keyIsNumber(type) && !value.canConvert()) @@ -74,7 +79,9 @@ bool NumerotationContext::addValue(const QString &type, + "|" + QString::number(initialvalue) + "|" - + QString::number(modulus); + + QString::number(modulus) + + "|" + + QString(format).remove("|"); return true; } @@ -179,6 +186,9 @@ QDomElement NumerotationContext::toXml(QDomDocument &d, const QString& str) { if (strl.at(0) == ("wrap") && strl.size() > 4) { part.setAttribute("modulus", strl.at(4)); } + if (strl.size() > 5 && !strl.at(5).isEmpty()) { + part.setAttribute("format", strl.at(5)); + } num_auto.appendChild(part); } return num_auto; @@ -190,7 +200,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(), qde.attribute("modulus").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(), qde.attribute("format")); } /** @@ -206,5 +216,17 @@ void NumerotationContext::replaceValue(int index, QString content) { 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; + QString format = strl.size() > 5 ? strl.at(5) : QString(); + content_[index] = type + "|" + value + "|" + increase + "|" + initvalue + "|" + modulus + "|" + format; +} + +/** + @brief NumerotationContext::formatOf + @param item : a context item as returned by itemAt() + @return the part's zero-padding mask, or an empty string when it has + none -- which every context written before the field existed will be. +*/ +QString NumerotationContext::formatOf(const QStringList &item) +{ + return item.size() > 5 ? item.at(5) : QString(); } diff --git a/sources/autoNum/numerotationcontext.h b/sources/autoNum/numerotationcontext.h index dcc0139ea..f53c42751 100644 --- a/sources/autoNum/numerotationcontext.h +++ b/sources/autoNum/numerotationcontext.h @@ -37,7 +37,11 @@ class NumerotationContext const QVariant & = QVariant(1), const int = 1, const int = 0, - const int = 0); + const int = 0, + const QString & = QString()); + /// Zero-padding mask of a part, e.g. "00"; empty means the type's + /// own natural width. See addValue(). + static QString formatOf(const QStringList &item); QString operator[] (const int &) const; void operator << (const NumerotationContext &); int size() const; diff --git a/sources/autoNum/numerotationcontextcommands.cpp b/sources/autoNum/numerotationcontextcommands.cpp index 9b5536cb6..7e65d374e 100644 --- a/sources/autoNum/numerotationcontextcommands.cpp +++ b/sources/autoNum/numerotationcontextcommands.cpp @@ -259,7 +259,7 @@ NumerotationContext NumStrategy::nextString (const NumerotationContext &nc, { QStringList strl = nc.itemAt(i); NumerotationContext newnc; - newnc.addValue(strl.at(0), strl.at(1), strl.at(2).toInt()); + newnc.addValue(strl.at(0), strl.at(1), strl.at(2).toInt(), 0, 0, NumerotationContext::formatOf(strl)); return (newnc); } @@ -273,7 +273,7 @@ NumerotationContext NumStrategy::nextNumber (const NumerotationContext &nc, QStringList strl = nc.itemAt(i); NumerotationContext newnc; QString value = QString::number( (strl.at(1).toInt()) + (strl.at(2).toInt()) ); - newnc.addValue(strl.at(0), value, strl.at(2).toInt(), strl.at(3).toInt()); + newnc.addValue(strl.at(0), value, strl.at(2).toInt(), strl.at(3).toInt(), 0, NumerotationContext::formatOf(strl)); return (newnc); } @@ -287,7 +287,7 @@ NumerotationContext NumStrategy::previousNumber(const NumerotationContext &nc, QStringList strl = nc.itemAt(i); NumerotationContext newnc; QString value = QString::number( (strl.at(1).toInt()) - (strl.at(2).toInt()) ); - newnc.addValue(strl.at(0), value, strl.at(2).toInt(), strl.at(3).toInt()); + newnc.addValue(strl.at(0), value, strl.at(2).toInt(), strl.at(3).toInt(), 0, NumerotationContext::formatOf(strl)); return (newnc); } @@ -550,7 +550,7 @@ NumerotationContext WrapNum::next (const NumerotationContext &nc, const int i) c 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); + newnc.addValue(strl.at(0), QString::number(new_value), increase, strl.at(3).toInt(), modulus, NumerotationContext::formatOf(strl)); return (newnc); } @@ -570,7 +570,7 @@ NumerotationContext WrapNum::previous(const NumerotationContext &nc, const int i if (new_value < 0) new_value += modulus; } - newnc.addValue(strl.at(0), QString::number(new_value), increase, strl.at(3).toInt(), modulus); + newnc.addValue(strl.at(0), QString::number(new_value), increase, strl.at(3).toInt(), modulus, NumerotationContext::formatOf(strl)); return (newnc); } @@ -706,7 +706,7 @@ NumerotationContext AlphaNum::next (const NumerotationContext &nc, const int i) { QStringList strl = nc.itemAt(i); NumerotationContext newnc; - newnc.addValue(strl.at(0), incrementAlpha(strl.at(1)), strl.at(2).toInt()); + newnc.addValue(strl.at(0), incrementAlpha(strl.at(1)), strl.at(2).toInt(), 0, 0, NumerotationContext::formatOf(strl)); return (newnc); } @@ -718,7 +718,7 @@ NumerotationContext AlphaNum::previous(const NumerotationContext &nc, const int { QStringList strl = nc.itemAt(i); NumerotationContext newnc; - newnc.addValue(strl.at(0), decrementAlpha(strl.at(1)), strl.at(2).toInt()); + newnc.addValue(strl.at(0), decrementAlpha(strl.at(1)), strl.at(2).toInt(), 0, 0, NumerotationContext::formatOf(strl)); return (newnc); } diff --git a/sources/autoNum/ui/numparteditorw.cpp b/sources/autoNum/ui/numparteditorw.cpp index 3f248c4d5..69db1a119 100644 --- a/sources/autoNum/ui/numparteditorw.cpp +++ b/sources/autoNum/ui/numparteditorw.cpp @@ -18,6 +18,8 @@ #include "numparteditorw.h" #include "ui_numparteditorw.h" +#include "../numerotationcontext.h" + #include /** @@ -35,6 +37,9 @@ NumPartEditorW::NumPartEditorW(int type, QWidget *parent) : { ui -> setupUi(this); setVisibleItems(); + //The mask is a run of zeros and nothing else, so it cannot be typed + //into a state the renderer would have to reject. + ui -> format_le -> setValidator(new QRegularExpressionValidator(QRegularExpression("0*"), this)); setType(NumPartEditorW::unit, true); } @@ -99,6 +104,7 @@ NumPartEditorW::NumPartEditorW (NumerotationContext &context, ui -> increase_spinBox -> setValue(strl.at(2).toInt()); if (strl.at(0)=="wrap" && strl.size() > 4) ui -> modulus_spinBox -> setValue(strl.at(4).toInt()); + ui -> format_le -> setText(NumerotationContext::formatOf(strl)); } } @@ -219,23 +225,30 @@ NumerotationContext NumPartEditorW::toNumContext() type_str = "alpha"; break; } + const QString number_format = ui -> format_le -> text(); if (type_str == "unitfolio" || type_str == "tenfolio" || type_str == "hundredfolio") nc.addValue(type_str, ui -> value_field -> displayText(), ui -> increase_spinBox -> value(), - ui->value_field->displayText().toInt()); + ui->value_field->displayText().toInt(), + 0, + number_format); else if (type_str == "wrap") nc.addValue(type_str, ui -> value_field -> displayText(), ui -> increase_spinBox -> value(), 0, - ui -> modulus_spinBox -> value()); + ui -> modulus_spinBox -> value(), + number_format); else nc.addValue(type_str, ui -> value_field -> displayText(), - ui -> increase_spinBox -> value()); + ui -> increase_spinBox -> value(), + 0, + 0, + number_format); return nc; } @@ -317,6 +330,14 @@ void NumPartEditorW::on_increase_spinBox_valueChanged(int) { @brief NumPartEditorW::on_modulus_spinBox_valueChanged emit changed when modulus_spinBox value changed */ +/** + @brief NumPartEditorW::on_format_le_textEdited + emit changed when the display format is edited +*/ +void NumPartEditorW::on_format_le_textEdited(const QString &) { + emit changed(); +} + void NumPartEditorW::on_modulus_spinBox_valueChanged(int) { if (!ui -> value_field -> text().isEmpty()) emit changed(); } @@ -359,8 +380,6 @@ 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 @@ -414,7 +433,24 @@ void NumPartEditorW::setType(NumPartEditorW::type t, bool fnum) { ui -> increase_spinBox -> setDisabled(true); } } + //A modulus of 0 means "no cycle", which makes a Cyclique part behave + //exactly like a plain digit. Defaulting it used to live in the numeric + //behavior block above, which is skipped when the previous type was + //itself numeric -- so the ordinary path of turning the default + //"Chiffre 1" into a "Cyclique (modulo)" left the modulus at 0 and + //produced a wrap part that never wrapped. Kept out of that block so it + //applies whatever the part was before, and only when the current value + //is unusable, so a modulus the user chose on purpose is not clobbered. + if (t == wrap && ui -> modulus_spinBox -> value() <= 0) + ui -> modulus_spinBox -> setValue(8); ui -> modulus_spinBox -> setEnabled(t == wrap); + //A padding mask only means anything for a part rendered as a number. + const bool numeric = (t == unit || t == unitfolio || t == ten + || t == tenfolio || t == hundred || t == hundredfolio + || t == wrap); + ui -> format_le -> setEnabled(numeric); + if (!numeric) + ui -> format_le -> clear(); type_= t; } diff --git a/sources/autoNum/ui/numparteditorw.h b/sources/autoNum/ui/numparteditorw.h index e33560aba..ce7d3ffae 100644 --- a/sources/autoNum/ui/numparteditorw.h +++ b/sources/autoNum/ui/numparteditorw.h @@ -66,6 +66,7 @@ class NumPartEditorW : public QWidget void on_value_field_textEdited(); void on_increase_spinBox_valueChanged(int); void on_modulus_spinBox_valueChanged(int); + void on_format_le_textEdited(const QString &); void setType (NumPartEditorW::type t, bool=false); signals: diff --git a/sources/autoNum/ui/numparteditorw.ui b/sources/autoNum/ui/numparteditorw.ui index bfc4fd9d2..15ee0cfa3 100644 --- a/sources/autoNum/ui/numparteditorw.ui +++ b/sources/autoNum/ui/numparteditorw.ui @@ -126,6 +126,28 @@ + + + + false + + + + 70 + 16777215 + + + + Format d'affichage : une suite de zéros donne le nombre minimum de chiffres (00 = 07, 000 = 007). Vide = largeur naturelle du type. + + + 0 + + + Qt::AlignCenter + + +