diff --git a/ico/titleblock.png b/ico/titleblock.png
new file mode 100644
index 000000000..c0585d411
Binary files /dev/null and b/ico/titleblock.png differ
diff --git a/qelectrotech.qrc b/qelectrotech.qrc
index dc74de6b5..bf21bb49b 100644
--- a/qelectrotech.qrc
+++ b/qelectrotech.qrc
@@ -180,6 +180,7 @@
ico/oxygen-icons/48x48/apps/qelectrotech.png
ico/oxygen-icons/64x64/apps/qelectrotech.png
ico/splash.png
+ ico/titleblock.png
titleblocks/default.titleblock
LICENSE
diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp
index 95b9a30b6..48e0b19b1 100644
--- a/sources/bordertitleblock.cpp
+++ b/sources/bordertitleblock.cpp
@@ -161,6 +161,35 @@ void BorderTitleBlock::setTitleBlockTemplate(const TitleBlockTemplate *titlebloc
titleblock_template_renderer -> setTitleBlockTemplate(titleblock_template);
}
+/**
+ This slot may be used to inform this class that the given title block
+ template has changed. The title block-dedicated rendering cache will thus be
+ flushed.
+ @param template_name Name of the title block template that has changed
+*/
+void BorderTitleBlock::titleBlockTemplateChanged(const QString &template_name) {
+ Q_UNUSED(template_name); // this class does not store the name of its template
+ titleblock_template_renderer -> invalidateRenderedTemplate();
+}
+
+/**
+ This slot has to be used to inform this class that the given title block
+ template is about to be removed and is no longer accessible. This class
+ will either use the provided optional TitleBlockTemplate or the default
+ title block provided by QETApp::defaultTitleBlockTemplate()
+ @param template_name Name of the title block template that has changed
+ @param new_template (Optional) title block template to use instead
+*/
+void BorderTitleBlock::titleBlockTemplateRemoved(const QString &removed_template_name, const TitleBlockTemplate *new_template) {
+ Q_UNUSED(removed_template_name); // this class does not store the name of its template
+
+ if (new_template) {
+ setTitleBlockTemplate(new_template);
+ } else {
+ setTitleBlockTemplate(QETApp::defaultTitleBlockTemplate());
+ }
+}
+
/**
@param di true pour afficher le cartouche, false sinon
*/
diff --git a/sources/bordertitleblock.h b/sources/bordertitleblock.h
index dfe395dcb..a9502580d 100644
--- a/sources/bordertitleblock.h
+++ b/sources/bordertitleblock.h
@@ -153,6 +153,10 @@ class BorderTitleBlock : public QObject {
const TitleBlockTemplate *titleBlockTemplate();
void setTitleBlockTemplate(const TitleBlockTemplate *);
+ public slots:
+ void titleBlockTemplateChanged(const QString &);
+ void titleBlockTemplateRemoved(const QString &, const TitleBlockTemplate * = 0);
+
// methodes d'acces en ecriture aux options
void displayTitleBlock(bool);
void displayColumns(bool);
diff --git a/sources/diagram.cpp b/sources/diagram.cpp
index 006d27230..ae59d956f 100644
--- a/sources/diagram.cpp
+++ b/sources/diagram.cpp
@@ -765,6 +765,36 @@ void Diagram::diagramTextChanged(DiagramTextItem *text_item, const QString &old_
undo_stack -> push(new ChangeDiagramTextCommand(text_item, old_text, new_text));
}
+/**
+ This slot may be used to inform the diagram object that the given title
+ block template has changed. The diagram will thus flush its title
+ block-dedicated rendering cache.
+ @param template_name Name of the title block template that has changed
+*/
+void Diagram::titleBlockTemplateChanged(const QString &template_name) {
+ if (titleblock_template_name_ == template_name) {
+ border_and_titleblock.titleBlockTemplateChanged(template_name);
+ }
+ update();
+}
+
+/**
+ This slot has to be be used to inform this class that the given title block
+ template is about to be removed and is no longer accessible. This class
+ will either use the provided optional TitleBlockTemplate or the default
+ title block provided by QETApp::defaultTitleBlockTemplate()
+ @param template_name Name of the title block template that has changed
+ @param new_template (Optional) Name of the title block template to use instead
+*/
+void Diagram::titleBlockTemplateRemoved(const QString &template_name, const QString &new_template) {
+ if (titleblock_template_name_ == template_name) {
+ const TitleBlockTemplate *final_template = project_ -> getTemplateByName(new_template);
+ titleblock_template_name_ = final_template ? new_template : QString();
+ border_and_titleblock.titleBlockTemplateRemoved(template_name, final_template);
+ update();
+ }
+}
+
/**
Selectionne tous les objets du schema
*/
diff --git a/sources/diagram.h b/sources/diagram.h
index 8a51ab044..efdbd0e93 100644
--- a/sources/diagram.h
+++ b/sources/diagram.h
@@ -169,6 +169,8 @@ class Diagram : public QGraphicsScene {
public slots:
void diagramTextChanged(DiagramTextItem *, const QString &, const QString &);
+ void titleBlockTemplateChanged(const QString &);
+ void titleBlockTemplateRemoved(const QString &, const QString & = QString());
// fonctions relative a la selection sur le schema
void selectAll();
diff --git a/sources/elementspanel.cpp b/sources/elementspanel.cpp
index 3e42ae4e6..3bbfababd 100644
--- a/sources/elementspanel.cpp
+++ b/sources/elementspanel.cpp
@@ -170,6 +170,24 @@ bool ElementsPanel::itemIsWritable(QTreeWidgetItem *qtwi) const {
return(false);
}
+/**
+ @param qtwi A QTreeWidgetItem
+ @return true if the given QTreeWidgetItem represents a block templates directory
+*/
+bool ElementsPanel::itemIsATitleBlockTemplatesDirectory(QTreeWidgetItem *qtwi) const {
+ return(title_blocks_directories_.contains(qtwi));
+}
+
+/**
+ @param qtwi A QTreeWidgetItem
+ @return true if the given QTreeWidgetItem represents a block template
+*/
+bool ElementsPanel::itemIsATitleBlockTemplate(QTreeWidgetItem *qtwi) const {
+ // does this QTreeWidgetItem have a parent?
+ if (!qtwi -> parent()) return(false);
+ return(itemIsATitleBlockTemplatesDirectory(qtwi -> parent()));
+}
+
/**
@param qtwi Un QTreeWidgetItem
@return L'ElementsCollectionItem represente par qtwi, ou 0 si qtwi ne
@@ -279,6 +297,23 @@ bool ElementsPanel::selectedItemIsWritable() const {
return(false);
}
+/**
+ @return true if the currently selected item represents a title block
+ templates directory
+*/
+bool ElementsPanel::selectedItemIsATitleBlockTemplatesDirectory() const {
+ return(itemIsATitleBlockTemplatesDirectory(currentItem()));
+}
+
+/**
+ @return true if the currently selected item represents a title block
+ template
+*/
+bool ElementsPanel::selectedItemIsATitleBlockTemplate() const {
+ if (!currentItem()) return(false);
+ return(itemIsATitleBlockTemplate(currentItem()));
+}
+
/**
@return la collection, la categorie ou l'element selectionne(e)
*/
@@ -507,6 +542,13 @@ QTreeWidgetItem *ElementsPanel::addProject(QTreeWidgetItem *qtwi_parent, QETProj
addDiagram(qtwi_project, diagram);
}
+ // add the title blocks templates embedded within the project
+ updateProjectTemplates(project);
+ connect(
+ project, SIGNAL(projectTemplatesChanged(QETProject *)),
+ this, SLOT (projectTemplatesChanged(QETProject *))
+ );
+
// ajoute la collection du projet
addCollection(qtwi_project, project -> embeddedCollection(), tr("Collection projet"));
@@ -673,6 +715,7 @@ void ElementsPanel::reload(bool reload_collections) {
locations_.clear();
projects_.clear();
diagrams_.clear();
+ title_blocks_directories_.clear();
common_collection_item_ = 0;
custom_collection_item_ = 0;
@@ -769,6 +812,8 @@ void ElementsPanel::deleteItem(QTreeWidgetItem *removed_item) {
diagrams_.remove(removed_item);
} else if (projects_.contains(removed_item)) {
projects_.remove(removed_item);
+ } else if (title_blocks_directories_.contains(removed_item)) {
+ title_blocks_directories_.remove(removed_item);
}
delete removed_item;
}
@@ -789,6 +834,41 @@ ElementsCategory *ElementsPanel::categoryForPos(const QPoint &pos) {
return(categoryForItem(pos_qtwi));
}
+/**
+ @param qtwi A QTreeWidgetItem, supposed to represent a templates directory
+ @return the project that embeds the given templates directory, if
+ applicable, 0 otherwise
+*/
+QETProject *ElementsPanel::projectForTitleBlockTemplatesDirectory(QTreeWidgetItem *qtwi) {
+ if (title_blocks_directories_.contains(qtwi)) {
+ return(title_blocks_directories_[qtwi]);
+ }
+ return(0);
+}
+
+/**
+ @param qtwi A QTreeWidgetItem, supposed to represent a title block template
+ @return the project that embeds the given template, if applicable, 0
+ otherwise
+*/
+QETProject *ElementsPanel::projectForTitleBlockTemplate(QTreeWidgetItem *qtwi) {
+ if (qtwi->parent()) {
+ return(projectForTitleBlockTemplatesDirectory(qtwi->parent()));
+ }
+ return(0);
+}
+
+/**
+ @param qtwi A QTreeWidgetItem, supposed to represent a title block template
+ @return the name of the given template, if applicable, 0 otherwise
+*/
+QString ElementsPanel::nameOfTitleBlockTemplate(QTreeWidgetItem *qtwi) {
+ if (itemIsATitleBlockTemplate(qtwi)) {
+ return(qtwi -> data(0, 42).toString());
+ }
+ return(QString());
+}
+
/**
Cette methode permet d'acceder a la categorie correspondant a un item donne.
Si cet item represente une collection, c'est sa categorie racine qui est renvoyee.
@@ -860,6 +940,14 @@ void ElementsPanel::projectInformationsChanged(QETProject *project) {
updateProjectItemInformations(project);
}
+/**
+ Handles the fact that the title block templates of a project changed.
+ @param project the modified project
+*/
+void ElementsPanel::projectTemplatesChanged(QETProject *project) {
+ updateProjectTemplates(project);
+}
+
/**
Gere l'ajout d'un schema dans un projet
@param project Projet auquel a ete ajouter le schema
@@ -965,6 +1053,39 @@ void ElementsPanel::updateProjectItemInformations(QETProject *project) {
qtwi_project -> setIcon(0, QET::Icons::Project);
}
+/**
+ (Re)generates the templates list of a given project.
+ @param project the project we want to update the templates
+*/
+void ElementsPanel::updateProjectTemplates(QETProject *project) {
+ // determine the QTWI for the templates directory of the given project
+ QTreeWidgetItem *qtwi_project = projects_.key(project);
+ if (!qtwi_project) return;
+
+ // determine the templates directory for the given project, if any
+ QTreeWidgetItem *titleblock_templates_qtwi = title_blocks_directories_.key(project);
+ if (!titleblock_templates_qtwi) {
+ // the poor thing does not exist... let's create it.
+ titleblock_templates_qtwi = new QTreeWidgetItem(qtwi_project, QStringList() << tr("Mod\350les de cartouche"));
+ titleblock_templates_qtwi -> setIcon(0, QET::Icons::Folder);
+ titleblock_templates_qtwi -> setExpanded(true);
+ title_blocks_directories_.insert(titleblock_templates_qtwi, project);
+ } else {
+ // oh, what a shiny templates directory... let's clear it.
+ foreach(QTreeWidgetItem *titleblock_template_qtwi, titleblock_templates_qtwi -> takeChildren()) {
+ deleteItem(titleblock_template_qtwi);
+ }
+ }
+
+ // we can now populate the templates directory
+ foreach (QString titleblock_name, project -> embeddedTitleBlockTemplates()) {
+ QString final_name = QString(tr("Mod\350le \"%1\"")).arg(titleblock_name);
+ QTreeWidgetItem *titleblock_template_qtwi = new QTreeWidgetItem(titleblock_templates_qtwi, QStringList() << final_name);
+ titleblock_template_qtwi -> setIcon(0, QET::Icons::TitleBlock);
+ titleblock_template_qtwi -> setData(0, 42, titleblock_name); // we store the original title block template name here, since the displayed one could be modified
+ }
+}
+
/**
@param diagram Schema dont on souhaite affiche le titre
@return Un titre affichable, tenant compte du fait que le titre du schema
diff --git a/sources/elementspanel.h b/sources/elementspanel.h
index 668bcba10..a1af64ff0 100644
--- a/sources/elementspanel.h
+++ b/sources/elementspanel.h
@@ -51,6 +51,8 @@ class ElementsPanel : public QTreeWidget {
bool itemIsADiagram(QTreeWidgetItem *) const;
bool itemHasLocation(QTreeWidgetItem *) const;
bool itemIsWritable(QTreeWidgetItem *) const;
+ bool itemIsATitleBlockTemplatesDirectory(QTreeWidgetItem *) const;
+ bool itemIsATitleBlockTemplate(QTreeWidgetItem *) const;
// methodes pour obtenir ce que represente un item donne
ElementsCollectionItem *collectionItemForItem(QTreeWidgetItem *) const;
@@ -59,6 +61,9 @@ class ElementsPanel : public QTreeWidget {
ElementsLocation locationForItem(QTreeWidgetItem *) const;
ElementsCategory *categoryForItem(QTreeWidgetItem *);
ElementsCategory *categoryForPos(const QPoint &);
+ QETProject *projectForTitleBlockTemplatesDirectory(QTreeWidgetItem *);
+ QETProject *projectForTitleBlockTemplate(QTreeWidgetItem *);
+ QString nameOfTitleBlockTemplate(QTreeWidgetItem *);
// methodes pour determiner ce que represente l'item selectionne
bool selectedItemIsACollection() const;
@@ -68,6 +73,8 @@ class ElementsPanel : public QTreeWidget {
bool selectedItemIsADiagram() const;
bool selectedItemHasLocation() const;
bool selectedItemIsWritable() const;
+ bool selectedItemIsATitleBlockTemplatesDirectory() const;
+ bool selectedItemIsATitleBlockTemplate() const;
// methodes pour obtenir ce que represente l'item selectionne
ElementsCollectionItem *selectedItem() const;
@@ -88,6 +95,7 @@ class ElementsPanel : public QTreeWidget {
void projectWasOpened(QETProject *);
void projectWasClosed(QETProject *);
void projectInformationsChanged(QETProject *);
+ void projectTemplatesChanged(QETProject *);
void diagramWasAdded(QETProject *, Diagram *);
void diagramWasRemoved(QETProject *, Diagram *);
void diagramTitleChanged(QETProject *, Diagram *);
@@ -111,6 +119,7 @@ class ElementsPanel : public QTreeWidget {
QTreeWidgetItem *findLocation(const QString &) const;
void deleteItem(QTreeWidgetItem *);
void updateProjectItemInformations(QETProject *);
+ void updateProjectTemplates(QETProject *);
QString diagramTitleToDisplay(Diagram *) const;
void ensureHierarchyIsVisible(QList);
@@ -122,6 +131,7 @@ class ElementsPanel : public QTreeWidget {
QSet projects_to_display_;
QHash projects_;
QHash diagrams_;
+ QHash title_blocks_directories_;
QTreeWidgetItem *common_collection_item_;
QTreeWidgetItem *custom_collection_item_;
};
diff --git a/sources/elementspanelwidget.cpp b/sources/elementspanelwidget.cpp
index 1ec5cb432..1a58142a8 100644
--- a/sources/elementspanelwidget.cpp
+++ b/sources/elementspanelwidget.cpp
@@ -64,6 +64,9 @@ ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) {
prj_del_diagram = new QAction(QET::Icons::DiagramDelete, tr("Supprimer ce sch\351ma"), this);
prj_move_diagram_up = new QAction(QET::Icons::GoUp, tr("Remonter ce sch\351ma"), this);
prj_move_diagram_down = new QAction(QET::Icons::GoDown, tr("Abaisser ce sch\351ma"), this);
+ tbt_add = new QAction(QET::Icons::TitleBlock, tr("Importer un nouveau mod\350le"), this);
+ tbt_edit = new QAction(QET::Icons::TitleBlock, tr("\311diter ce mod\350le"), this);
+ tbt_remove = new QAction(QET::Icons::TitleBlock, tr("Supprimer ce mod\350le"), this);
move_elements_ = new QAction(QET::Icons::MoveFile, tr("D\351placer dans cette cat\351gorie"), this);
copy_elements_ = new QAction(QET::Icons::CopyFile, tr("Copier dans cette cat\351gorie"), this);
cancel_elements_ = new QAction(QET::Icons::Cancel, tr("Annuler"), this);
@@ -102,6 +105,9 @@ ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) {
connect(prj_del_diagram, SIGNAL(triggered()), this, SLOT(deleteDiagram()));
connect(prj_move_diagram_up, SIGNAL(triggered()), this, SLOT(moveDiagramUp()));
connect(prj_move_diagram_down, SIGNAL(triggered()), this, SLOT(moveDiagramDown()));
+ connect(tbt_add, SIGNAL(triggered()), this, SLOT(addTitleBlockTemplate()));
+ connect(tbt_edit, SIGNAL(triggered()), this, SLOT(editTitleBlockTemplate()));
+ connect(tbt_remove, SIGNAL(triggered()), this, SLOT(removeTitleBlockTemplate()));
connect(move_elements_, SIGNAL(triggered()), this, SLOT(moveElements()));
connect(copy_elements_, SIGNAL(triggered()), this, SLOT(copyElements()));
@@ -234,6 +240,49 @@ void ElementsPanelWidget::moveDiagramDown() {
}
}
+/**
+ Opens a template editor to create a new title block template.
+*/
+void ElementsPanelWidget::addTitleBlockTemplate() {
+ QTreeWidgetItem *current_item = elements_panel -> currentItem();
+ if (!current_item) return;
+
+ QETProject *parent_project = 0;
+ if (elements_panel -> itemIsATitleBlockTemplate(current_item)) {
+ parent_project = elements_panel -> projectForTitleBlockTemplate(current_item);
+ } else if (elements_panel -> itemIsATitleBlockTemplatesDirectory(current_item)) {
+ parent_project = elements_panel -> projectForTitleBlockTemplatesDirectory(current_item);
+ }
+
+ if (parent_project) {
+ QETApp::instance() -> openTitleBlockTemplate(parent_project);
+ }
+}
+
+/**
+ Opens an editor to edit the currently selected title block template, if any.
+*/
+void ElementsPanelWidget::editTitleBlockTemplate() {
+ QTreeWidgetItem *current_item = elements_panel -> currentItem();
+ if (current_item && elements_panel -> itemIsATitleBlockTemplate(current_item)) {
+ QETProject *parent_project = elements_panel -> projectForTitleBlockTemplate(current_item);
+ QString template_name = elements_panel -> nameOfTitleBlockTemplate(current_item);
+ QETApp::instance() -> openTitleBlockTemplate(parent_project, template_name);
+ }
+}
+
+/**
+ Delete the currently selected title block template, if any.
+*/
+void ElementsPanelWidget::removeTitleBlockTemplate() {
+ QTreeWidgetItem *current_item = elements_panel -> currentItem();
+ if (current_item && elements_panel -> itemIsATitleBlockTemplate(current_item)) {
+ QETProject *parent_project = elements_panel -> projectForTitleBlockTemplate(current_item);
+ QString template_name = elements_panel -> nameOfTitleBlockTemplate(current_item);
+ parent_project -> removeTemplateByName(template_name);
+ }
+}
+
/**
Appelle l'assistant de creation de nouvel element
*/
@@ -311,6 +360,14 @@ void ElementsPanelWidget::updateButtons() {
prj_del_diagram -> setEnabled(is_writable);
prj_move_diagram_up -> setEnabled(is_writable && diagram_position > 0);
prj_move_diagram_down -> setEnabled(is_writable && diagram_position < project_diagrams_count - 1);
+ } else if (elements_panel -> selectedItemIsATitleBlockTemplatesDirectory()) {
+ bool is_writable = !(elements_panel -> projectForTitleBlockTemplatesDirectory(elements_panel -> currentItem()) -> isReadOnly());
+ tbt_add -> setEnabled(is_writable);
+ } else if (elements_panel -> selectedItemIsATitleBlockTemplate()) {
+ bool is_writable = !(elements_panel -> projectForTitleBlockTemplate(elements_panel -> currentItem()) -> isReadOnly());
+ tbt_add -> setEnabled(is_writable);
+ tbt_edit -> setEnabled(is_writable);
+ tbt_remove -> setEnabled(is_writable);
}
}
@@ -381,6 +438,12 @@ void ElementsPanelWidget::handleContextMenu(const QPoint &pos) {
context_menu -> addAction(prj_del_diagram);
context_menu -> addAction(prj_move_diagram_up);
context_menu -> addAction(prj_move_diagram_down);
+ } else if (elements_panel -> itemIsATitleBlockTemplatesDirectory(item)) {
+ context_menu -> addAction(tbt_add);
+ } else if (elements_panel -> itemIsATitleBlockTemplate(item)) {
+ context_menu -> addAction(tbt_add);
+ context_menu -> addAction(tbt_edit);
+ context_menu -> addAction(tbt_remove);
}
}
diff --git a/sources/elementspanelwidget.h b/sources/elementspanelwidget.h
index c15cdab5a..a50c1856c 100644
--- a/sources/elementspanelwidget.h
+++ b/sources/elementspanelwidget.h
@@ -43,6 +43,7 @@ class ElementsPanelWidget : public QWidget {
QAction *delete_collection;
QAction *new_element, *import_element, *edit_element, *delete_element;
QAction *prj_close, *prj_edit_prop, *prj_prop_diagram, *prj_add_diagram, *prj_del_diagram, *prj_move_diagram_up, *prj_move_diagram_down;
+ QAction *tbt_add, *tbt_edit, *tbt_remove;
QAction *copy_elements_, *move_elements_, *cancel_elements_;
QMenu *context_menu;
QAction *erase_textfield;
@@ -72,6 +73,9 @@ class ElementsPanelWidget : public QWidget {
void deleteDiagram();
void moveDiagramUp();
void moveDiagramDown();
+ void addTitleBlockTemplate();
+ void editTitleBlockTemplate();
+ void removeTitleBlockTemplate();
void newCategory();
void newElement();
void importElement();
diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp
index 58039b5f6..71e2cfb5b 100644
--- a/sources/qetapp.cpp
+++ b/sources/qetapp.cpp
@@ -23,6 +23,7 @@
#include "elementscollectionitem.h"
#include "fileelementscollection.h"
#include "titleblocktemplate.h"
+#include "templateeditor.h"
#include "qetproject.h"
#include "qtextorientationspinboxwidget.h"
#include "recentfiles.h"
@@ -835,6 +836,23 @@ void QETApp::openElementLocations(const QList &locations_list)
}
}
+/**
+ Launch a new title block template editor to edit the given template
+ @param project Parent project of the template to edit
+ @param template_name Name of the template to edit within its parent project
+ If no template name is supplied, the method assumes the editor has to be
+ launched for a template creation.
+*/
+void QETApp::openTitleBlockTemplate(QETProject *project, const QString &template_name) {
+ TemplateEditor *editor = new TemplateEditor();
+ bool can_edit = editor -> edit(project, template_name);
+ if (can_edit) {
+ editor -> showNormal();
+ } else {
+ QMessageBox::warning(0, tr("Erreur"), tr("Impossible d'\351diter le template demand\351"));
+ }
+}
+
/**
Permet a l'utilisateur de configurer QET en lancant un dialogue approprie.
@see ConfigDialog
diff --git a/sources/qetapp.h b/sources/qetapp.h
index 577fecca9..39a61759d 100644
--- a/sources/qetapp.h
+++ b/sources/qetapp.h
@@ -165,6 +165,7 @@ class QETApp : public QETSingleApplication {
void openProjectFiles(const QStringList &);
void openElementFiles(const QStringList &);
void openElementLocations(const QList &);
+ void openTitleBlockTemplate(QETProject *, const QString & = QString());
void configureQET();
void aboutQET();
diff --git a/sources/qeticons.cpp b/sources/qeticons.cpp
index 50a382bab..96e0f8500 100644
--- a/sources/qeticons.cpp
+++ b/sources/qeticons.cpp
@@ -128,6 +128,7 @@ namespace QET {
QIcon South;
QIcon Start;
QIcon Terminal;
+ QIcon TitleBlock;
QIcon UserInformations;
QIcon ViewFitWidth;
QIcon ViewFitWindow;
@@ -304,6 +305,7 @@ void QET::Icons::initIcons() {
South .addFile(":/ico/16x16/south.png");
Start .addFile(":/ico/22x22/start.png");
Terminal .addFile(":/ico/22x22/terminal.png");
+ TitleBlock .addFile(":/ico/titleblock.png");
UserInformations .addFile(":/ico/16x16/preferences-desktop-user.png");
UserInformations .addFile(":/ico/22x22/preferences-desktop-user.png");
ViewFitWidth .addFile(":/ico/22x22/view_fit_width.png");
diff --git a/sources/qeticons.h b/sources/qeticons.h
index 48d60ebb5..de81b7c21 100644
--- a/sources/qeticons.h
+++ b/sources/qeticons.h
@@ -138,6 +138,7 @@ namespace QET {
extern QIcon South;
extern QIcon Start;
extern QIcon Terminal;
+ extern QIcon TitleBlock;
extern QIcon UserInformations;
extern QIcon ViewFitWidth;
extern QIcon ViewFitWindow;
diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp
index ae5cbf9a9..177542307 100644
--- a/sources/qetproject.cpp
+++ b/sources/qetproject.cpp
@@ -312,6 +312,70 @@ QDomElement QETProject::getTemplateXmlDescriptionByName(const QString &template_
return(QDomElement());
}
+/**
+ This methods allows adding or modifying a template embedded within the
+ project. This method emits the signal projectTemplatesChanged() if
+ necessary.
+ @param template_name Name / Identifier of the template - will be used to
+ determine whether the given description will be added or will replace an
+ existing one.
+ @param xml_elmt An \ XML element describing the
+ template. Its "name" attribute must equal to template_name.
+ @return false if a problem occured, true otherwise
+*/
+bool QETProject::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_elmt) {
+ // checks basic stuff
+ if (xml_elmt.tagName() != "titleblocktemplate" || xml_elmt.attribute("name") != template_name) {
+ return(false);
+ }
+
+ // we import the provided XML element in the project document
+ QDomElement import = document_root_.importNode(xml_elmt, true).toElement();
+
+ // we either replace the previous description
+ if (titleblock_templates_xml_.contains(template_name)) {
+ QDomElement old_description = titleblock_templates_xml_[template_name];
+ if (!old_description.parentNode().isNull()) {
+ old_description.parentNode().replaceChild(import, old_description);
+ titleblock_templates_xml_[template_name] = import;
+ }
+ } else {
+ // or simply insert the new one
+ titleblock_templates_xml_.insert(template_name, import);
+ }
+
+ if (titleblock_templates_.contains(template_name)) {
+ titleblock_templates_[template_name] -> loadFromXmlElement(titleblock_templates_xml_[template_name]);
+ foreach (Diagram *diagram, diagrams_) {
+ diagram -> titleBlockTemplateChanged(template_name);
+ }
+ }
+ emit(projectTemplatesChanged(this));
+
+ return(true);
+}
+
+/**
+ This methods allows removing a template embedded within the project. This
+ method emits the signal projectTemplatesChanged() if necessary.
+ @param template_name Name of the template to be removed
+*/
+void QETProject::removeTemplateByName(const QString &template_name) {
+ if (titleblock_templates_.contains(template_name)) {
+ // warn diagrams that the given template is about to be removed
+ foreach (Diagram *diagram, diagrams_) {
+ diagram -> titleBlockTemplateRemoved(template_name); /// TODO specify the default template of the project as a fallback
+ }
+ }
+
+ // remove the template itself
+ titleblock_templates_xml_.remove(template_name);
+ titleblock_templates_.remove(template_name);
+
+ // warn the rest of the world that the list of templates embedded within this project has changed
+ emit(projectTemplatesChanged(this));
+}
+
/**
@return les dimensions par defaut utilisees lors de la creation d'un
nouveau schema dans ce projet.
diff --git a/sources/qetproject.h b/sources/qetproject.h
index 148bb9ecd..678d5f91d 100644
--- a/sources/qetproject.h
+++ b/sources/qetproject.h
@@ -83,6 +83,8 @@ class QETProject : public QObject {
QList embeddedTitleBlockTemplates() const;
const TitleBlockTemplate *getTemplateByName(const QString &template_name);
QDomElement getTemplateXmlDescriptionByName(const QString &);
+ bool setTemplateXmlDescription(const QString &, const QDomElement &);
+ void removeTemplateByName(const QString &);
BorderProperties defaultBorderProperties() const;
void setDefaultBorderProperties(const BorderProperties &);
TitleBlockProperties defaultTitleBlockProperties() const;
@@ -119,6 +121,7 @@ class QETProject : public QObject {
void diagramAdded(QETProject *, Diagram *);
void diagramRemoved(QETProject *, Diagram *);
void readOnlyChanged(QETProject *, bool);
+ void projectTemplatesChanged(QETProject *);
private slots:
void updateDiagramsFolioData();
diff --git a/sources/templateeditor.cpp b/sources/templateeditor.cpp
new file mode 100644
index 000000000..e6a42a9a2
--- /dev/null
+++ b/sources/templateeditor.cpp
@@ -0,0 +1,170 @@
+#include "templateeditor.h"
+#include
+#include "qetproject.h"
+#include "qetapp.h"
+
+/**
+ Constructor
+ @param parent parent QWidget for this editor
+ @param f Windows flags for this editor
+ @see QWidget()
+*/
+TemplateEditor::TemplateEditor(QWidget *parent, Qt::WindowFlags f) :
+ QWidget(parent, f),
+ parent_project_(0)
+{
+ build();
+}
+
+/**
+ Destructor
+*/
+TemplateEditor::~TemplateEditor() {
+}
+
+/**
+ Edit the given template.
+ @param project Parent project of the template to edit.
+ @param template_name Name of the template to edit within its parent project.
+*/
+bool TemplateEditor::edit(QETProject *project, const QString &template_name) {
+ // we require a project we will rattach templates to
+ if (!project) return(false);
+ parent_project_ = project;
+ updateProjectLabel();
+
+ // the template name may be empty to create a new element
+ if (template_name.isEmpty()) {
+ template_name_edit_ -> setText(tr("Nouveau-modele"));
+ template_name_edit_ -> setReadOnly(false);
+ return(true);
+ }
+
+ QDomElement xml_tb_template = project -> getTemplateXmlDescriptionByName(template_name);
+ if (!xml_tb_template.isNull()) {
+ QDomDocument xml_doc;
+ xml_doc.appendChild(xml_doc.importNode(xml_tb_template, true));
+ template_name_edit_ -> setText(template_name);
+ template_name_edit_ -> setReadOnly(true);
+ template_xml_edit_ -> setPlainText(xml_doc.toString(4));
+
+ // stores the parent project and template name, in order to write/save the template later
+ template_name_ = template_name;
+ return(true);
+ }
+ return(false);
+}
+
+/**
+ Validates the content of the current text area. It has to be a valid XML
+ description of a title block template for this method not to display a
+ message to the user.
+ @todo implement it.
+*/
+void TemplateEditor::validate() {
+ QMessageBox::information(
+ this,
+ tr("Not implemented yet"),
+ tr("Sorry, Not implemented yet")
+ );
+}
+
+/**
+ Saves the content of the current text area to a template within the project.
+*/
+void TemplateEditor::save() {
+ if (!parent_project_) return;
+
+ // are we creating a new template?
+ if (!template_name_edit_ -> isReadOnly()) {
+ // Yes, so we must ensure the new name will not clatch with an existing ine
+ if (parent_project_ -> embeddedTitleBlockTemplates().contains(template_name_edit_ -> text())) {
+ QMessageBox::critical(
+ this,
+ tr("Un mod\350le de ce nom existe d\351j\340"),
+ tr("Un mod\350le de ce nom existe d\351j\340 au sein du projet - veuillez choisir un autre nom.")
+ );
+ /// TODO propose to overwrite the existing template?
+ return;
+ }
+
+ }
+
+ QDomDocument xml_doc;
+ bool parsing = xml_doc.setContent(template_xml_edit_ -> toPlainText());
+ if (!parsing) {
+ 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.")
+ );
+ return;
+ }
+
+ if (!template_name_edit_ -> isReadOnly()) {
+ template_name_edit_ -> setReadOnly(true);
+ template_name_ = template_name_edit_ -> text();
+ }
+ parent_project_ -> setTemplateXmlDescription(template_name_, xml_doc.documentElement());
+}
+
+/**
+ Exits this editor.
+*/
+void TemplateEditor::quit() {
+ /// TODO save if needed
+ close();
+}
+
+/**
+ Builds the user interface.
+*/
+void TemplateEditor::build() {
+ parent_project_label_ = new QLabel();
+ updateProjectLabel();
+ template_name_edit_ = new QLineEdit();
+ template_xml_edit_ = new QTextEdit();
+ template_xml_edit_ -> setAcceptRichText(false);
+ template_xml_edit_ -> setFontFamily("monospace");
+ template_xml_edit_ -> setWordWrapMode(QTextOption::NoWrap);
+
+ validate_button_ = new QPushButton(tr("V\351rifier le mod\350le"));
+ save_button_ = new QPushButton(tr("Enregistrer et appliquer"));
+ quit_button_ = new QPushButton(tr("Quitter"));
+
+ connect(validate_button_, SIGNAL(released()), this, SLOT(validate()));
+ connect(save_button_, SIGNAL(released()), this, SLOT(save()));
+ connect(quit_button_, SIGNAL(released()), this, SLOT(quit()));
+
+ QHBoxLayout *h_layout0 = new QHBoxLayout();
+ h_layout0 -> addWidget(validate_button_);
+ h_layout0 -> addWidget(save_button_);
+ h_layout0 -> addWidget(quit_button_);
+
+ QVBoxLayout *v_layout0 = new QVBoxLayout();
+ v_layout0 -> addWidget(parent_project_label_);
+ v_layout0 -> addWidget(template_name_edit_);
+ v_layout0 -> addWidget(template_xml_edit_);
+ v_layout0 -> addLayout(h_layout0);
+
+ setLayout(v_layout0);
+
+ setWindowTitle(tr("QElectroTech - \311diteur de mod\350le de cartouche"));
+ resize(700, 500);
+}
+
+/**
+ Updates the "Parent project:" label.
+*/
+void TemplateEditor::updateProjectLabel() {
+ QString parent_project_title;
+ if (parent_project_) {
+ parent_project_title = parent_project_ -> pathNameTitle();
+ } else {
+ parent_project_title = tr("Non d\351fini");
+ }
+
+ parent_project_label_ -> setText(
+ QString(tr("Projet parent : %1")).arg(parent_project_title)
+ );
+}
diff --git a/sources/templateeditor.h b/sources/templateeditor.h
new file mode 100644
index 000000000..10c755317
--- /dev/null
+++ b/sources/templateeditor.h
@@ -0,0 +1,60 @@
+/*
+ Copyright 2006-2010 Xavier Guerrin
+ 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 .
+*/
+#ifndef TEMPLATE_EDITOR_H
+#define TEMPLATE_EDITOR_H
+#include
+class QETProject;
+/**
+ This class allows the user to edit a title block template.
+ For the moment, it simply provides a text editor.
+*/
+class TemplateEditor : public QWidget {
+ Q_OBJECT
+
+ // constructors, destructor
+ public:
+ TemplateEditor(QWidget * = 0, Qt::WindowFlags = 0);
+ virtual ~TemplateEditor();
+ private:
+ TemplateEditor(const TemplateEditor &);
+
+ // method\s
+ public:
+ bool edit(QETProject *, const QString &);
+
+ private slots:
+ void validate();
+ void save();
+ void quit();
+
+ private:
+ void build();
+ void updateProjectLabel();
+
+ // attributes
+ private:
+ QLabel *parent_project_label_;
+ QLineEdit *template_name_edit_;
+ QTextEdit *template_xml_edit_;
+ QPushButton *validate_button_;
+ QPushButton *save_button_;
+ QPushButton *quit_button_;
+ QETProject *parent_project_;
+ QString template_name_;
+};
+#endif
diff --git a/sources/titleblocktemplate.cpp b/sources/titleblocktemplate.cpp
index 74bdf1d4a..46a01fbce 100644
--- a/sources/titleblocktemplate.cpp
+++ b/sources/titleblocktemplate.cpp
@@ -486,7 +486,7 @@ void TitleBlockTemplate::render(QPainter &painter, const DiagramContext &diagram
// run through each inidividual cell
for (int j = 0 ; j < rows_heights_.count() ; ++ j) {
for (int i = 0 ; i < columns_width_.count() ; ++ i) {
- if (cells_[i][j].spanner_cell) continue;
+ if (cells_[i][j].spanner_cell || cells_[i][j].is_null) continue;
// calculate the border rect of the current cell
int x = lengthRange(0, cells_[i][j].num_col, widths);
diff --git a/sources/titleblocktemplaterenderer.h b/sources/titleblocktemplaterenderer.h
index 2f84c1180..7ac0c7e15 100644
--- a/sources/titleblocktemplaterenderer.h
+++ b/sources/titleblocktemplaterenderer.h
@@ -31,10 +31,10 @@ class TitleBlockTemplateRenderer : public QObject {
void setContext(const DiagramContext &context);
int height() const;
void render(QPainter *, int);
+ void invalidateRenderedTemplate();
private:
void renderToQPicture(int);
- void invalidateRenderedTemplate();
private:
const TitleBlockTemplate *titleblock_template_;