[qet] [1433] Implemented the common and custom title block templates collections.

[ Thread Index | Date Index | More lists.tuxfamily.org/qet Archives ]


Revision: 1433
Author:   xavier
Date:     2012-01-08 18:04:34 +0100 (Sun, 08 Jan 2012)
Log Message:
-----------
Implemented the common and custom title block templates collections.

Modified Paths:
--------------
    branches/0.3/qelectrotech.pro
    branches/0.3/sources/elementspanel.cpp
    branches/0.3/sources/elementspanel.h
    branches/0.3/sources/elementspanelwidget.cpp
    branches/0.3/sources/qetapp.cpp
    branches/0.3/sources/qetapp.h
    branches/0.3/sources/qetarguments.cpp
    branches/0.3/sources/qetarguments.h
    branches/0.3/sources/qetproject.cpp
    branches/0.3/sources/qetproject.h
    branches/0.3/sources/titleblock/qettemplateeditor.cpp
    branches/0.3/sources/titleblock/qettemplateeditor.h
    branches/0.3/sources/titleblock/templatedeleter.cpp
    branches/0.3/sources/titleblock/templatelocation.cpp
    branches/0.3/sources/titleblock/templatelocation.h
    branches/0.3/sources/titleblock/templatelocationchooser.cpp
    branches/0.3/sources/titleblock/templatelocationchooser.h

Added Paths:
-----------
    branches/0.3/sources/titleblock/templatescollection.cpp
    branches/0.3/sources/titleblock/templatescollection.h

Modified: branches/0.3/qelectrotech.pro
===================================================================
--- branches/0.3/qelectrotech.pro	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/qelectrotech.pro	2012-01-08 17:04:34 UTC (rev 1433)
@@ -9,6 +9,7 @@
 	INSTALL_PREFIX             = '/usr/local/'
 	QET_BINARY_PATH            = 'bin/'
 	QET_COMMON_COLLECTION_PATH = 'share/qelectrotech/elements/'
+	QET_COMMON_TBT_PATH        = 'share/qelectrotech/titleblocks/'
 	QET_LANG_PATH              = 'share/qelectrotech/lang/'
 	QET_EXAMPLES_PATH          = 'share/qelectrotech/examples/'
 	QET_LICENSE_PATH           = 'doc/qelectrotech/'
@@ -25,6 +26,7 @@
 	INSTALL_PREFIX             = './'
 	QET_BINARY_PATH            = './'
 	QET_COMMON_COLLECTION_PATH = 'elements/'
+	QET_COMMON_TBT_PATH        = 'titleblocks/'
 	QET_LANG_PATH              = 'lang/'
 	QET_LICENSE_PATH           = './'
 }
@@ -34,6 +36,7 @@
 	INSTALL_PREFIX             = '/usr/local/'
 	QET_BINARY_PATH            = 'bin/'
 	QET_COMMON_COLLECTION_PATH = '../Resources/elements/'
+	QET_COMMON_TBT_PATH        = '../Resources/titleblocks/'
 	QET_LANG_PATH              = '../Resources/lang/'
 	QET_EXAMPLES_PATH          = 'share/qelectrotech/examples/'
 	QET_LICENSE_PATH           = 'doc/qelectrotech/'
@@ -47,6 +50,9 @@
 # Commenter la ligne ci-dessous pour desactiver l'option --common-elements-dir
 DEFINES += QET_ALLOW_OVERRIDE_CED_OPTION
 
+# Comment the line below to disable the --common-tbt-dir option
+DEFINES += QET_ALLOW_OVERRIDE_CTBTD_OPTION
+
 # Commenter la ligne ci-dessous pour desactiver l'option --config-dir
 DEFINES += QET_ALLOW_OVERRIDE_CD_OPTION
 
@@ -88,6 +94,9 @@
 elements.path      = $$join(INSTALL_PREFIX,,,$${QET_COMMON_COLLECTION_PATH})
 elements.files     = elements/*
 
+tbt.path           = $$join(INSTALL_PREFIX,,,$${QET_COMMON_TBT_PATH})
+tbt.files          = titleblocks/*
+
 lang.path          = $$join(INSTALL_PREFIX,,,$${QET_LANG_PATH})
 lang.files         = $$replace(TRANSLATIONS, '.ts', '.qm')
 
@@ -136,6 +145,8 @@
 	
 	# Chemin de la collection commune ; par defaut : elements/ dans le repertoire d'execution
 	DEFINES += QET_COMMON_COLLECTION_PATH=$$join(COMPIL_PREFIX,,,$${QET_COMMON_COLLECTION_PATH})
+	
+	DEFINES += QET_COMMON_TBT_PATH=$$join(COMPIL_PREFIX,,,$${QET_COMMON_TBT_PATH})
 }
 
 # Options de compilation specifiques a MacOS X

Modified: branches/0.3/sources/elementspanel.cpp
===================================================================
--- branches/0.3/sources/elementspanel.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/elementspanel.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -25,6 +25,7 @@
 #include "fileelementscollection.h"
 #include "fileelementdefinition.h"
 #include "qeticons.h"
+#include "templatescollection.h"
 
 /**
 	This class implements a thread reloading the following elements
@@ -204,8 +205,12 @@
 	@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));
+bool ElementsPanel::itemIsATitleBlockTemplatesCollection(QTreeWidgetItem *qtwi) const {
+	return(
+		qtwi == custom_tbt_collection_item_ ||
+		qtwi == common_tbt_collection_item_ ||
+		title_blocks_collections_.contains(qtwi)
+	);
 }
 
 /**
@@ -213,9 +218,7 @@
 	@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()));
+	return(title_blocks_.contains(qtwi));
 }
 
 /**
@@ -333,7 +336,7 @@
 	templates directory
 */
 bool ElementsPanel::selectedItemIsATitleBlockTemplatesDirectory() const {
-	return(itemIsATitleBlockTemplatesDirectory(currentItem()));
+	return(itemIsATitleBlockTemplatesCollection(currentItem()));
 }
 
 /**
@@ -563,9 +566,9 @@
 	@return Le QTreeWidgetItem insere le plus haut
 */
 QTreeWidgetItem *ElementsPanel::addProject(QTreeWidgetItem *qtwi_parent, QETProject *project) {
-	// le projet sera insere juste avant la collection commune
+	// the project will be inserted right before the common tb templates collection
 	QTreeWidgetItem *last_project = 0;
-	if (int common_collection_item_idx = indexOfTopLevelItem(common_collection_item_)) {
+	if (int common_collection_item_idx = indexOfTopLevelItem(common_tbt_collection_item_)) {
 		last_project = topLevelItem(common_collection_item_idx - 1);
 	}
 	
@@ -584,14 +587,10 @@
 		addDiagram(qtwi_project, diagram);
 	}
 	
-	// add the title blocks templates embedded within the project
-	updateProjectTemplates(project);
-	connect(
-		project, SIGNAL(projectTemplatesChanged(QETProject *)),
-		this,    SLOT  (projectTemplatesChanged(QETProject *))
-	);
+	// add the embedded title block templates collection
+	addTitleBlockTemplatesCollection(qtwi_project, project -> embeddedTitleBlockTemplatesCollection());
 	
-	// ajoute la collection du projet
+	// add the embedded elements collection
 	addCollection(qtwi_project, project -> embeddedCollection(), tr("Collection projet"));
 	
 	return(qtwi_project);
@@ -739,6 +738,64 @@
 }
 
 /**
+	Adds \a collection under \a qtwi_parent with the given \a label and \a icon.
+	@param qtwi_parent Parent QTreeWidgetItem
+	@param collection Title block templates collection to be added to the panel
+	@param label Label for the returned QTreeWidgetItem
+	@param icon  Label for the returned QTreeWidgetItem
+	@return the QTreeWidgetItem representing the collection
+*/
+QTreeWidgetItem *ElementsPanel::addTitleBlockTemplatesCollection(
+	QTreeWidgetItem *qtwi_parent,
+	TitleBlockTemplatesCollection *collection,
+	const QString &label,
+	const QIcon &icon
+) {
+	if (!collection) return(0);
+	
+	// check whether we have an item for the given collection
+	QTreeWidgetItem *qtwi_tbt_collection = title_blocks_collections_.key(collection);
+	if (!qtwi_tbt_collection) {
+		// the collection has not been added yet
+		QString final_label(label.isEmpty() ? tr("Mod\350les de cartouche") : label);
+		QIcon final_icon(icon.isNull() ? QET::Icons::TitleBlock : icon);
+		
+		// create the QTreeWidgetItem representing the collection itself
+		qtwi_tbt_collection = new QTreeWidgetItem(qtwi_parent, QStringList(final_label));
+		qtwi_tbt_collection -> setIcon(0, final_icon);
+		qtwi_tbt_collection -> setToolTip(0, collection -> location().toString());
+		qtwi_tbt_collection -> setExpanded(true);
+		title_blocks_collections_.insert(qtwi_tbt_collection, collection);
+		
+		// ensure the added collection will inform us about its changes
+		connect(
+			collection,
+			SIGNAL(changed(TitleBlockTemplatesCollection*, const QString &)),
+			this,
+			SLOT(titleBlockTemplatesCollectionChanged(TitleBlockTemplatesCollection*, const QString &))
+		);
+	} else {
+		// the collection has already been added
+		// remove the child title block templates
+		foreach(QTreeWidgetItem *qtwi_tbt, qtwi_tbt_collection -> takeChildren()) {
+			deleteItem(qtwi_tbt);
+		}
+	}
+	
+	// add the templates
+	foreach (QString template_name, collection -> templates()) {
+		QString final_name = titleBlockTemplateNameToDisplay(template_name);
+		TitleBlockTemplateLocation template_location = collection -> location(template_name);
+		
+		QTreeWidgetItem *qtwi_tbt = new QTreeWidgetItem(qtwi_tbt_collection, QStringList(final_name));
+		qtwi_tbt -> setToolTip(0, template_location.toString());
+		qtwi_tbt -> setIcon(0, QET::Icons::TitleBlock);
+		title_blocks_.insert(qtwi_tbt, template_location);
+	}
+	return(qtwi_tbt_collection);
+}
+
+/**
 	Reloads the following collections:
 	  * common collection
 	  * custom collection
@@ -790,34 +847,49 @@
 	locations_.clear();
 	projects_.clear();
 	diagrams_.clear();
-	title_blocks_directories_.clear();
+	title_blocks_collections_.clear();
+	title_blocks_.clear();
 	common_collection_item_ = 0;
 	custom_collection_item_ = 0;
 	
+	QIcon system_icon(":/ico/16x16/qet.png");
+	QIcon user_icon(":/ico/16x16/go-home.png");
+	
+	
 	// estimates the number of categories and elements to load
 	int items_count = elementsCollectionItemsCount();
 	emit(loadingProgressed(loading_progress_ = 0, items_count));
 	
+	// load the common title block templates collection
+	TitleBlockTemplatesCollection *common_tbt_collection = QETApp::commonTitleBlockTemplatesCollection();
+	common_tbt_collection_item_ = addTitleBlockTemplatesCollection(invisibleRootItem(), common_tbt_collection, common_tbt_collection -> title(), system_icon);
+	if (first_reload_) common_tbt_collection_item_ -> setExpanded(true);
+	
 	// chargement des elements de la collection QET
 	if (QETApp::commonElementsCollection()->rootCategory()) {
-		common_collection_item_ = addCollection(invisibleRootItem(), QETApp::commonElementsCollection(), tr("Collection QET"),         QIcon(":/ico/16x16/qet.png"));
+		common_collection_item_ = addCollection(invisibleRootItem(), QETApp::commonElementsCollection(), tr("Collection QET"), system_icon);
 		if (first_reload_) common_collection_item_ -> setExpanded(true);
 	}
 	
+	// load the custom title block templates collection
+	TitleBlockTemplatesCollection *custom_tbt_collection = QETApp::customTitleBlockTemplatesCollection();
+	custom_tbt_collection_item_ = addTitleBlockTemplatesCollection(invisibleRootItem(), custom_tbt_collection, custom_tbt_collection -> title(), user_icon);
+	if (first_reload_) custom_tbt_collection_item_ -> setExpanded(true);
+	
 	// chargement des elements de la collection utilisateur
 	if (QETApp::customElementsCollection()->rootCategory()) {
-		custom_collection_item_ = addCollection(invisibleRootItem(), QETApp::customElementsCollection(), tr("Collection utilisateur"), QIcon(":/ico/16x16/go-home.png"));
+		custom_collection_item_ = addCollection(invisibleRootItem(), QETApp::customElementsCollection(), tr("Collection utilisateur"), user_icon);
 		if (first_reload_) custom_collection_item_ -> setExpanded(true);
 	}
 	
-	// the first time, expand the first level of collections
-	if (first_reload_) first_reload_ = false;
-	
 	// chargement des projets
 	foreach(QETProject *project, projects_to_display_.values()) {
 		addProject(invisibleRootItem(), project);
 	}
 	
+	// the first time, expand the first level of collections
+	if (first_reload_) first_reload_ = false;
+	
 	// reselectionne le dernier element selectionne
 	if (!last_selected_item.isNull()) {
 		QTreeWidgetItem *qtwi = findLocation(last_selected_item);
@@ -843,9 +915,7 @@
 	} else if (ElementsCollectionItem *item = collectionItemForItem(qtwi)) {
 		emit(requestForCollectionItem(item));
 	} else if (itemIsATitleBlockTemplate(qtwi)) {
-		if (QETProject *project = projectForTitleBlockTemplate(qtwi)) {
-			emit(requestForTitleBlockTemplate(project, nameOfTitleBlockTemplate(qtwi)));
-		}
+		emit(requestForTitleBlockTemplate(title_blocks_[qtwi]));
 	}
 }
 
@@ -899,8 +969,10 @@
 		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);
+	} else if (title_blocks_collections_.contains(removed_item)) {
+		title_blocks_collections_.remove(removed_item);
+	} else if (title_blocks_.contains(removed_item)) {
+		title_blocks_.remove(removed_item);
 	}
 	
 	// supprime les eventuels enfants de l'item
@@ -928,36 +1000,27 @@
 }
 
 /**
-	@param qtwi A QTreeWidgetItem, supposed to represent a templates directory
-	@return the project that embeds the given templates directory, if
-	applicable, 0 otherwise
+	@param qtwi A QTreeWidgetItem, supposed to represent either a title block
+	@template or a title block templates collection. return the adequate title
+	@block template location
 */
