diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp index e3674b5f9..ab8af80ca 100644 --- a/sources/bordertitleblock.cpp +++ b/sources/bordertitleblock.cpp @@ -18,7 +18,6 @@ #include #include "titleblocktemplate.h" #include "titleblocktemplaterenderer.h" -#include "diagramcontext.h" #include "bordertitleblock.h" #include "diagramposition.h" #include "qetapp.h" @@ -94,16 +93,7 @@ qreal BorderTitleBlock::minRowsHeight() { @param xml_elmt the XML element attributes will be added to */ void BorderTitleBlock::titleBlockToXml(QDomElement &xml_elmt) { - if (!author().isNull()) xml_elmt.setAttribute("author", author()); - if (!date().isNull()) xml_elmt.setAttribute("date", date().toString("yyyyMMdd")); - if (!title().isNull()) xml_elmt.setAttribute("title", title()); - if (!fileName().isNull()) xml_elmt.setAttribute("filename", fileName()); - if (!folio().isNull()) xml_elmt.setAttribute("folio", folio()); - - QString current_template_name = titleBlockTemplateName(); - if (!current_template_name.isEmpty()) { - xml_elmt.setAttribute("titleblocktemplate", current_template_name); - } + exportTitleBlock().toXml(xml_elmt); } /** @@ -111,12 +101,9 @@ void BorderTitleBlock::titleBlockToXml(QDomElement &xml_elmt) { @param xml_elmt the XML element values will be read from */ void BorderTitleBlock::titleBlockFromXml(const QDomElement &xml_elmt) { - setAuthor(xml_elmt.attribute("author")); - setTitle(xml_elmt.attribute("title")); - setDate(QDate::fromString(xml_elmt.attribute("date"), "yyyyMMdd")); - setFileName(xml_elmt.attribute("filename")); - setFolio(xml_elmt.attribute("folio")); - needTitleBlockTemplate(xml_elmt.attribute("titleblocktemplate", "")); + TitleBlockProperties tbp; + tbp.fromXml(xml_elmt); + importTitleBlock(tbp); } /** @@ -177,12 +164,15 @@ void BorderTitleBlock::borderFromXml(const QDomElement &xml_elmt) { */ TitleBlockProperties BorderTitleBlock::exportTitleBlock() { TitleBlockProperties ip; - ip.author = bi_author; - ip.date = bi_date; - ip.title = bi_title; - ip.folio = bi_folio; - ip.filename = bi_filename; + + ip.author = author(); + ip.date = date(); + ip.title = title(); + ip.filename = fileName(); + ip.folio = folio(); ip.template_name = titleBlockTemplateName(); + ip.context = additional_fields_; + return(ip); } @@ -190,13 +180,15 @@ TitleBlockProperties BorderTitleBlock::exportTitleBlock() { @param ip les nouvelles proprietes du cartouche */ void BorderTitleBlock::importTitleBlock(const TitleBlockProperties &ip) { - bi_author = ip.author; - bi_date = ip.date; + setAuthor(ip.author); + setDate(ip.date); setTitle(ip.title); - bi_folio = ip.folio; - bi_filename = ip.filename; - updateDiagramContextForTitleBlock(); + setFileName(ip.filename); + setFolio(ip.folio); + additional_fields_ = ip.context; + emit(needFolioData()); + updateDiagramContextForTitleBlock(); emit(needTitleBlockTemplate(ip.template_name)); } @@ -577,7 +569,10 @@ DiagramPosition BorderTitleBlock::convertPosition(const QPointF &pos) { DiagramContext object. */ void BorderTitleBlock::updateDiagramContextForTitleBlock() { - DiagramContext context; + // our final DiagramContext object is the "additional fields" one + DiagramContext context = additional_fields_; + + // ... overridden by the historical and/or dynamically generated fields context.addValue("author", bi_author); context.addValue("date", bi_date.toString("dd/MM/yyyy")); context.addValue("title", bi_title); diff --git a/sources/bordertitleblock.h b/sources/bordertitleblock.h index 1e35300c0..e1105a5da 100644 --- a/sources/bordertitleblock.h +++ b/sources/bordertitleblock.h @@ -17,6 +17,7 @@ */ #ifndef BORDERTITLEBLOCK_H #define BORDERTITLEBLOCK_H +#include "diagramcontext.h" #include "titleblockproperties.h" #include "borderproperties.h" #include @@ -216,6 +217,7 @@ class BorderTitleBlock : public QObject { int folio_index_; int folio_total_; QString bi_filename; + DiagramContext additional_fields_; // dimensions du cadre (lignes et colonnes) // colonnes : nombres et dimensions diff --git a/sources/diagramcontext.cpp b/sources/diagramcontext.cpp index ce56d0bcd..9358fc5cc 100644 --- a/sources/diagramcontext.cpp +++ b/sources/diagramcontext.cpp @@ -55,6 +55,14 @@ bool DiagramContext::addValue(const QString &key, const QVariant &value) { return(false); } +bool DiagramContext::operator==(const DiagramContext &dc) const { + return(content_ == dc.content_); +} + +bool DiagramContext::operator!=(const DiagramContext &dc) const { + return(!(*this == dc)); +} + /** @param key a key string @return true if that key is acceptable, false otherwise diff --git a/sources/diagramcontext.h b/sources/diagramcontext.h index 70168a8cb..fc925b8cd 100644 --- a/sources/diagramcontext.h +++ b/sources/diagramcontext.h @@ -32,6 +32,9 @@ class DiagramContext { const QVariant operator[](const QString &) const; bool addValue(const QString &, const QVariant &); + bool operator==(const DiagramContext &) const; + bool operator!=(const DiagramContext &) const; + private: bool keyIsAcceptable(const QString &) const; /// Diagram context data (key/value pairs) diff --git a/sources/templateeditor.cpp b/sources/templateeditor.cpp index a743fb5f6..04bde87a5 100644 --- a/sources/templateeditor.cpp +++ b/sources/templateeditor.cpp @@ -100,7 +100,7 @@ void TemplateEditor::save() { QMessageBox::critical( this, tr("Code XML non valide"), - tr("Le code XML du mod\350le ne semble pas \320tre valide. Impossible d'enregistrer le mod\350le.") + tr("Le code XML du mod\350le ne semble pas \352tre valide. Impossible d'enregistrer le mod\350le.") ); return; } diff --git a/sources/titleblockproperties.cpp b/sources/titleblockproperties.cpp index 653dcaa2e..33f08a1c9 100644 --- a/sources/titleblockproperties.cpp +++ b/sources/titleblockproperties.cpp @@ -16,6 +16,7 @@ along with QElectroTech. If not, see . */ #include "titleblockproperties.h" +#include "qet.h" /** Constructeur. Initialise un objet TitleBlockProperties avec tous les champs @@ -44,7 +45,8 @@ bool TitleBlockProperties::operator==(const TitleBlockProperties &ip) { ip.date == date &&\ ip.filename == filename &&\ ip.folio == folio &&\ - ip.template_name == template_name + ip.template_name == template_name &&\ + ip.context == context ); } @@ -70,19 +72,40 @@ void TitleBlockProperties::toXml(QDomElement &e) const { if (!template_name.isEmpty()) { e.setAttribute("titleblocktemplate", template_name); } + + if (context.keys().count()) { + QDomElement properties = e.ownerDocument().createElement("properties"); + foreach (QString key, context.keys()) { + QDomElement property = e.ownerDocument().createElement("property"); + property.setAttribute("name", key); + QDomText value = e.ownerDocument().createTextNode(context[key].toString()); + property.appendChild(value); + properties.appendChild(property); + } + e.appendChild(properties); + } } /** Importe le cartouche a partir des attributs XML de l'element e @param e Element XML dont les attributs seront lus */ -void TitleBlockProperties::fromXml(QDomElement &e) { +void TitleBlockProperties::fromXml(const QDomElement &e) { + // reads the historical fields if (e.hasAttribute("author")) author = e.attribute("author"); if (e.hasAttribute("title")) title = e.attribute("title"); if (e.hasAttribute("filename")) filename = e.attribute("filename"); if (e.hasAttribute("folio")) folio = e.attribute("folio"); if (e.hasAttribute("date")) setDateFromString(e.attribute("date")); + + // reads the template used to render the title block if (e.hasAttribute("titleblocktemplate")) template_name = e.attribute("titleblocktemplate"); + + // reads the additional fields used to fill the title block + foreach (QDomElement property, QET::findInDomElement(e, "properties", "property")) { + if (!property.hasAttribute("name")) continue; + context.addValue(property.attribute("name"), QVariant(property.text())); + } } /** @@ -96,6 +119,15 @@ void TitleBlockProperties::toSettings(QSettings &settings, const QString &prefix settings.setValue(prefix + "filename", filename); settings.setValue(prefix + "folio", folio); settings.setValue(prefix + "date", exportDate()); + + settings.beginWriteArray(prefix + "properties"); + int i = 0; + foreach (QString key, context.keys()) { + settings.setArrayIndex(i); + settings.setValue("name", key); + settings.setValue("value", context[key].toString()); + } + settings.endArray(); } /** @@ -109,6 +141,15 @@ void TitleBlockProperties::fromSettings(QSettings &settings, const QString &pref filename = settings.value(prefix + "filename").toString(); folio = settings.value(prefix + "folio", "%id/%total").toString(); setDateFromString(settings.value(prefix + "date").toString()); + + int size = settings.beginReadArray(prefix + "properties"); + for (int i = 0 ; i < size; ++ i) { + settings.setArrayIndex(i); + QString key = settings.value("name").toString(); + if (key.isEmpty()) continue; + context.addValue(key, settings.value("value").toString()); + } + settings.endArray(); } /** diff --git a/sources/titleblockproperties.h b/sources/titleblockproperties.h index 33b46dd52..00c3e4c54 100644 --- a/sources/titleblockproperties.h +++ b/sources/titleblockproperties.h @@ -19,6 +19,7 @@ #define TITLEBLOCK_PROPERTIES_H #include #include +#include "diagramcontext.h" /** Cette classe est un conteneur pour les proprietes d'un cartouche de schema : titre, auteur, date, nom de fichier et folio @@ -37,7 +38,7 @@ class TitleBlockProperties { bool operator!=(const TitleBlockProperties &); void toXml(QDomElement &) const; - void fromXml(QDomElement &); + void fromXml(const QDomElement &); void toSettings(QSettings &, const QString & = QString()) const; void fromSettings(QSettings &, const QString & = QString()); @@ -51,6 +52,7 @@ class TitleBlockProperties { QString folio; ///< Folio affiche par le cartouche DateManagement useDate; ///< Indique s'il faut utiliser ou non l'attribut date QString template_name; ///< Name of the template used to render the title block - an empty string means "the default template provided by the application" + DiagramContext context; ///< Container for the additional, user-defined fields private: QString exportDate() const; diff --git a/sources/titleblockpropertieswidget.cpp b/sources/titleblockpropertieswidget.cpp index 0006950a8..6847038ce 100644 --- a/sources/titleblockpropertieswidget.cpp +++ b/sources/titleblockpropertieswidget.cpp @@ -25,71 +25,16 @@ @param current true pour afficher l'option "Date courante" @param parent QWidget parent */ -TitleBlockPropertiesWidget::TitleBlockPropertiesWidget(const TitleBlockProperties &titleblock, bool current, QWidget *parent) : QWidget(parent), display_current_date(false) { - - QVBoxLayout *this_layout = new QVBoxLayout(this); - this_layout -> setContentsMargins(0, 0, 0, 0); - QGroupBox *titleblock_infos = new QGroupBox(tr("Informations du cartouche"), this); - titleblock_infos -> setMinimumSize(300, 330); - this_layout -> addWidget(titleblock_infos); - - titleblock_template_label = new QLabel(tr("Mod\350le :")); - titleblock_template_name = new QComboBox(); - - titleblock_title = new QLineEdit(this); - titleblock_author = new QLineEdit(this); - - QButtonGroup *date_policy_group = new QButtonGroup(this); - titleblock_no_date = new QRadioButton(tr("Pas de date"), this); - titleblock_current_date = new QRadioButton(tr("Date courante"), this); - titleblock_fixed_date = new QRadioButton(tr("Date fixe : "), this); - date_policy_group -> addButton(titleblock_no_date); - date_policy_group -> addButton(titleblock_current_date); - date_policy_group -> addButton(titleblock_fixed_date); - titleblock_date = new QDateEdit(QDate::currentDate(), this); - titleblock_date -> setEnabled(titleblock_fixed_date -> isChecked()); - titleblock_current_date -> setVisible(display_current_date); - connect(titleblock_fixed_date, SIGNAL(toggled(bool)), titleblock_date, SLOT(setEnabled(bool))); - titleblock_date -> setCalendarPopup(true); - - QGridLayout *layout_date = new QGridLayout(); - layout_date -> addWidget(titleblock_no_date, 0, 0); - layout_date -> addWidget(titleblock_current_date, 1, 0); - layout_date -> addWidget(titleblock_fixed_date, 2, 0); - layout_date -> addWidget(titleblock_date, 2, 1); - layout_date -> setColumnStretch(0, 1); - layout_date -> setColumnStretch(1, 500); - - titleblock_filename = new QLineEdit(this); - titleblock_folio = new QLineEdit(this); - QLabel *folio_tip = new QLabel( - tr( - "Les variables suivantes sont utilisables dans le champ Folio :\n" - " - %id : num\351ro du sch\351ma courant dans le projet\n" - " - %total : nombre total de sch\351mas dans le projet" - ) - ); - folio_tip -> setWordWrap(true); - - QGridLayout *layout_champs = new QGridLayout(titleblock_infos); - layout_champs -> addWidget(titleblock_template_label, 0, 0); - layout_champs -> addWidget(titleblock_template_name, 0, 1); - layout_champs -> addWidget(new QLabel(tr("Titre : ")), 1, 0); - layout_champs -> addWidget(titleblock_title, 1, 1); - layout_champs -> addWidget(new QLabel(tr("Auteur : ")), 2, 0); - layout_champs -> addWidget(titleblock_author, 2, 1); - layout_champs -> addWidget(new QLabel(tr("Date : ")), 3, 0, Qt::AlignTop); - layout_champs -> addLayout(layout_date, 3, 1); - layout_champs -> addWidget(new QLabel(tr("Fichier : ")), 4, 0); - layout_champs -> addWidget(titleblock_filename, 4, 1); - layout_champs -> addWidget(new QLabel(tr("Folio : ")), 5, 0); - layout_champs -> addWidget(titleblock_folio, 5, 1); - layout_champs -> addWidget(folio_tip, 6, 1, Qt::AlignTop); - layout_champs -> setRowStretch(5, 500); +TitleBlockPropertiesWidget::TitleBlockPropertiesWidget(const TitleBlockProperties &titleblock, bool current, QWidget *parent) : + QWidget(parent), + display_current_date(false) +{ + initWidgets(titleblock); + initLayouts(); + connect(tabbar, SIGNAL(currentChanged(int)), stack_layout, SLOT(setCurrentIndex(int))); titleblock_current_date -> setVisible(display_current_date = current); setTitleBlockProperties(titleblock); - setLayout(this_layout); // by default, we do not display the template combo box titleblock_template_label -> setVisible(false); @@ -125,6 +70,18 @@ TitleBlockProperties TitleBlockPropertiesWidget::titleBlockProperties() const { prop.template_name = titleblock_template_name -> itemData(index).toString(); } + for (int i = 0 ; i < additional_fields_table -> rowCount() ; ++ i) { + QTableWidgetItem *qtwi_name = additional_fields_table -> item(i, 0); + QTableWidgetItem *qtwi_value = additional_fields_table -> item(i, 1); + if (!qtwi_name || !qtwi_value) continue; + + QString key = qtwi_name -> text(); + if (key.isEmpty()) continue; + + QString value = qtwi_value -> text(); + prop.context.addValue(key, value); + } + return(prop); } @@ -196,8 +153,8 @@ void TitleBlockPropertiesWidget::setReadOnly(bool ro) { titleblock_no_date -> setDisabled(ro); titleblock_current_date -> setDisabled(ro); titleblock_fixed_date -> setDisabled(ro); - titleblock_template_label -> setDisabled(ro); - titleblock_template_name -> setDisabled(ro); + titleblock_template_name -> setDisabled(ro); + additional_fields_table -> setDisabled(ro); } /** @@ -220,3 +177,159 @@ void TitleBlockPropertiesWidget::setTitleBlockTemplatesVisible(bool visible) { titleblock_template_name -> setVisible(visible); titleblock_template_label -> setVisible(visible); } + +/** + Adds a row in the additional fields table if needed. +*/ +void TitleBlockPropertiesWidget::checkTableRows() { + if (!nameLessRowsCount()) { + int new_idx = additional_fields_table -> rowCount(); + additional_fields_table -> setRowCount(new_idx + 1); + additional_fields_table -> setItem(new_idx, 0, new QTableWidgetItem("")); + additional_fields_table -> setItem(new_idx, 1, new QTableWidgetItem("")); + } +} + +/** + Builds the various child widgets for this widget +*/ +void TitleBlockPropertiesWidget::initWidgets(const TitleBlockProperties &titleblock) { + titleblock_template_label = new QLabel(tr("Mod\350le :"), this); + titleblock_template_name = new QComboBox(this); + + titleblock_title = new QLineEdit(this); + titleblock_author = new QLineEdit(this); + titleblock_filename = new QLineEdit(this); + + titleblock_folio = new QLineEdit(this); + folio_tip = new QLabel( + tr( + "Les variables suivantes sont utilisables dans le champ Folio :\n" + " - %id : num\351ro du sch\351ma courant dans le projet\n" + " - %total : nombre total de sch\351mas dans le projet" + ) + ); + folio_tip -> setWordWrap(true); + + QButtonGroup *date_policy_group = new QButtonGroup(this); + titleblock_no_date = new QRadioButton(tr("Pas de date"), this); + titleblock_current_date = new QRadioButton(tr("Date courante"), this); + titleblock_fixed_date = new QRadioButton(tr("Date fixe : "), this); + date_policy_group -> addButton(titleblock_no_date); + date_policy_group -> addButton(titleblock_current_date); + date_policy_group -> addButton(titleblock_fixed_date); + titleblock_date = new QDateEdit(QDate::currentDate(), this); + titleblock_date -> setEnabled(titleblock_fixed_date -> isChecked()); + titleblock_current_date -> setVisible(display_current_date); + connect(titleblock_fixed_date, SIGNAL(toggled(bool)), titleblock_date, SLOT(setEnabled(bool))); + titleblock_date -> setCalendarPopup(true); + + additional_fields_label = new QLabel( + tr( + "Vous pouvez définir ici vos propres associations noms/valeurs pour" + " que le cartouche en tienne compte. Exemple : associer le nom " + "\"volta\" et la valeur \"1745\" remplacera %volta par 1745 dans le " + "cartouche." + ) + ); + additional_fields_label -> setWordWrap(true); + additional_fields_label -> setAlignment(Qt::AlignJustify); + int num_rows = titleblock.context.keys().count() + 1; + additional_fields_table = new QTableWidget(num_rows, 2); + additional_fields_table -> setHorizontalHeaderLabels(QStringList() << tr("Nom") << tr("Valeur")); + additional_fields_table -> horizontalHeader() -> setStretchLastSection(true); + + int i = 0; + foreach (QString key, titleblock.context.keys()) { + additional_fields_table -> setItem(i, 0, new QTableWidgetItem(key)); + additional_fields_table -> setItem(i, 1, new QTableWidgetItem(titleblock.context[key].toString())); + ++ i; + } + + connect(additional_fields_table, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(checkTableRows())); + + tabbar = new QTabBar(this); + tabbar -> addTab(tr("Principales")); + tabbar -> addTab(tr("Personnalisées")); + tabbar -> setShape(QTabBar::RoundedSouth); +} + +/** + Builds the various layouts for this widget +*/ +void TitleBlockPropertiesWidget::initLayouts() { + // layouts for tab #0 + QGridLayout *layout_date = new QGridLayout(); + layout_date -> addWidget(titleblock_no_date, 0, 0); + layout_date -> addWidget(titleblock_current_date, 1, 0); + layout_date -> addWidget(titleblock_fixed_date, 2, 0); + layout_date -> addWidget(titleblock_date, 2, 1); + layout_date -> setColumnStretch(0, 1); + layout_date -> setColumnStretch(1, 500); + + QWidget *widget_main_fields = new QWidget(this); + QGridLayout *layout_main_fields = new QGridLayout(widget_main_fields); + layout_main_fields -> addWidget(new QLabel(tr("Titre : ")), 0, 0); + layout_main_fields -> addWidget(titleblock_title, 0, 1); + layout_main_fields -> addWidget(new QLabel(tr("Auteur : ")), 1, 0); + layout_main_fields -> addWidget(titleblock_author, 1, 1); + layout_main_fields -> addWidget(new QLabel(tr("Date : ")), 2, 0, Qt::AlignTop); + layout_main_fields -> addLayout(layout_date, 2, 1); + layout_main_fields -> addWidget(new QLabel(tr("Fichier : ")), 3, 0); + layout_main_fields -> addWidget(titleblock_filename, 3, 1); + layout_main_fields -> addWidget(new QLabel(tr("Folio : ")), 4, 0); + layout_main_fields -> addWidget(titleblock_folio, 4, 1); + layout_main_fields -> addWidget(folio_tip, 5, 1, Qt::AlignTop); + layout_main_fields -> setContentsMargins(0, 0, 0, 0); + layout_main_fields -> setRowStretch(5, 500); + + // layouts for tab #1 + QWidget *widget_user_fields = new QWidget(this); + QVBoxLayout *layout_user_fields = new QVBoxLayout(widget_user_fields); + layout_user_fields -> addWidget(additional_fields_label); + layout_user_fields -> addWidget(additional_fields_table); + layout_user_fields -> setContentsMargins(0, 0, 0, 0); + + // stacked layout + stack_layout = new QStackedLayout(); + stack_layout -> addWidget(widget_main_fields); + stack_layout -> addWidget(widget_user_fields); + stack_layout -> setContentsMargins(0, 0, 0, 0); + stack_layout -> setCurrentIndex(0); + + // template layout + QHBoxLayout *template_layout = new QHBoxLayout(); + template_layout -> addWidget(titleblock_template_label); + template_layout -> addWidget(titleblock_template_name); + template_layout -> setStretch(0, 1); + template_layout -> setStretch(1, 500); + + // groupbox layout + QVBoxLayout *groupbox_layout = new QVBoxLayout(); + groupbox_layout -> addLayout(template_layout); + groupbox_layout -> addLayout(stack_layout); + groupbox_layout -> addWidget(tabbar); + + // groupbox + QGroupBox *titleblock_infos = new QGroupBox(tr("Informations du cartouche"), this); + titleblock_infos -> setLayout(groupbox_layout); + titleblock_infos -> setMinimumSize(300, 330); + + // widget layout + QVBoxLayout *this_layout = new QVBoxLayout(); + this_layout -> setContentsMargins(0, 0, 0, 0); + this_layout -> addWidget(titleblock_infos); + setLayout(this_layout); +} + +/** + @return The count of name-less rows in the additional fields table. +*/ +int TitleBlockPropertiesWidget::nameLessRowsCount() const { + int name_less_rows_count = 0; + for (int i = 0 ; i < additional_fields_table -> rowCount() ; ++ i) { + QTableWidgetItem *qtwi_name = additional_fields_table -> item(i, 0); + if (qtwi_name && qtwi_name -> text().isEmpty()) ++ name_less_rows_count; + } + return(name_less_rows_count); +} diff --git a/sources/titleblockpropertieswidget.h b/sources/titleblockpropertieswidget.h index 1b7408cb4..0a96f5c02 100644 --- a/sources/titleblockpropertieswidget.h +++ b/sources/titleblockpropertieswidget.h @@ -42,18 +42,33 @@ class TitleBlockPropertiesWidget : public QWidget { void setTitleBlockTemplatesList(const QList &); void setTitleBlockTemplatesVisible(bool); + // slots: + private slots: + void checkTableRows(); + + // private methods + private: + void initWidgets(const TitleBlockProperties &); + void initLayouts(); + int nameLessRowsCount() const; + // attributs private: + QStackedLayout *stack_layout; + QLabel *titleblock_template_label; + QComboBox *titleblock_template_name; QLineEdit *titleblock_title; QLineEdit *titleblock_author; QDateEdit *titleblock_date; QLineEdit *titleblock_filename; QLineEdit *titleblock_folio; + QLabel *folio_tip; QRadioButton *titleblock_no_date; QRadioButton *titleblock_current_date; QRadioButton *titleblock_fixed_date; bool display_current_date; - QLabel *titleblock_template_label; - QComboBox *titleblock_template_name; + QLabel *additional_fields_label; + QTableWidget *additional_fields_table; + QTabBar *tabbar; }; #endif