-QETProject *ElementsPanel::projectForTitleBlockTemplatesDirectory(QTreeWidgetItem *qtwi) {
-	if (title_blocks_directories_.contains(qtwi)) {
-		return(title_blocks_directories_[qtwi]);
+TitleBlockTemplateLocation ElementsPanel::locationForTitleBlockTemplate(QTreeWidgetItem *qtwi) {
+	if (title_blocks_.contains(qtwi)) {
+		// the QTreeWidgetItem is a title block template
+		return(title_blocks_[qtwi]);
+	} else if (title_blocks_collections_.contains(qtwi)) {
+		return(title_blocks_collections_[qtwi] -> location());
 	}
-	return(0);
+	return(TitleBlockTemplateLocation());
 }
 
 /**
 	@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());
+	if (title_blocks_.contains(qtwi)) {
+		return(title_blocks_[qtwi].name());
 	}
 	return(QString());
 }
@@ -1034,11 +1097,16 @@
 }
 
 /**
-	Handles the fact that the title block templates of a project changed.
-	@param project the modified project
+	@param collection Title block templates collection that changed and should be updated
+	@param template_name Name of the changed template (unused)
 */
-void ElementsPanel::projectTemplatesChanged(QETProject *project) {
-	updateProjectTemplates(project);
+void ElementsPanel::titleBlockTemplatesCollectionChanged(TitleBlockTemplatesCollection*collection, const QString &template_name) {
+	Q_UNUSED(template_name)
+	
+	QTreeWidgetItem *qtwi_parent = title_blocks_collections_.key(collection);
+	if (!qtwi_parent) qtwi_parent = invisibleRootItem();
+	
+	addTitleBlockTemplatesCollection(qtwi_parent, collection);
 }
 
 /**
@@ -1156,7 +1224,7 @@
 	
 	// determine le nom et l'icone du projet
 	QString final_name(project -> pathNameTitle());
-	QString final_tooltip = project -> filePath();
+	QString final_tooltip = QDir::toNativeSeparators(project -> filePath());
 	if (final_tooltip.isEmpty()) {
 		final_tooltip = tr(
 			"Pas de fichier",
@@ -1173,7 +1241,7 @@
 	(Re)generates the templates list of a given project.
 	@param project the project we want to update the templates
 */
-void ElementsPanel::updateProjectTemplates(QETProject *project) {
+/*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;
@@ -1194,13 +1262,18 @@
 	}
 	
 	// 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);
+	TitleBlockTemplatesCollection *collection = project -> embeddedTitleBlockTemplatesCollection();
+	if (!collection) {
+		// this stinks...
+		return;
+	}
+	foreach (QString titleblock_name, collection -> templates()) {
+		QString final_name = titleBlockTemplateNameToDisplay(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
+		titleblocks_.insert(titleblock_template_qtwi, collection -> location(titleblock_name));
 	}
-}
+}*/
 
 /**
 	Updates the label of a diagram displayed by the elements panel
@@ -1246,6 +1319,14 @@
 }
 
 /**
+	@param template_name Name of a title block template
+	@return a displayable title
+*/
+QString ElementsPanel::titleBlockTemplateNameToDisplay(const QString &template_name) const {
+	return(tr("Mod\350le \"%1\"", "used to display a title block template").arg(template_name));
+}
+
+/**
 	@param items une liste de QTreeWidgetItem pour lesquels il faut s'assurer
 	que eux et leurs parents sont visibles
 */

Modified: branches/0.3/sources/elementspanel.h
===================================================================
--- branches/0.3/sources/elementspanel.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/elementspanel.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -19,6 +19,7 @@
 #define PANELAPPAREILS_H
 #include <QtGui>
 #include "elementslocation.h"
+#include "templatelocation.h"
 class QETProject;
 class Diagram;
 class ElementsCollection;
@@ -26,6 +27,8 @@
 class ElementsCategory;
 class ElementDefinition;
 class ElementsCollectionCache;
+class TitleBlockTemplatesFilesCollection;
+
 /**
 	Cette classe represente le panel d'appareils (en tant qu'element
 	graphique) dans lequel l'utilisateur choisit les composants de
@@ -52,7 +55,7 @@
 	bool itemIsADiagram(QTreeWidgetItem *) const;
 	bool itemHasLocation(QTreeWidgetItem *) const;
 	bool itemIsWritable(QTreeWidgetItem *) const;
-	bool itemIsATitleBlockTemplatesDirectory(QTreeWidgetItem *) const;
+	bool itemIsATitleBlockTemplatesCollection(QTreeWidgetItem *) const;
 	bool itemIsATitleBlockTemplate(QTreeWidgetItem *) const;
 	
 	// methodes pour obtenir ce que represente un item donne
@@ -62,8 +65,7 @@
 	ElementsLocation locationForItem(QTreeWidgetItem *) const;
 	ElementsCategory *categoryForItem(QTreeWidgetItem *);
 	ElementsCategory *categoryForPos(const QPoint &);
-	QETProject *projectForTitleBlockTemplatesDirectory(QTreeWidgetItem *);
-	QETProject *projectForTitleBlockTemplate(QTreeWidgetItem *);
+	TitleBlockTemplateLocation locationForTitleBlockTemplate(QTreeWidgetItem *);
 	QString nameOfTitleBlockTemplate(QTreeWidgetItem *);
 	
 	// methodes pour determiner ce que represente l'item selectionne
@@ -91,7 +93,7 @@
 	void requestForDiagram(Diagram *);
 	void requestForCollectionItem(ElementsCollectionItem *);
 	void requestForMoveElements(ElementsCollectionItem *, ElementsCollectionItem *, QPoint);
-	void requestForTitleBlockTemplate(QETProject *, const QString &);
+	void requestForTitleBlockTemplate(const TitleBlockTemplateLocation &);
 	void readingAboutToBegin();
 	void readingFinished();
 	void loadingProgressed(int, int);
@@ -103,7 +105,7 @@
 	void projectWasOpened(QETProject *);
 	void projectWasClosed(QETProject *);
 	void projectInformationsChanged(QETProject *);
-	void projectTemplatesChanged(QETProject *);
+	void titleBlockTemplatesCollectionChanged(TitleBlockTemplatesCollection*, const QString & = QString());
 	void diagramWasAdded(QETProject *, Diagram *);
 	void diagramWasRemoved(QETProject *, Diagram *);
 	void diagramTitleChanged(QETProject *, Diagram *);
@@ -123,14 +125,15 @@
 	QTreeWidgetItem *addCollection(QTreeWidgetItem *, ElementsCollection *, const QString & = QString(), const QIcon & = QIcon());
 	QTreeWidgetItem *addCategory  (QTreeWidgetItem *, ElementsCategory   *, const QString & = QString(), const QIcon & = QIcon());
 	QTreeWidgetItem *addElement   (QTreeWidgetItem *, ElementDefinition  *, const QString & = QString());
+	QTreeWidgetItem *addTitleBlockTemplatesCollection(QTreeWidgetItem *, TitleBlockTemplatesCollection *, const QString & = QString(), const QIcon & = QIcon());
 	void saveExpandedCategories();
 	QTreeWidgetItem *findLocation(const ElementsLocation &) const;
 	QTreeWidgetItem *findLocation(const QString &) const;
 	void deleteItem(QTreeWidgetItem *);
 	void updateProjectItemInformations(QETProject *);
-	void updateProjectTemplates(QETProject *);
 	void updateDiagramLabel(QTreeWidgetItem *, int);
 	QString diagramTitleToDisplay(Diagram *) const;
+	QString titleBlockTemplateNameToDisplay(const QString &) const;
 	void ensureHierarchyIsVisible(QList<QTreeWidgetItem *>);
 	
 	// attributs
@@ -138,12 +141,15 @@
 	QStringList expanded_directories;
 	QString last_selected_item;
 	QHash<QTreeWidgetItem *, ElementsLocation> locations_;
+	QHash<QTreeWidgetItem *, TitleBlockTemplateLocation> title_blocks_;
 	QSet<QETProject *> projects_to_display_;
 	QHash<QTreeWidgetItem *, QETProject *> projects_;
 	QHash<QTreeWidgetItem *, Diagram *> diagrams_;
-	QHash<QTreeWidgetItem *, QETProject *> title_blocks_directories_;
+	QHash<QTreeWidgetItem *, TitleBlockTemplatesCollection *> title_blocks_collections_;
 	QTreeWidgetItem *common_collection_item_;
+	QTreeWidgetItem *common_tbt_collection_item_;
 	QTreeWidgetItem *custom_collection_item_;
+	QTreeWidgetItem *custom_tbt_collection_item_;
 	int loading_progress_;
 	bool first_activation_;
 	bool first_reload_;

Modified: branches/0.3/sources/elementspanelwidget.cpp
===================================================================
--- branches/0.3/sources/elementspanelwidget.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/elementspanelwidget.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -131,9 +131,9 @@
 	);
 	connect(
 		elements_panel,
-		SIGNAL(requestForTitleBlockTemplate(QETProject *, const QString &)),
+		SIGNAL(requestForTitleBlockTemplate(const TitleBlockTemplateLocation &)),
 		QETApp::instance(),
-		SLOT(openTitleBlockTemplate(QETProject *, const QString &))
+		SLOT(openTitleBlockTemplate(const TitleBlockTemplateLocation &))
 	);
 	connect(elements_panel, SIGNAL(loadingProgressed(int, int)),  this, SLOT(updateProgressBar(int, int)));
 	connect(elements_panel, SIGNAL(readingAboutToBegin()),        this, SLOT(collectionsRead()));
@@ -263,16 +263,10 @@
 	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 (elements_panel -> itemIsATitleBlockTemplatesCollection(current_item)) {
+		TitleBlockTemplateLocation location = elements_panel -> locationForTitleBlockTemplate(current_item);
+		QETApp::instance() -> openTitleBlockTemplate(location);
 	}
-	
-	if (parent_project) {
-		QETApp::instance() -> openTitleBlockTemplate(parent_project);
-	}
 }
 
 /**
@@ -281,9 +275,7 @@
 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);
+		QETApp::instance() -> openTitleBlockTemplate(elements_panel -> locationForTitleBlockTemplate(current_item));
 	}
 }
 
@@ -293,11 +285,10 @@
 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);
-		TitleBlockTemplateLocation template_location(parent_project, template_name);
-		TitleBlockTemplateDeleter template_deleter(template_location, this);
-		template_deleter.exec();
+		TitleBlockTemplateDeleter(
+			elements_panel -> locationForTitleBlockTemplate(current_item),
+			this
+		).exec();
 	}
 }
 
@@ -380,15 +371,20 @@
 		prj_move_diagram_up   -> setEnabled(is_writable && diagram_position > 0);
 		prj_move_diagram_down -> setEnabled(is_writable && diagram_position < project_diagrams_count - 1);
 		setElementsActionEnabled(false);
-	} else if (elements_panel -> selectedItemIsATitleBlockTemplatesDirectory()) {
-		bool is_writable = !(elements_panel -> projectForTitleBlockTemplatesDirectory(elements_panel -> currentItem()) -> isReadOnly());
-		tbt_add -> setEnabled(is_writable);
+	} else if (
+		elements_panel -> selectedItemIsATitleBlockTemplatesDirectory() ||
+		elements_panel -> selectedItemIsATitleBlockTemplate()
+	) {
+		QTreeWidgetItem *item = elements_panel -> currentItem();
+		TitleBlockTemplateLocation location = elements_panel -> locationForTitleBlockTemplate(item);
+		bool is_writable;
+		if (location.isValid()) {
+			is_writable = !location.parentCollection() -> isReadOnly();
+			tbt_add    -> setEnabled(is_writable);
+			tbt_edit   -> setEnabled(is_writable);
+			tbt_remove -> setEnabled(is_writable);
+		}
 		setElementsActionEnabled(false);
-	} else if (elements_panel -> selectedItemIsATitleBlockTemplate()) {
-		bool is_writable = !(elements_panel -> projectForTitleBlockTemplate(elements_panel -> currentItem()) -> isReadOnly());
-		tbt_edit -> setEnabled(is_writable);
-		tbt_remove -> setEnabled(is_writable);
-		setElementsActionEnabled(false);
 	}
 }
 
@@ -474,7 +470,7 @@
 			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)) {
+		} else if (elements_panel -> itemIsATitleBlockTemplatesCollection(item)) {
 			context_menu -> addAction(tbt_add);
 		} else if (elements_panel -> itemIsATitleBlockTemplate(item)) {
 			context_menu -> addAction(tbt_edit);

Modified: branches/0.3/sources/qetapp.cpp
===================================================================
--- branches/0.3/sources/qetapp.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetapp.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -29,6 +29,7 @@
 #include "qtextorientationspinboxwidget.h"
 #include "recentfiles.h"
 #include "qeticons.h"
+#include "templatescollection.h"
 #include <cstdlib>
 #include <iostream>
 #define QUOTE(x) STRINGIFY(x)
@@ -37,12 +38,17 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 QString QETApp::common_elements_dir = QString();
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+QString QETApp::common_tbt_dir_ = QString();
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 QString QETApp::config_dir = QString();
 #endif
 QString QETApp::lang_dir = QString();
 FileElementsCollection *QETApp::common_collection = 0;
 FileElementsCollection *QETApp::custom_collection = 0;
+TitleBlockTemplatesFilesCollection *QETApp::common_tbt_collection_;
+TitleBlockTemplatesFilesCollection *QETApp::custom_tbt_collection_;
 ElementsCollectionCache *QETApp::collections_cache_ = 0;
 QMap<uint, QETProject *> QETApp::registered_projects_ = QMap<uint, QETProject *>();
 uint QETApp::next_project_id = 0;
@@ -131,6 +137,8 @@
 	delete qsti;
 	delete custom_collection;
 	delete common_collection;
+	if (custom_tbt_collection_) delete custom_tbt_collection_;
+	if (common_tbt_collection_) delete common_tbt_collection_;
 }
 
 /**
@@ -289,6 +297,49 @@
 }
 
 /**
+	@return the common title block templates collection, i.e. the one provided
+	by QElecrotTech
+*/
+TitleBlockTemplatesFilesCollection *QETApp::commonTitleBlockTemplatesCollection() {
+	if (!common_tbt_collection_) {
+		common_tbt_collection_ = new TitleBlockTemplatesFilesCollection(QETApp::commonTitleBlockTemplatesDir());
+		common_tbt_collection_ -> setTitle(tr("Cartouches QET", "title of the title block templates collection provided by QElectroTech"));
+		common_tbt_collection_ -> setProtocol("commontbt");
+	}
+	return(common_tbt_collection_);
+}
+
+/**
+	@return the custom title block templates collection, i.e. the one managed
+	by the end user
+*/
+TitleBlockTemplatesFilesCollection *QETApp::customTitleBlockTemplatesCollection() {
+	if (!custom_tbt_collection_) {
+		custom_tbt_collection_ = new TitleBlockTemplatesFilesCollection(QETApp::customTitleBlockTemplatesDir());
+		custom_tbt_collection_ -> setTitle(tr("Cartouches utilisateur", "title of the user's title block templates collection"));
+		custom_tbt_collection_ -> setProtocol("customtbt");
+	}
+	return(custom_tbt_collection_);
+}
+
+/**
+	@return the list of all available title block tempaltes collections,
+	beginning with the common and custom ones, plus the projects-embedded ones.
+*/
+QList<TitleBlockTemplatesCollection *> QETApp::availableTitleBlockTemplatesCollections() {
+	QList<TitleBlockTemplatesCollection *> collections_list;
+	
+	collections_list << common_tbt_collection_;
+	collections_list << custom_tbt_collection_;
+	
+	foreach(QETProject *opened_project, registered_projects_) {
+		collections_list << opened_project -> embeddedTitleBlockTemplatesCollection();
+	}
+	
+	return(collections_list);
+}
+
+/**
 	@return le nom de l'utilisateur courant
 */
 QString QETApp::userName() {
@@ -333,6 +384,36 @@
 }
 
 /**
+	@return the path of the directory containing the common title block
+	templates collection.
+*/
+QString QETApp::commonTitleBlockTemplatesDir() {
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	if (common_tbt_dir_ != QString()) return(common_tbt_dir_);
+#endif
+#ifndef QET_COMMON_TBT_PATH
+	// without any compile-time option, use the "titleblocks" directory next to the executable binary
+	return(QCoreApplication::applicationDirPath() + "/titleblocks/");
+#else
+	#ifndef QET_COMMON_COLLECTION_PATH_RELATIVE_TO_BINARY_PATH
+		// the compile-time option represents a usual path (be it absolute or relative)
+		return(QUOTE(QET_COMMON_TBT_PATH));
+	#else
+		// the compile-time option represents a path relative to the directory that contains the executable binary
+		return(QCoreApplication::applicationDirPath() + "/" + QUOTE(QET_COMMON_TBT_PATH));
+	#endif
+#endif
+}
+
+/**
+	@return the path of the directory containing the custom title block
+	templates collection.
+*/
+QString QETApp::customTitleBlockTemplatesDir() {
+	return(configDir() + "titleblocks/");
+}
+
+/**
 	Renvoie le dossier de configuration de QET, c-a-d le chemin du dossier dans
 	lequel QET lira les informations de configuration et de personnalisation
 	propres a l'utilisateur courant. Ce dossier est generalement
@@ -371,6 +452,10 @@
 		directory = commonElementsDir();
 	} else if (sym_path.startsWith("custom://")) {
 		directory = customElementsDir();
+	} else if (sym_path.startsWith("commontbt://")) {
+		directory = commonTitleBlockTemplatesDir();
+	} else if (sym_path.startsWith("customtbt://")) {
+		directory = customTitleBlockTemplatesDir();
 	} else return(QString());
 	return(directory + QDir::toNativeSeparators(sym_path.right(sym_path.length() - 9)));
 }
@@ -429,6 +514,20 @@
 }
 #endif
 
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+/**
+	Define the path of the directory containing the common title block
+	tempaltes collection.
+*/
+void QETApp::overrideCommonTitleBlockTemplatesDir(const QString &new_ctbtd) {
+	QFileInfo new_ctbtd_info(new_ctbtd);
+	if (new_ctbtd_info.isDir()) {
+		common_tbt_dir_ = new_ctbtd_info.absoluteFilePath();
+		if (!common_tbt_dir_.endsWith("/")) common_tbt_dir_ += "/";
+	}
+}
+#endif
+
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 /**
 	Redefinit le chemin du dossier de configuration
@@ -556,10 +655,7 @@
 	
 	// foreach known template editor
 	foreach (QETTitleBlockTemplateEditor *tbt_editor, titleBlockTemplateEditors()) {
-		// retrieve the location of the currently edited template
-		TitleBlockTemplateLocation tbt_editor_loc(tbt_editor -> location());
-		
-		if (tbt_editor_loc.project() == project) {
+		if (tbt_editor -> location().parentProject() == project) {
 			editors << tbt_editor;
 		}
 	}
@@ -903,9 +999,9 @@
 	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) {
+void QETApp::openTitleBlockTemplate(const TitleBlockTemplateLocation &location) {
 	QETTitleBlockTemplateEditor *qet_template_editor = new QETTitleBlockTemplateEditor();
-	qet_template_editor -> edit(project, template_name);
+	qet_template_editor -> edit(location);
 	qet_template_editor -> showMaximized();
 }
 
@@ -1004,6 +1100,11 @@
 		overrideCommonElementsDir(qet_arguments_.commonElementsDir());
 	}
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	if (qet_arguments_.commonTitleBlockTemplatesDirSpecified()) {
+		overrideCommonTitleBlockTemplatesDir(qet_arguments_.commonTitleBlockTemplatesDir());
+	}
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	if (qet_arguments_.configDirSpecified()) {
 		overrideConfigDir(qet_arguments_.configDir());
@@ -1081,6 +1182,7 @@
 	Cette methode creera, si necessaire :
 	  * le dossier de configuration
 	  * le dossier de la collection perso
+	  * the directory for custom title blocks
 */
 void QETApp::initConfiguration() {
 	// cree les dossiers de configuration si necessaire
@@ -1090,6 +1192,9 @@
 	QDir custom_elements_dir(QETApp::customElementsDir());
 	if (!custom_elements_dir.exists()) custom_elements_dir.mkpath(QETApp::customElementsDir());
 	
+	QDir custom_tbt_dir(QETApp::customTitleBlockTemplatesDir());
+	if (!custom_tbt_dir.exists()) custom_tbt_dir.mkpath(QETApp::customTitleBlockTemplatesDir());
+	
 	// lit le fichier de configuration
 	qet_settings = new QSettings(configDir() + "qelectrotech.conf", QSettings::IniFormat, this);
 	
@@ -1271,6 +1376,9 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 		+ tr("  --common-elements-dir=DIR     Definir le dossier de la collection d'elements\n")
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+		+ tr("  --common-tbt-dir=DIR          Definir le dossier de la collection de modeles de cartouches\n")
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 		+ tr("  --config-dir=DIR              Definir le dossier de configuration\n")
 #endif

Modified: branches/0.3/sources/qetapp.h
===================================================================
--- branches/0.3/sources/qetapp.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetapp.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -21,6 +21,7 @@
 #include <QTranslator>
 #include <QtGui>
 #include "elementslocation.h"
+#include "templatelocation.h"
 #include "qetarguments.h"
 class AboutQET;
 class QETDiagramEditor;
@@ -32,6 +33,8 @@
 class ElementsCategory;
 class ElementDefinition;
 class TitleBlockTemplate;
+class TitleBlockTemplatesCollection;
+class TitleBlockTemplatesFilesCollection;
 class QETProject;
 class QETTitleBlockTemplateEditor;
 class QTextOrientationSpinBoxWidget;
@@ -65,9 +68,15 @@
 	static ElementsCollection *customElementsCollection();
 	static QList<ElementsCollection *> availableCollections();
 	
+	static TitleBlockTemplatesFilesCollection *commonTitleBlockTemplatesCollection();
+	static TitleBlockTemplatesFilesCollection *customTitleBlockTemplatesCollection();
+	static QList<TitleBlockTemplatesCollection *> availableTitleBlockTemplatesCollections();
+	
 	static QString userName();
 	static QString commonElementsDir();
 	static QString customElementsDir();
+	static QString commonTitleBlockTemplatesDir();
+	static QString customTitleBlockTemplatesDir();
 	static bool registerProject(QETProject *);
 	static bool unregisterProject(QETProject *);
 	static QMap<uint, QETProject *> registeredProjects();
@@ -86,6 +95,12 @@
 	private:
 	static QString common_elements_dir; ///< Dossier contenant la collection d'elements commune
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	public:
+	static void overrideCommonTitleBlockTemplatesDir(const QString &);
+	private:
+	static QString common_tbt_dir_; ///< Directory containing the common title block templates collection
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	public:
 	static void overrideConfigDir(const QString &);
@@ -145,6 +160,8 @@
 	
 	static FileElementsCollection *common_collection;
 	static FileElementsCollection *custom_collection;
+	static TitleBlockTemplatesFilesCollection *common_tbt_collection_;
+	static TitleBlockTemplatesFilesCollection *custom_tbt_collection_;
 	static ElementsCollectionCache *collections_cache_;
 	static QMap<uint, QETProject *> registered_projects_;
 	static uint next_project_id;
@@ -176,7 +193,7 @@
 	void openProjectFiles(const QStringList &);
 	void openElementFiles(const QStringList &);
 	void openElementLocations(const QList<ElementsLocation> &);
-	void openTitleBlockTemplate(QETProject *, const QString & = QString());
+	void openTitleBlockTemplate(const TitleBlockTemplateLocation &);
 	void configureQET();
 	void aboutQET();
 	

Modified: branches/0.3/sources/qetarguments.cpp
===================================================================
--- branches/0.3/sources/qetarguments.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetarguments.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -56,6 +56,9 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 	common_elements_dir_(qet_arguments.common_elements_dir_),
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+common_tbt_dir_(qet_arguments.common_tbt_dir_),
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	config_dir_(qet_arguments.config_dir_),
 #endif
@@ -78,6 +81,9 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 	common_elements_dir_ = qet_arguments.common_elements_dir_;
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	common_tbt_dir_ = qet_arguments.common_tbt_dir_;
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	config_dir_ = qet_arguments.config_dir_;
 #endif
@@ -159,6 +165,9 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 	common_elements_dir_.clear();
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	common_tbt_dir_.clear();
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	config_dir_.clear();
 #endif
@@ -205,6 +214,7 @@
 	Gere les arguments correspondant potentiellement a une option.
 	Les options reconnues sont : 
 	  * --common-elements-dir=
+	  * --common-tbt-dir
 	  * --config-dir=
 	  * --lang-dir=
 	  * --help
@@ -235,6 +245,13 @@
 	}
 	
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	QString ctbtd_arg("--common-tbt-dir=");
+	if (option.startsWith(ctbtd_arg)) {
+		common_tbt_dir_ = option.mid(ctbtd_arg.length());
+		return;
+	}
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	QString cd_arg("--config-dir=");
 	if (option.startsWith(cd_arg)) {
@@ -270,8 +287,26 @@
 QString QETArguments::commonElementsDir() const {
 	return(common_elements_dir_);
 }
+#endif
 
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+/**
+	@return true if the user has specified a directory for the common title
+	block templates collection
+*/
+bool QETArguments::commonTitleBlockTemplatesDirSpecified() const {
+	return(!common_tbt_dir_.isEmpty());
+}
+
+/**
+	@return the directory of the common title block templates collection
+	specified by the user. If none were specified, return an empty string.
+*/
+QString QETArguments::commonTitleBlockTemplatesDir() const {
+	return(common_tbt_dir_);
+}
 #endif
+
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 /**
 	@return true si l'utilisateur a specifie un dossier pour la configuration.

Modified: branches/0.3/sources/qetarguments.h
===================================================================
--- branches/0.3/sources/qetarguments.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetarguments.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -46,6 +46,10 @@
 	virtual bool commonElementsDirSpecified() const;
 	virtual QString commonElementsDir() const;
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	virtual bool commonTitleBlockTemplatesDirSpecified() const;
+	virtual QString commonTitleBlockTemplatesDir() const;
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	virtual bool configDirSpecified() const;
 	virtual QString configDir() const;
@@ -73,6 +77,9 @@
 #ifdef QET_ALLOW_OVERRIDE_CED_OPTION
 	QString common_elements_dir_;
 #endif
+#ifdef QET_ALLOW_OVERRIDE_CTBTD_OPTION
+	QString common_tbt_dir_;
+#endif
 #ifdef QET_ALLOW_OVERRIDE_CD_OPTION
 	QString config_dir_;
 #endif

Modified: branches/0.3/sources/qetproject.cpp
===================================================================
--- branches/0.3/sources/qetproject.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetproject.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -39,7 +39,8 @@
 	QObject(parent),
 	collection_(0),
 	project_qet_version_(-1),
-	read_only_(false)
+	read_only_(false),
+	titleblocks_(this)
 {
 	// 0 a n schema(s) vide(s)
 	int diagrams_count = qMax(0, diagrams);
@@ -55,6 +56,7 @@
 	
 	// une categorie dediee aux elements integres automatiquement
 	ensureIntegrationCategoryExists();
+	setupTitleBlockTemplatesCollection();
 }
 
 /**
@@ -66,7 +68,8 @@
 	QObject(parent),
 	collection_(0),
 	project_qet_version_(-1),
-	read_only_(false)
+	read_only_(false),
+	titleblocks_(this)
 {
 	// ouvre le fichier
 	QFile project_file(path);
@@ -86,6 +89,8 @@
 	// et construit le projet
 	readProjectXml();
 	
+	setupTitleBlockTemplatesCollection();
+	
 	// passe le projet en lecture seule si le fichier l'est
 	QFileInfo project_file_info(path);
 	if (!project_file_info.isWritable()) {
@@ -101,13 +106,16 @@
 	QObject(parent),
 	collection_(0),
 	project_qet_version_(-1),
-	read_only_(false)
+	read_only_(false),
+	titleblocks_(this)
 {
 	// copie le contenu XML
 	document_root_.appendChild(document_root_.importNode(xml_element, true));
 	
 	// et construit le projet
 	readProjectXml();
+	
+	setupTitleBlockTemplatesCollection();
 }
 
 /**
@@ -167,6 +175,13 @@
 }
 
 /**
+	@return the title block templates collection enbeedded within this project
+*/
+TitleBlockTemplatesProjectCollection *QETProject::embeddedTitleBlockTemplatesCollection() {
+	return(&titleblocks_);
+}
+
+/**
 	@return le chemin du fichier dans lequel ce projet est enregistre
 */
 QString QETProject::filePath() {
@@ -286,8 +301,8 @@
 /**
 	@return the list of the titleblock templates embedded within this project 
 */
-QList<QString> QETProject::embeddedTitleBlockTemplates() const {
-	return(titleblock_templates_xml_.keys());
+QList<QString> QETProject::embeddedTitleBlockTemplates() {
+	return(titleblocks_.templates());
 }
 
 /**
@@ -296,24 +311,7 @@
 	name within the project
 */
 const TitleBlockTemplate *QETProject::getTemplateByName(const QString &template_name) {
-	// Do we have already loaded this template?
-	if (titleblock_templates_.contains(template_name)) {
-		return(titleblock_templates_[template_name]);
-	}
-	
-	// No? Do we even know of it?
-	if (!titleblock_templates_xml_.contains(template_name)) {
-		return(0);
-	}
-	
-	// Ok, we have its XML description, we have to generate an TitleBlockTemplate object
-	TitleBlockTemplate *titleblock_template = new TitleBlockTemplate(this);
-	if (titleblock_template -> loadFromXmlElement(titleblock_templates_xml_[template_name])) {
-		titleblock_templates_.insert(template_name, titleblock_template);
-		return(titleblock_template);
-	} else {
-		return(0);
-	}
+	return(titleblocks_.getTemplate(template_name));
 }
 
 /**
@@ -322,16 +320,12 @@
 	if the project does not have such an titleblock template
 */
 QDomElement QETProject::getTemplateXmlDescriptionByName(const QString &template_name) {
-	if (titleblock_templates_xml_.contains(template_name)) {
-		return(titleblock_templates_xml_[template_name]);
-	}
-	return(QDomElement());
+	return(titleblocks_.getTemplateXmlDescription(template_name));
 }
 
 /**
 	This methods allows adding or modifying a template embedded within the
-	project. This method emits the signal projectTemplatesChanged() if
-	necessary.
+	project.
 	@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.
@@ -340,53 +334,15 @@
 	@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_.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);
+	return(titleblocks_.setTemplateXmlDescription(template_name, xml_elmt));
 }
 
 /**
-	This methods allows removing a template embedded within the project. This
-	method emits the signal projectTemplatesChanged() if necessary.
+	This methods allows removing a template embedded within the project.
 	@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(titleblocks_.removeTemplate(template_name));
 }
 
 /**
@@ -451,11 +407,11 @@
 	xml_doc.appendChild(project_root);
 	
 	// titleblock templates, if any
-	if (titleblock_templates_xml_.count()) {
-		qDebug() << qPrintable(QString("QETProject::toXml() : exporting %1 titleblock templates").arg(titleblock_templates_xml_.count()));
+	if (titleblocks_.templates().count()) {
 		QDomElement titleblocktemplates_elmt = xml_doc.createElement("titleblocktemplates");
-		foreach (QDomElement e, titleblock_templates_xml_) {
-			titleblocktemplates_elmt.appendChild(e);
+		foreach (QString template_name, titleblocks_.templates()) {
+			QDomElement e = titleblocks_.getTemplateXmlDescription(template_name);
+			titleblocktemplates_elmt.appendChild(xml_doc.importNode(e, true));
 		}
 		project_root.appendChild(titleblocktemplates_elmt);
 	}
@@ -819,6 +775,25 @@
 }
 
 /**
+	Set up signals/slots connections related to the title block templates
+	collection.
+*/
+void QETProject::setupTitleBlockTemplatesCollection() {
+	connect(
+		&titleblocks_,
+		SIGNAL(changed(TitleBlockTemplatesCollection *, const QString &)),
+		this,
+		SLOT(updateDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *, const QString &))
+	);
+	connect(
+		&titleblocks_,
+		SIGNAL(aboutToRemove(TitleBlockTemplatesCollection *, const QString &)),
+		this,
+		SLOT(removeDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *, const QString &))
+	);
+}
+
+/**
 	@return un pointeur vers la categorie racine de la collection embarquee, ou
 	0 si celle-ci n'est pas accessible.
 */
@@ -923,18 +898,7 @@
 	Loads the embedded template from the XML description of the project
 */
 void QETProject::readEmbeddedTemplatesXml() {
-	foreach (QDomElement e, QET::findInDomElement(document_root_.documentElement(), "titleblocktemplates", "titleblocktemplate")) {
-		// each titleblock template must have a name
-		if (!e.hasAttribute("name")) continue;
-		QString titleblock_template_name = e.attribute("name");
-		
-		// if several templates have the same name, we keep the first one encountered
-		if (titleblock_templates_xml_.contains(titleblock_template_name)) continue;
-		
-		// we simply store the XML element describing the titleblock template,
-		// without any further analysis for the moment
-		titleblock_templates_xml_.insert(titleblock_template_name, e);
-	}
+	titleblocks_.fromXml(document_root_.documentElement());
 }
 
 /**
@@ -1149,6 +1113,33 @@
 }
 
 /**
+	Inform each diagram that the \a template_name title block changed.
+	@param collection Title block templates collection
+	@param template_name Name of the changed template
+*/
+void QETProject::updateDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *collection, const QString &template_name) {
+	Q_UNUSED(collection)
+	
+	foreach (Diagram *diagram, diagrams_) {
+		diagram -> titleBlockTemplateChanged(template_name);
+	}
+}
+
+/**
+	Inform each diagram that the \a template_name title block is about to be removed.
+	@param collection Title block templates collection
+	@param template_name Name of the removed template
+*/
+void QETProject::removeDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *collection, const QString &template_name) {
+	Q_UNUSED(collection)
+	
+	// warn diagrams that the given template is about to be removed
+	foreach (Diagram *diagram, diagrams_) {
+		diagram -> titleBlockTemplateRemoved(template_name);
+	}
+}
+
+/**
 	Copie l'element integ_elmt dans la categorie target_cat en utilisant le
 	gestionnaire handler ; en cas d'erreur, error_message est rempli.
 	@return l'emplacement de l'element cree

Modified: branches/0.3/sources/qetproject.h
===================================================================
--- branches/0.3/sources/qetproject.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/qetproject.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -24,6 +24,7 @@
 #include "borderproperties.h"
 #include "conductorproperties.h"
 #include "titleblockproperties.h"
+#include "templatescollection.h"
 class Diagram;
 class ElementsCollection;
 class ElementsCategory;
@@ -75,6 +76,7 @@
 	QList<Diagram *> diagrams() const;
 	int folioIndex(const Diagram *) const;
 	ElementsCollection *embeddedCollection() const;
+	TitleBlockTemplatesProjectCollection *embeddedTitleBlockTemplatesCollection();
 	QString filePath();
 	void setFilePath(const QString &);
 	QString currentDir() const;
@@ -82,7 +84,7 @@
 	QString title() const;
 	qreal declaredQElectroTechVersion();
 	void setTitle(const QString &);
-	QList<QString> embeddedTitleBlockTemplates() const;
+	QList<QString> embeddedTitleBlockTemplates();
 	const TitleBlockTemplate *getTemplateByName(const QString &template_name);
 	QDomElement getTemplateXmlDescriptionByName(const QString &);
 	bool setTemplateXmlDescription(const QString &, const QDomElement &);
@@ -123,12 +125,14 @@
 	void diagramAdded(QETProject *, Diagram *);
 	void diagramRemoved(QETProject *, Diagram *);
 	void readOnlyChanged(QETProject *, bool);
-	void projectTemplatesChanged(QETProject *);
 	
 	private slots:
 	void updateDiagramsFolioData();
+	void updateDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *, const QString &);
+	void removeDiagramsTitleBlockTemplate(TitleBlockTemplatesCollection *, const QString &);
 	
 	private:
+	void setupTitleBlockTemplatesCollection();
 	ElementsCategory *rootCategory() const;
 	void readProjectXml();
 	void readDiagramsXml();
@@ -168,9 +172,7 @@
 	ConductorProperties default_conductor_properties_;
 	/// Proprietes par defaut du cartouche pour les nouveaux schemas dans ce projet
 	TitleBlockProperties default_titleblock_properties_;
-	/// XML descriptions of embedded titleblock templates
-	QHash<QString, QDomElement> titleblock_templates_xml_;
-	/// Already parsed embedded titleblock templates
-	QHash<QString, TitleBlockTemplate *> titleblock_templates_;
+	/// Embedded title block templates collection
+	TitleBlockTemplatesProjectCollection titleblocks_;
 };
 #endif

Modified: branches/0.3/sources/titleblock/qettemplateeditor.cpp
===================================================================
--- branches/0.3/sources/titleblock/qettemplateeditor.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/qettemplateeditor.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -32,7 +32,6 @@
 QETTitleBlockTemplateEditor::QETTitleBlockTemplateEditor(QWidget *parent) :
 	QMainWindow(parent),
 	read_only(false),
-	parent_project_(0),
 	tb_template_(0),
 	logo_manager_(0)
 {
@@ -54,10 +53,33 @@
 	@return the location of the currently edited template
 */
 TitleBlockTemplateLocation QETTitleBlockTemplateEditor::location() const {
-	return(TitleBlockTemplateLocation(parent_project_, template_name_));
+	return(location_);
 }
 
 /**
+	@param location Location of the tile block template to be edited.
+*/
+bool QETTitleBlockTemplateEditor::edit(const TitleBlockTemplateLocation &location) {
+	// the template name may be empty to create a new one
+	const TitleBlockTemplate *tb_template_orig;
+	if (location.name().isEmpty()) {
+		// loads the default title block template provided by the application
+		// it will be used as a start point to design the title block
+		tb_template_orig = QETApp::defaultTitleBlockTemplate();
+	} else {
+		tb_template_orig = location.getTemplate();
+	}
+	if (!tb_template_orig) {
+		/// TODO The TBT does not exist, manage error
+		return(false);
+	}
+	
+	location_ = location;
+	editCopyOf(tb_template_orig);
+	return(true);
+}
+
+/**
 	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.
@@ -82,9 +104,42 @@
 		return(false);
 	}
 	
-	tb_template_ = tb_template_orig -> clone();
-	parent_project_ = project;
-	template_name_ = template_name;
+	location_.setParentCollection(project -> embeddedTitleBlockTemplatesCollection());
+	location_.setName(template_name);
+	return(editCopyOf(tb_template_orig));
+}
+
+/**
+	@param file_path Path of the template file to edit.
+	@return false if a problem occured while opening the template, true otherwise.
+*/
+bool QETTitleBlockTemplateEditor::edit(const QString &file_path) {
+	// get title block template object from the file, edit it
+	TitleBlockTemplate *tbt = new TitleBlockTemplate();
+	bool loading = tbt -> loadFromXmlFile(file_path);
+	if (!loading) {
+		/// TODO the file opening failed, warn the user?
+		return(false);
+	}
+	return(edit(tbt));
+}
+
+/**
+	@param tbt Title block template to be edited
+	@return false if a problem occured while opening the template, true otherwise.
+*/
+bool QETTitleBlockTemplateEditor::editCopyOf(const TitleBlockTemplate *tbt) {
+	if (!tbt) return(false);
+	return(edit(tbt -> clone()));
+}
+
+/**
+	@param tbt Title block template to be directly edited
+	@return false if a problem occured while opening the template, true otherwise.
+*/
+bool QETTitleBlockTemplateEditor::edit(TitleBlockTemplate *tbt) {
+	if (!tbt) return(false);
+	tb_template_ = tbt;
 	template_edition_area_view_ -> setTitleBlockTemplate(tb_template_);
 	template_cell_editor_widget_ -> updateLogosComboBox(tb_template_);
 	updateEditorTitle();
@@ -242,6 +297,9 @@
 	);
 }
 
+/**
+	Initialize the logo manager
+*/
 void QETTitleBlockTemplateEditor::initLogoManager() {
 	logo_manager_ = new TitleBlockTemplateLogoManager(tb_template_);
 	connect(
@@ -302,7 +360,7 @@
 	);
 	
 	QString title;
-	if (template_name_.isEmpty()) {
+	if (location_.name().isEmpty()) {
 		title = min_title;
 	} else {
 		title = QString(
@@ -310,38 +368,37 @@
 				"%1 - %2",
 				"window title: %1 is the base window title, %2 is a template name"
 			)
-		).arg(min_title).arg(template_name_);
+		).arg(min_title).arg(location_.name());
 	}
 	setWindowTitle(title);
 }
 
 /**
-	Save the template as \a name within \a project.
+	Save the template under the provided location.
 	@see QETProject::setTemplateXmlDescription()
-	@param project Parent project
-	@param name Template name
+	@param location Location where the title block template should be saved.
 */
-void QETTitleBlockTemplateEditor::saveAs(QETProject *project, const QString &name) {
-	if (!project || name.isEmpty()) return;
+void QETTitleBlockTemplateEditor::saveAs(const TitleBlockTemplateLocation &location) {
+	TitleBlockTemplatesCollection *collection = location.parentCollection();
+	if (!collection) return;
 	
 	QDomDocument doc;
 	QDomElement elmt = doc.createElement("root");
 	tb_template_ -> saveToXmlElement(elmt);
-	elmt.setAttribute("name", name);
+	elmt.setAttribute("name", location.name());
 	doc.appendChild(elmt);
 	
-	project -> setTemplateXmlDescription(name, elmt);
+	collection -> setTemplateXmlDescription(location.name(), elmt);
 	
-	parent_project_ = project;
-	template_name_ = name;
+	location_ = location;
 }
 
 /**
 	Save the currently edited title block template back to its parent project.
 */
 void QETTitleBlockTemplateEditor::save() {
-	if (parent_project_ && !template_name_.isEmpty()) {
-		saveAs(parent_project_, template_name_);
+	if (location_.isValid()) {
+		saveAs(location_);
 	} else {
 		saveAs();
 	}
@@ -353,13 +410,14 @@
 void QETTitleBlockTemplateEditor::saveAs() {
 	TitleBlockTemplateLocation location = getTitleBlockTemplateLocationFromUser();
 	if (location.isValid()) {
-		saveAs(location.project(), location.name());
+		saveAs(location);
 	}
 }
 
 /**
-	Ask the user for a title block template location
-	@return The location chosen by the user, or an empty TitleBlockTemplateLocation if the user cancelled the dialog
+	Ask the user for a title block template location @return The location chosen
+	by the user, or an empty TitleBlockTemplateLocation if the user cancelled the
+	dialog
 */
 TitleBlockTemplateLocation QETTitleBlockTemplateEditor::getTitleBlockTemplateLocationFromUser() {
 	TitleBlockTemplateLocationChooser *chooser = new TitleBlockTemplateLocationChooser(location());

Modified: branches/0.3/sources/titleblock/qettemplateeditor.h
===================================================================
--- branches/0.3/sources/titleblock/qettemplateeditor.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/qettemplateeditor.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -51,10 +51,8 @@
 	/// actions
 	QAction *save_, *save_as_, *quit_, *configure_, *about_qt_, *about_qet_, *merge_cells_, *split_cell_;
 	QAction *zoom_in_, *zoom_out_, *zoom_fit_, *zoom_reset_;
-	/// Parent project of the currently edited template
-	QETProject *parent_project_;
-	/// Name of the currently edited template
-	QString template_name_;
+	/// Location of the currently edited template
+	TitleBlockTemplateLocation location_;
 	/// Template Object edited
 	TitleBlockTemplate *tb_template_;
 	/// Template preview
@@ -84,7 +82,11 @@
 	
 	public slots:
 	void selectedCellsChanged(QList<TitleBlockCell *>);
+	bool edit(const TitleBlockTemplateLocation &);
 	bool edit(QETProject *, const QString &);
+	bool edit(const QString &);
+	bool editCopyOf(const TitleBlockTemplate *);
+	bool edit(TitleBlockTemplate *);
 	void editLogos();
 	void save();
 	void saveAs();
@@ -96,7 +98,7 @@
 	void pushGridUndoCommand(TitleBlockTemplateCommand *);
 	void pushUndoCommand(QUndoCommand *);
 	void updateEditorTitle();
-	void saveAs(QETProject *, const QString &);
+	void saveAs(const TitleBlockTemplateLocation &);
 };
 
 #endif

Modified: branches/0.3/sources/titleblock/templatedeleter.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatedeleter.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/templatedeleter.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -43,10 +43,12 @@
 */
 bool TitleBlockTemplateDeleter::exec() {
 	if (!template_location_.isValid()) return(false);
-	QETProject *project = template_location_.project();
+	
 	QString name = template_location_.name();
+	TitleBlockTemplatesCollection *collection = template_location_.parentCollection();
+	if (!collection) return(false);
 	
-	if (!project -> embeddedTitleBlockTemplates().contains(name)) {
+	if (!collection -> templates().contains(name)) {
 		return(false);
 	}
 	
@@ -65,6 +67,6 @@
 	if (answer != QMessageBox::Yes) return(false);
 	
 	// delete the title block template
-	project -> removeTemplateByName(name);
+	collection -> removeTemplate(name);
 	return(true);
 }

Modified: branches/0.3/sources/titleblock/templatelocation.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatelocation.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/templatelocation.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -16,14 +16,16 @@
 	along with QElectroTech.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "templatelocation.h"
+#include "templatescollection.h"
+#include "qetapp.h"
 
 /**
 	Constructor
-	@param project Parent project of the title block template
+	@param collection Parent collection of the title block template
 	@param name Name of the title block template within its parent project or collection
 */
-TitleBlockTemplateLocation::TitleBlockTemplateLocation(QETProject *project, const QString &name) :
-	project_(project),
+TitleBlockTemplateLocation::TitleBlockTemplateLocation(const QString &name, TitleBlockTemplatesCollection *collection) :
+	collection_(collection),
 	name_(name)
 {
 }
@@ -35,18 +37,18 @@
 }
 
 /**
-	@return the parent project of the template, or 0 if none was defined
+	@return the parent collection of the template, or 0 if none was defined
 */
-QETProject *TitleBlockTemplateLocation::project() const {
-	return(project_);
+TitleBlockTemplatesCollection *TitleBlockTemplateLocation::parentCollection() const {
+	return(collection_);
 }
 
 /**
-	@param project The new parent project of the template, or 0 if none
+	@param project The new parent collection of the template, or 0 if none
 	applies.
 */
-void TitleBlockTemplateLocation::setProject(QETProject *project) {
-	project_ = project;
+void TitleBlockTemplateLocation::setParentCollection(TitleBlockTemplatesCollection *collection) {
+	collection_ = collection;
 }
 
 /**
@@ -67,5 +69,43 @@
 	@return true if this location is null, false otherwise
 */
 bool TitleBlockTemplateLocation::isValid() const {
-	return(project_ && !name_.isEmpty());
+	return(!name_.isEmpty());
 }
+
+/**
+	@return A string representation of the location
+*/
+QString TitleBlockTemplateLocation::toString() const {
+	return(protocol() + QString("://") + name_);
+}
+
+/**
+	This is a convenience method equivalent to
+	parentCollection() -> parentProject().
+*/
+QETProject *TitleBlockTemplateLocation::parentProject() const {
+	if (collection_) {
+		return(collection_ -> parentProject());
+	}
+	return(0);
+}
+
+/**
+	This is a convenience method equivalent to
+	parentCollection() -> protocol().
+*/
+QString TitleBlockTemplateLocation::protocol() const {
+	if (collection_) {
+		return(collection_ -> protocol());
+	}
+	return("unknown");
+}
+
+/**
+	This is a convenience method equivalent to
+	parentCollection() -> getTemplate(...).
+*/
+TitleBlockTemplate *TitleBlockTemplateLocation::getTemplate() const {
+	if (!collection_ || name_.isEmpty()) return(0);
+	return(collection_ -> getTemplate(name_));
+}

Modified: branches/0.3/sources/titleblock/templatelocation.h
===================================================================
--- branches/0.3/sources/titleblock/templatelocation.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/templatelocation.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -19,6 +19,8 @@
 #define TITLEBLOCK_SLASH_TEMPLATE_LOCATION_H
 #include <QtCore>
 class QETProject;
+class TitleBlockTemplate;
+class TitleBlockTemplatesCollection;
 
 /**
 	This class represents the location of a title block template.
@@ -26,20 +28,24 @@
 class TitleBlockTemplateLocation {
 	// constructor, destructor
 	public:
-	TitleBlockTemplateLocation(QETProject * = 0, const QString & = QString());
+	TitleBlockTemplateLocation(const QString & = QString(), TitleBlockTemplatesCollection * = 0);
 	virtual ~TitleBlockTemplateLocation();
 	
 	// methods
 	public:
-	QETProject *project() const;
-	void setProject(QETProject *);
+	TitleBlockTemplatesCollection *parentCollection() const;
+	void setParentCollection(TitleBlockTemplatesCollection *);
 	QString name() const;
 	void setName(const QString &);
 	bool isValid() const;
+	QString toString() const;
+	QETProject *parentProject() const;
+	QString protocol() const;
+	TitleBlockTemplate *getTemplate() const;
 	
 	// attributes
 	private:
-	QETProject *project_; ///< Parent project of the template, if any
-	QString name_;        ///< Name of the template
+	TitleBlockTemplatesCollection *collection_; ///< Collection the template belongs to
+	QString name_;                              ///< Name of the template
 };
 #endif

Modified: branches/0.3/sources/titleblock/templatelocationchooser.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatelocationchooser.cpp	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/templatelocationchooser.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -1,6 +1,7 @@
 #include "templatelocationchooser.h"
 #include "qetapp.h"
 #include "qetproject.h"
+#include "templatescollection.h"
 
 /**
 	Constructor
@@ -27,15 +28,14 @@
 	@return the current location
 */
 TitleBlockTemplateLocation TitleBlockTemplateLocationChooser::location() const {
-	return(TitleBlockTemplateLocation(project(), name()));
+	return(TitleBlockTemplateLocation(name(), collection()));
 }
 
 /**
-	@return the currently selected project
+	@return the currently selected collection
 */
-QETProject *TitleBlockTemplateLocationChooser::project() const {
-	uint project_id = projects_ -> itemData(projects_ -> currentIndex()).toUInt();
-	return(QETApp::project(project_id));
+TitleBlockTemplatesCollection *TitleBlockTemplateLocationChooser::collection() const {
+	return(collections_index_[collections_ -> currentIndex()]);
 }
 
 /**
@@ -51,16 +51,8 @@
 	@param location to be displayed by this widget
 */
 void TitleBlockTemplateLocationChooser::setLocation(const TitleBlockTemplateLocation &location) {
-	// we need a project id
-	int project_id = QETApp::projectId(location.project());
-	if (project_id == -1) return;
+	collections_ -> setCurrentIndex(collections_index_.keys(location.parentCollection()).first());
 	
-	// attempt to find this project id in our project combo box
-	int project_index = projects_ -> findData(QVariant(static_cast<uint>(project_id)));
-	if (project_index == -1) return;
-	
-	projects_ -> setCurrentIndex(project_index);
-	
 	if (!location.name().isEmpty()) {
 		int template_index = templates_ -> findText(location.name());
 		if (template_index != -1) {
@@ -76,43 +68,64 @@
 	@param location Initial location displayed by the widget
 */
 void TitleBlockTemplateLocationChooser::init() {
-	projects_ = new QComboBox();
+	collections_ = new QComboBox();
 	templates_ = new QComboBox();
 	new_name_ = new QLineEdit();
 	
-	QMap<uint, QETProject *> projects = QETApp::registeredProjects();
-	foreach (uint project_id, projects.keys()) {
-		projects_ -> addItem(projects[project_id] -> title(), project_id);
-	}
-	updateTemplates();
-	connect(projects_, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTemplates()));
+	updateCollections();
+	connect(collections_, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTemplates()));
+	connect(templates_,   SIGNAL(currentIndexChanged(int)), this, SLOT(updateNewName()));
 	
 	QFormLayout *form_layout = new QFormLayout();
-	form_layout -> addRow(tr("Projet parent",   "used in save as form"), projects_);
-	form_layout -> addRow(tr("Mod\xE8le existant", "used in save as form"), templates_);
-	form_layout -> addRow(tr("ou nouveau nom",  "used in save as form"), new_name_);
+	form_layout -> addRow(tr("Collection parente",   "used in save as form"), collections_);
+	form_layout -> addRow(tr("Mod\xE8le existant",      "used in save as form"), templates_);
+	form_layout -> addRow(tr("ou nouveau nom",       "used in save as form"), new_name_);
 	setLayout(form_layout);
 }
 
 /**
+	Update the collections list
+*/
+void TitleBlockTemplateLocationChooser::updateCollections() {
+	collections_ -> clear();
+	collections_index_.clear();
+	
+	int index = 0;
+	foreach(TitleBlockTemplatesCollection *collection, QETApp::availableTitleBlockTemplatesCollections()) {
+		collections_ -> addItem(collection -> title());
+		collections_index_.insert(index, collection);
+		++ index;
+	}
+	
+	updateTemplates();
+}
+
+/**
 	Update the templates list according to the selected project.
 */
 void TitleBlockTemplateLocationChooser::updateTemplates() {
-	int current_index = projects_ -> currentIndex();
-	if (current_index == -1) return;
+	TitleBlockTemplatesCollection *current_collection = collection();
+	if (!current_collection) return;
 	
-	uint project_id = projects_ -> itemData(current_index).toUInt();
-	QETProject *project = QETApp::project(project_id);
-	if (!project) return;
-	
 	templates_ -> clear();
 	templates_ -> addItem(tr("Nouveau mod\xE8le (entrez son nom)", "combox box entry"), QVariant(false));
 	
-	QStringList available_templates = project -> embeddedTitleBlockTemplates();
+	QStringList available_templates = current_collection -> templates();
 	if (available_templates.count()) {
 		templates_ -> insertSeparator(1);
 		foreach (QString template_name, available_templates) {
 			templates_ -> addItem(template_name, QVariant(true));
 		}
 	}
+	
+	updateNewName();
 }
+
+/**
+	Enable or diable the "new name" text field depending of the selected
+	template.
+*/
+void TitleBlockTemplateLocationChooser::updateNewName() {
+	int template_index = templates_ -> currentIndex();
+	new_name_ -> setEnabled(!template_index);
+}

Modified: branches/0.3/sources/titleblock/templatelocationchooser.h
===================================================================
--- branches/0.3/sources/titleblock/templatelocationchooser.h	2012-01-08 14:03:53 UTC (rev 1432)
+++ branches/0.3/sources/titleblock/templatelocationchooser.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -19,6 +19,8 @@
 #define TITLEBLOCK_SLASH_LOCATION_CHOOSER_H
 #include <QtGui>
 #include "templatelocation.h"
+class TitleBlockTemplateCollection;
+
 /**
 	This class is a widget that allows the user to choose a target title block
 	template.
@@ -35,7 +37,7 @@
 	// methods
 	public:
 	TitleBlockTemplateLocation location() const;
-	QETProject *project() const;
+	TitleBlockTemplatesCollection *collection() const;
 	QString name() const;
 	void setLocation(const TitleBlockTemplateLocation &);
 	private:
@@ -43,12 +45,16 @@
 	
 	// slots
 	private slots:
+	void updateCollections();
 	void updateTemplates();
+	void updateNewName();
 	
 	// attributes
 	private:
-	QComboBox *projects_;  ///< Projects combo box
-	QComboBox *templates_; ///< Existing templates combo box
-	QLineEdit *new_name_;  ///< New template name textfield
+	QComboBox *collections_;  ///< Collections combo box
+	/// Collections index within the combo box
+	QHash<int, TitleBlockTemplatesCollection *> collections_index_;
+	QComboBox *templates_;    ///< Existing templates combo box
+	QLineEdit *new_name_;     ///< New template name textfield
 };
 #endif

Added: branches/0.3/sources/titleblock/templatescollection.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatescollection.cpp	                        (rev 0)
+++ branches/0.3/sources/titleblock/templatescollection.cpp	2012-01-08 17:04:34 UTC (rev 1433)
@@ -0,0 +1,464 @@
+/*
+	Copyright 2006-2012 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 <http://www.gnu.org/licenses/>.
+*/
+#include "templatescollection.h"
+#include "titleblocktemplate.h"
+#include "qetapp.h"
+#include "qetproject.h"
+
+/**
+	Constructor
+	@param parent Parent QObject
+*/
+TitleBlockTemplatesCollection::TitleBlockTemplatesCollection(QObject *parent) :
+	QObject(parent),
+	protocol_("unknown")
+{
+}
+
+/**
+	Destructor
+*/
+TitleBlockTemplatesCollection::~TitleBlockTemplatesCollection() {
+}
+
+/**
+	@return the title of this collection
+*/
+QString TitleBlockTemplatesCollection::title() const {
+	return(title_);
+}
+
+/**
+	@oaram title New title for this collection
+*/
+void TitleBlockTemplatesCollection::setTitle(const QString &title) {
+	title_ = title;
+}
+
+/**
+	@return the protocol used by this collection ; examples: commontbt,
+	customtbt, embedtbt, ...
+*/
+QString TitleBlockTemplatesCollection::protocol() const {
+	return(protocol_);
+}
+
+/**
+	Define the protocol for this collection
+	@param protocol New protocol for this collection
+*/
+void TitleBlockTemplatesCollection::setProtocol(const QString &protocol) {
+	if (!protocol.isEmpty()) protocol_ = protocol;
+}
+
+/**
+	@return the project this collection is affiliated to, or 0 if this
+	collection is not related to any project.
+*/
+QETProject *TitleBlockTemplatesCollection::parentProject() {
+	return(0);
+}
+
+/**
+	Constructor
+	@param project Parent project
+	@param parent Parent QObject
+*/
+TitleBlockTemplatesProjectCollection::TitleBlockTemplatesProjectCollection(QETProject *project, QObject *parent) :
+	TitleBlockTemplatesCollection(parent),
+	project_(project)
+{
+}
+
+/**
+	Destructor
+*/
+TitleBlockTemplatesProjectCollection::~TitleBlockTemplatesProjectCollection() {
+}
+
+/**
+	@return a human readable title for this collection
+*/
+QString TitleBlockTemplatesProjectCollection::title() const {
+	if (!title_.isEmpty()) return(title_);
+	
+	// if the title attribute is empty, we generate a suitable one using the
+	// parent project
+	QString final_title;
+	if (project_) {
+		QString project_title = project_ -> title();
+		if (project_title.isEmpty()) {
+			final_title = QString(
+				tr(
+					"Cartouches du projet sans titre (id %1)",
+					"collection title when the parent project has an empty title -- %1 is the project internal id"
+				)
+			);
+			final_title = final_title.arg(QETApp::projectId(project_));
+		} else {
+			final_title = QString(
+				tr(
+					"Cartouches du projet \"%1\"",
+					"collection title when the project has a suitble title -- %1 is the project title"
+				)
+			);
+			final_title = final_title.arg(project_title);
+		}
+	}
+	return(final_title);
+}
+
+/**
+	@return the protocol used to mention this collection
+*/
+QString TitleBlockTemplatesProjectCollection::protocol() const {
+	if (project_) {
+		int project_id = QETApp::projectId(project_);
+		if (project_id != -1) {
+			return(QString("project%1+embedtbt").arg(project_id));
+		}
+	}
+	// fall back on the parent method
+	return(TitleBlockTemplatesCollection::protocol());
+}
+
+/**
+	@return the parent project of this project collection
+*/
+QETProject *TitleBlockTemplatesProjectCollection::parentProject() {
+	return(project_);
+}
+
+/**
+	@return the list of title block templates embedded within the project.
+*/
+QStringList TitleBlockTemplatesProjectCollection::templates() {
+	return(titleblock_templates_xml_.keys());
+}
+
+/**
+	@param template_name Name of the requested template
+	@return the requested template, or 0 if there is no valid template of this
+	name within the project
+*/
+TitleBlockTemplate *TitleBlockTemplatesProjectCollection::getTemplate(const QString &template_name){
+	// Do we have already loaded this template?
+	if (titleblock_templates_.contains(template_name)) {
+		return(titleblock_templates_[template_name]);
+	}
+	
+	// No? Do we even know of it?
+	if (!titleblock_templates_xml_.contains(template_name)) {
+		return(0);
+	}
+	
+	// Ok, we have its XML description, we have to generate a TitleBlockTemplate object
+	TitleBlockTemplate *titleblock_template = new TitleBlockTemplate(this);
+	if (titleblock_template -> loadFromXmlElement(titleblock_templates_xml_[template_name])) {
+		titleblock_templates_.insert(template_name, titleblock_template);
+		return(titleblock_template);
+	} else {
+		return(0);
+	}
+}
+
+/**
+	@param template_name Name of the requested template
+	@return the XML description of the requested template, or a null QDomElement
+	if the project does not have such an titleblock template
+*/
+QDomElement TitleBlockTemplatesProjectCollection::getTemplateXmlDescription(const QString &template_name)  {
+	if (titleblock_templates_xml_.contains(template_name)) {
+		return(titleblock_templates_xml_[template_name]);
+	}
+	return(QDomElement());
+}
+
+/**
+	This methods allows adding or modifying a template embedded within the
+	project. This method emits the signal changed() 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 \<titleblocktemplate\> XML element describing the
+	template. Its "name" attribute must equal to template_name.
+	@return false if a problem occured, true otherwise
+*/
+bool TitleBlockTemplatesProjectCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_elmt) {
+	// check basic stuff
+	if (xml_elmt.tagName() != "titleblocktemplate" || xml_elmt.attribute("name") != template_name) {
+		return(false);
+	}
+	
+	// we *require* a project (at least for the moment...)
+	if (!project_) return(false);
+	
+	// we import the provided XML element in the project document
+	QDomElement import = xml_document_.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_.insert(template_name, import);
+	
+	if (titleblock_templates_.contains(template_name)) {
+		titleblock_templates_[template_name] -> loadFromXmlElement(titleblock_templates_xml_[template_name]);
+	}
+	emit(changed(this, template_name));
+	
+	return(true);
+}
+
+/**
+	This methods allows removing a template embedded within the project. This
+	method emits the signal changed() if necessary.
+	@param template_name Name of the template to be removed
+*/
+void TitleBlockTemplatesProjectCollection::removeTemplate(const QString &template_name) {
+	emit(aboutToRemove(this, template_name));
+	
+	// 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(changed(this, template_name));
+}
+
+/**
+	@param template_name Name of the requested template
+	@return the location object for the requested template
+*/
+TitleBlockTemplateLocation TitleBlockTemplatesProjectCollection::location(const QString &template_name) {
+	return(TitleBlockTemplateLocation(template_name, this));
+}
+
+/**
+	@return true if this collection is read only
+*/
+bool TitleBlockTemplatesProjectCollection::isReadOnly() const {
+	if (project_) {
+		return(project_ -> isReadOnly());
+	}
+	return(false);
+}
+
+/**
+	@param xml_element XML element to be parsed to load title block templates
+*/
+void TitleBlockTemplatesProjectCollection::fromXml(const QDomElement &xml_element) {
+	foreach (QDomElement e, QET::findInDomElement(xml_element, "titleblocktemplates", "titleblocktemplate")) {
+		// each titleblock template must have a name
+		if (!e.hasAttribute("name")) continue;
+		QString titleblock_template_name = e.attribute("name");
+		
+		// if several templates have the same name, we keep the first one encountered
+		if (titleblock_templates_xml_.contains(titleblock_template_name)) continue;
+		
+		// we simply store the XML element describing the titleblock template,
+		// without any further analysis for the moment
+		titleblock_templates_xml_.insert(titleblock_template_name, e);
+	}
+}
+
+/**
+	Constructor
+	@param path Path of the directory containing the collection
+	@param parent Parent QObject
+*/
+TitleBlockTemplatesFilesCollection::TitleBlockTemplatesFilesCollection(const QString &path, QObject *parent) :
+	TitleBlockTemplatesCollection(parent),
+	dir_(
+		path,
+		QString("*%1").arg(TITLEBLOCKS_FILE_EXTENSION),
+		QDir::SortFlags(QDir::Name | QDir::IgnoreCase),
+		QDir::Readable | QDir::Files
+	)
+{
+	if (dir_.exists()) {
+		watcher_.addPath(dir_.canonicalPath());
+	}
+	connect(&watcher_, SIGNAL(directoryChanged(const QString &)), this, SLOT(fileSystemChanged(const QString &)));
+}
+
+/**
+	Destructor
+*/
+TitleBlockTemplatesFilesCollection::~TitleBlockTemplatesFilesCollection() {
+}
+
+/**
+	@return the canonical path of the directory hosting this collection.
+*/
+QString TitleBlockTemplatesFilesCollection::path(const QString &template_name) const {
+	if (template_name.isEmpty()) {
+		return(dir_.canonicalPath());
+	} else {
+		return(dir_.absoluteFilePath(toFileName(template_name)));
+	}
+}
+
+/**
+	@return the list of templates contained in this collection
+*/
+QStringList TitleBlockTemplatesFilesCollection::templates() {
+	QStringList templates_names;
+	QRegExp replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
+	foreach(QString name, dir_.entryList()) {
+		templates_names << name.replace(replace_regexp, "");
+	}
+	return(templates_names);
+}
+
+/**
+	@return the template which name is \a template_name, or 0 if the template
+	could not be loaded.
+*/
+TitleBlockTemplate *TitleBlockTemplatesFilesCollection::getTemplate(const QString &template_name) {
+	if (!templates().contains(template_name)) return(0);
+	
+	TitleBlockTemplate *tbtemplate = new TitleBlockTemplate();
+	QString tbt_file_path = path(template_name);
+	
+	bool loading = tbtemplate -> loadFromXmlFile(tbt_file_path);
+	if (!loading) {
+		delete tbtemplate;
+		return(0);
+	}
+	return(tbtemplate);
+}
+
+/**
+	@param template_name Name of a template (which has to already exist)
+	@return the XML description for the \a template_name template, or a null QDomElement if no such template exists.
+*/
+QDomElement TitleBlockTemplatesFilesCollection::getTemplateXmlDescription(const QString &template_name) {
+	QString xml_file_path = path(template_name);
+	
+	QFileInfo xml_file_info(xml_file_path);
+	if (!xml_file_info.exists() || !xml_file_info.isReadable()) {
+		return(QDomElement());
+	}
+	
+	QFile xml_file(xml_file_path);
+	if (!xml_file.open(QIODevice::ReadOnly)) {
+		return(QDomElement());
+	}
+	
+	QDomDocument *xml_document = new QDomDocument();
+	bool xml_parsing = xml_document -> setContent(&xml_file);
+	if (!xml_parsing) {
+		delete xml_document;
+		return(QDomElement());
+	}
+	return(xml_document -> documentElement());
+}
+
+/**
+	Set the XML description of the \a template_name template to \a xml_element.
+	@param template_name Name of a template (which does not have to already exist)
+	@param xml_element XML element describing the template
+*/
+bool TitleBlockTemplatesFilesCollection::setTemplateXmlDescription(const QString &template_name, const QDomElement &xml_element) {
+	if (template_name.isEmpty()) return(false);
+	
+	// prevent the watcher from emitting signals while we open and write to file
+	blockSignals(true);
+	
+	QFile xml_file(path(template_name));
+	if (!xml_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+		return(false);
+	}
+	QDomDocument doc;
+	doc.appendChild(doc.importNode(xml_element, true));
+	
+	QTextStream out(&xml_file);
+	out.setCodec("UTF-8");
+	out << doc.toString(4);
+	xml_file.close();
+	
+	// emit a single signal for the change
+	blockSignals(false);
+	emit(changed(this, template_name));
+	return(true);
+}
+
+/**
+	Remove the \a template_name template.
+*/
+void TitleBlockTemplatesFilesCollection::removeTemplate(const QString &template_name) {
+	emit(aboutToRemove(this, template_name));
+	// prevent the watcher from emitting signals while we open and write to file
+	blockSignals(true);
+	
+	dir_.remove(toFileName(template_name));
+	
+	// emit a single signal for the removal
+	blockSignals(false);
+	emit(changed(this, template_name));
+}
+
+/**
+	@param template_name Name of a template supposed to be contained within
+	this collection.
+	@return 
+*/
+TitleBlockTemplateLocation TitleBlockTemplatesFilesCollection::location(const QString &template_name) {
+	return(TitleBlockTemplateLocation(template_name, this));
+}
+
+/**
+	@return true if this collection is read only, false otherwise
+*/
+bool TitleBlockTemplatesFilesCollection::isReadOnly() const {
+	QFileInfo info(dir_.canonicalPath());
+	return(!info.isWritable());
+}
+
+/**
+	@param file_name A file name
+	@return the template name for \a file_name
+*/
+QString TitleBlockTemplatesFilesCollection::toTemplateName(const QString &file_name) {
+	static QRegExp replace_regexp(QString("%1$").arg(TITLEBLOCKS_FILE_EXTENSION));
+	QString template_name(file_name);
+	return(template_name.replace(replace_regexp, ""));
+}
+
+/**
+	@param template_name A template name
+	@return the file name for \a template_name
+*/
+QString TitleBlockTemplatesFilesCollection::toFileName(const QString &template_name) {
+	return(QString("%1%2").arg(template_name).arg(TITLEBLOCKS_FILE_EXTENSION));
+}
+
+/**
+	Handle the changes occuring on the file system.
+	@param str Path of the directory that changed.
+*/
+void TitleBlockTemplatesFilesCollection::fileSystemChanged(const QString &str) {
+	Q_UNUSED(str);
+	dir_.refresh();
+	emit(changed(this));
+}

Added: branches/0.3/sources/titleblock/templatescollection.h
===================================================================
--- branches/0.3/sources/titleblock/templatescollection.h	                        (rev 0)
+++ branches/0.3/sources/titleblock/templatescollection.h	2012-01-08 17:04:34 UTC (rev 1433)
@@ -0,0 +1,148 @@
+/*
+	Copyright 2006-2012 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 <http://www.gnu.org/licenses/>.
+*/
+#ifndef TITLEBLOCK_SLASH_TEMPLATES_COLLECTION_H
+#define TITLEBLOCK_SLASH_TEMPLATES_COLLECTION_H
+#define TITLEBLOCKS_FILE_EXTENSION ".titleblock"
+#include <QtCore>
+#include <QtXml>
+#include "templatelocation.h"
+class TitleBlockTemplate;
+class QETProject;
+
+/**
+	This abstract class represents a generic collection of title block templates.
+	Unlike elements collections, title block templates collections do not provide
+	a tree structure. Instead, they provide a simple, flat list of available
+	templates.
+*/
+class TitleBlockTemplatesCollection : public QObject {
+	Q_OBJECT
+	
+	// Constructors, destructor
+	public:
+	TitleBlockTemplatesCollection(QObject *parent);
+	virtual ~TitleBlockTemplatesCollection();
+	private:
+	TitleBlockTemplatesCollection(const TitleBlockTemplatesCollection &);
+	
+	// methods
+	public:
+	virtual QStringList templates() = 0;
+	virtual TitleBlockTemplate *getTemplate(const QString &) = 0;
+	virtual QDomElement getTemplateXmlDescription(const QString &) = 0;
+	virtual bool setTemplateXmlDescription(const QString &, const QDomElement &) = 0;
+	virtual void removeTemplate(const QString &) = 0;
+	virtual TitleBlockTemplateLocation location(const QString & = QString()) = 0;
+	virtual bool isReadOnly() const = 0;
+	virtual QString title() const;
+	virtual void setTitle(const QString &);
+	virtual QString protocol() const;
+	virtual void setProtocol(const QString &);
+	virtual QETProject *parentProject();
+	
+	signals:
+	void changed(TitleBlockTemplatesCollection *, const QString & = QString());
+	void aboutToRemove(TitleBlockTemplatesCollection *, const QString &);
+	
+	// attributes
+	protected:
+	/// Human-readable title for this collection
+	QString title_;
+	/// Protocol used to designate this collection
+	QString protocol_;
+	/// Already parsed embedded titleblock templates
+	QHash<QString, TitleBlockTemplate *> titleblock_templates_;
+};
+
+/**
+	This class represents a simple abastraction layer for a collection of title
+	block templates embedded within a project.
+*/
+class TitleBlockTemplatesProjectCollection : public TitleBlockTemplatesCollection {
+	Q_OBJECT
+	
+	// Constructors, destructor
+	public:
+	TitleBlockTemplatesProjectCollection(QETProject *, QObject *parent = 0);
+	virtual ~TitleBlockTemplatesProjectCollection();
+	private:
+	TitleBlockTemplatesProjectCollection(const TitleBlockTemplatesProjectCollection &);
+	
+	// methods
+	public:
+	virtual QString title() const;
+	virtual QString protocol() const;
+	virtual QETProject *parentProject();
+	virtual QStringList templates();
+	virtual TitleBlockTemplate *getTemplate(const QString &);
+	virtual QDomElement getTemplateXmlDescription(const QString &);
+	virtual bool setTemplateXmlDescription(const QString &, const QDomElement &);
+	virtual void removeTemplate(const QString &);
+	virtual TitleBlockTemplateLocation location(const QString & = QString());
+	virtual bool isReadOnly() const;
+	virtual void fromXml(const QDomElement &);
+	
+	// attributes
+	private:
+	/// Parent project
+	QETProject *project_;
+	/// Parent QDomDocument for stored QDomElements
+	QDomDocument xml_document_;
+	/// XML descriptions of embedded titleblock templates
+	QHash<QString, QDomElement> titleblock_templates_xml_;
+};
+
+/**
+	This classe represents a simple abastraction layer for a file-based title
+	block templates directory. 
+*/
+class TitleBlockTemplatesFilesCollection : public TitleBlockTemplatesCollection {
+	Q_OBJECT
+	
+	// Constructors, destructor
+	public:
+	TitleBlockTemplatesFilesCollection(const QString &, QObject * = 0);
+	virtual ~TitleBlockTemplatesFilesCollection();
+	private:
+	TitleBlockTemplatesFilesCollection(const TitleBlockTemplatesFilesCollection &);
+	
+	// methods
+	public:
+	QString path(const QString & = QString()) const;
+	virtual QStringList templates();
+	virtual TitleBlockTemplate *getTemplate(const QString &);
+	virtual QDomElement getTemplateXmlDescription(const QString &);
+	virtual bool setTemplateXmlDescription(const QString &, const QDomElement &);
+	virtual void removeTemplate(const QString &);
+	virtual TitleBlockTemplateLocation location(const QString & = QString());
+	virtual bool isReadOnly() const;
+	
+	static QString toTemplateName(const QString &);
+	static QString toFileName(const QString &);
+	
+	private slots:
+	void fileSystemChanged(const QString &str);
+	
+	// attributes
+	private:
+	/// File System Watcher object to track the files changes made outside the application
+	QFileSystemWatcher watcher_;
+	/// Collection real directory
+	QDir dir_;
+};
+#endif


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/