[qet] [1471] Implemented drag' n drop of title block templates to diagrams + automatic integration in the parent project

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


Revision: 1471
Author:   xavier
Date:     2012-01-22 11:40:37 +0100 (Sun, 22 Jan 2012)
Log Message:
-----------
Implemented drag'n drop of title block templates to diagrams + automatic integration in the parent project

Modified Paths:
--------------
    branches/0.3/sources/diagramview.cpp
    branches/0.3/sources/diagramview.h
    branches/0.3/sources/elementspanel.cpp
    branches/0.3/sources/elementspanel.h
    branches/0.3/sources/qetproject.cpp
    branches/0.3/sources/qetproject.h
    branches/0.3/sources/titleblock/templatescollection.cpp

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

Modified: branches/0.3/sources/diagramview.cpp
===================================================================
--- branches/0.3/sources/diagramview.cpp	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/diagramview.cpp	2012-01-22 10:40:37 UTC (rev 1471)
@@ -27,10 +27,12 @@
 #include "elementtextitem.h"
 #include "independenttextitem.h"
 #include "titleblockpropertieswidget.h"
+#include "templatelocation.h"
 #include "qetapp.h"
 #include "qetproject.h"
 #include "borderpropertieswidget.h"
 #include "integrationmoveelementshandler.h"
+#include "integrationmovetemplateshandler.h"
 #include "qetdiagrameditor.h"
 #include "qeticons.h"
 #include "qetmessagebox.h"
@@ -73,6 +75,11 @@
 	connect(&(scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(updateWindowTitle()));
 	
 	connect(this, SIGNAL(aboutToAddElement()), this, SLOT(addDroppedElement()), Qt::QueuedConnection);
+	connect(
+		this, SIGNAL(aboutToSetDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &)),
+		this, SLOT(setDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &)),
+		Qt::QueuedConnection
+	);
 	QShortcut *edit_conductor_color_shortcut = new QShortcut(QKeySequence(Qt::Key_F2), this);
 	connect(edit_conductor_color_shortcut, SIGNAL(activated()), this, SLOT(editSelectedConductorColor()));
 }
@@ -205,6 +212,8 @@
 void DiagramView::dragEnterEvent(QDragEnterEvent *e) {
 	if (e -> mimeData() -> hasFormat("application/x-qet-element-uri")) {
 		e -> acceptProposedAction();
+	} else if (e -> mimeData() -> hasFormat("application/x-qet-titleblock-uri")) {
+		e -> acceptProposedAction();
 	} else {
 		e -> ignore();
 	}
@@ -228,13 +237,26 @@
 }
 
 /**
-	Gere les depots (drop) acceptes sur le schema. Cette methode emet le signal
-	aboutToAddElement si l'element depose est accessible.
-	@param e le QDropEvent correspondant au drag'n drop effectue
+	Handle the drops accepted on diagram (elements and title block templates). 
+	@param e the QDropEvent describing the current drag'n drop
 */
 void DiagramView::dropEvent(QDropEvent *e) {
-	// recupere l'emplacement de l'element depuis le drag'n drop
+
+	if (e -> mimeData() -> hasFormat("application/x-qet-element-uri")) {
+		handleElementDrop(e);
+	} else if (e -> mimeData() -> hasFormat("application/x-qet-titleblock-uri")) {
+		handleTitleBlockDrop(e);
+	}
+}
+
+/**
+	Handle the drop of an element.
+	@param e the QDropEvent describing the current drag'n drop
+*/
+void DiagramView::handleElementDrop(QDropEvent *e) {
+	// fetch the element location from the drop event
 	QString elmt_path = e -> mimeData() -> text();
+	
 	ElementsLocation location(ElementsLocation::locationFromString(elmt_path));
 	
 	// verifie qu'il existe un element correspondant a cet emplacement
@@ -248,6 +270,19 @@
 }
 
 /**
+	Handle the drop of an element.
+	@param e the QDropEvent describing the current drag'n drop
+*/
+void DiagramView::handleTitleBlockDrop(QDropEvent *e) {
+	// fetch the title block template location from the drop event
+	TitleBlockTemplateLocation tbt_loc;
+	tbt_loc.fromString(e -> mimeData() -> text());
+	if (tbt_loc.isValid()) {
+		emit(aboutToSetDroppedTitleBlockTemplate(tbt_loc));
+	}
+}
+
+/**
 	Passe le Diagram en mode visualisation
 */
 void DiagramView::setVisualisationMode() {
@@ -673,6 +708,20 @@
 }
 
 /**
+	@param tbt_loc A title block template location
+	@return true if the title block template needs to be integrated in the
+	parent project before being applied to the current diagram, or false if it
+	can be directly applied
+*/
+bool DiagramView::mustIntegrateTitleBlockTemplate(const TitleBlockTemplateLocation &tbt_loc) const {
+	// unlike elements, the integration of title block templates is mandatory, so we simply check whether the parent project of the 
+	QETProject *tbt_parent_project = tbt_loc.parentProject();
+	if (!tbt_parent_project) return(true);
+	
+	return(tbt_parent_project != scene -> project());
+}
+
+/**
 	@param location Emplacement de l'element a ajouter sur le schema
 	@param pos Position (dans les coordonnees de la vue) a laquelle l'element sera ajoute
 */
@@ -1095,7 +1144,7 @@
 }
 
 /**
-	Cette methode ajoute l'element deisgne par l'emplacement location a la
+	Cette methode ajoute l'element designe par l'emplacement location a la
 	position pos. Si necessaire, elle demande l'integration de l'element au
 	projet.
 	@see mustIntegrateElement
@@ -1119,3 +1168,34 @@
 	}
 	adjustSceneRect();
 }
+
+/**
+	@param tbt TitleBlockTemplateLocation
+*/
+void DiagramView::setDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &tbt) {
+	// fetch the current title block properties
+	TitleBlockProperties titleblock_properties_before = scene -> border_and_titleblock.exportTitleBlock();
+	
+	// check the provided template is not already applied
+	QETProject *tbt_parent_project = tbt.parentProject();
+	if (tbt_parent_project && tbt_parent_project == scene -> project()) {
+		// same parent project and same name = same title block template
+		if (tbt.name() == titleblock_properties_before.template_name) return;
+	}
+	
+	// integrate the provided template into the project if needed
+	QString integrated_template_name = tbt.name();
+	if (mustIntegrateTitleBlockTemplate(tbt)) {
+		IntegrationMoveTitleBlockTemplatesHandler *handler = new IntegrationMoveTitleBlockTemplatesHandler(this);
+		//QString error_message;
+		integrated_template_name = scene -> project() -> integrateTitleBlockTemplate(tbt, handler);
+		if (integrated_template_name.isEmpty()) return;
+	}
+	
+	// apply the provided title block template
+	if (titleblock_properties_before.template_name == integrated_template_name) return;
+	TitleBlockProperties titleblock_properties_after = titleblock_properties_before;
+	titleblock_properties_after.template_name = integrated_template_name;
+	scene -> undoStack().push(new ChangeTitleBlockCommand(scene, titleblock_properties_before, titleblock_properties_after));
+	adjustSceneRect();
+}

Modified: branches/0.3/sources/diagramview.h
===================================================================
--- branches/0.3/sources/diagramview.h	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/diagramview.h	2012-01-22 10:40:37 UTC (rev 1471)
@@ -19,6 +19,7 @@
 #define DIAGRAMVIEW_H
 #include <QtGui>
 #include "elementslocation.h"
+#include "templatelocation.h"
 class Conductor;
 class Diagram;
 class Element;
@@ -78,8 +79,11 @@
 	void dragLeaveEvent(QDragLeaveEvent *);
 	void dragMoveEvent(QDragMoveEvent *);
 	void dropEvent(QDropEvent *);
+	void handleElementDrop(QDropEvent *);
+	void handleTitleBlockDrop(QDropEvent *);
 	QRectF viewedSceneRect() const;
 	bool mustIntegrateElement(const ElementsLocation &) const;
+	bool mustIntegrateTitleBlockTemplate(const TitleBlockTemplateLocation &) const;
 	bool addElementAtPos(const ElementsLocation &, const QPoint &);
 	
 	signals:
@@ -93,6 +97,8 @@
 	void titleChanged(DiagramView *, const QString &);
 	/// Signal emis avant l'integration d'un element
 	void aboutToAddElement();
+	/// Signal emitted before integrating a title block template
+	void aboutToSetDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &);
 	/// Signal emis lorsque l'utilisateur souhaite retrouver un element du schema dans les collections
 	void findElementRequired(const ElementsLocation &);
 	/// Signal emis lorsque l'utilisateur souhaite editer un element du schema
@@ -127,6 +133,7 @@
 	
 	private slots:
 	void addDroppedElement();
+	void setDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &);
 	void adjustGridToZoom();
 	void applyReadOnly();
 };

Modified: branches/0.3/sources/elementspanel.cpp
===================================================================
--- branches/0.3/sources/elementspanel.cpp	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/elementspanel.cpp	2012-01-22 10:40:37 UTC (rev 1471)
@@ -493,9 +493,24 @@
 void ElementsPanel::startDrag(Qt::DropActions supportedActions) {
 	Q_UNUSED(supportedActions);
 	// recupere l'emplacement selectionne
-	ElementsLocation location = selectedLocation();
-	if (location.isNull()) return;
+	ElementsLocation element_location = selectedLocation();
+	if (!element_location.isNull()) {
+		startElementDrag(element_location);
+		return;
+	}
 	
+	TitleBlockTemplateLocation tbt_location = locationForTitleBlockTemplate(currentItem());
+	if (tbt_location.isValid()) {
+		startTitleBlockTemplateDrag(tbt_location);
+		return;
+	}
+}
+
+/**
+	Handle the dragging of an element.
+	@param location Location of the dragged element
+*/
+void ElementsPanel::startElementDrag(const ElementsLocation &location) {
 	// recupere la selection
 	ElementsCollectionItem *selected_item = QETApp::collectionItem(location);
 	if (!selected_item) return;
@@ -549,6 +564,23 @@
 }
 
 /**
+	Handle the dragging of a title block template
+	@param location Location of the dragged template.
+*/
+void ElementsPanel::startTitleBlockTemplateDrag(const TitleBlockTemplateLocation &location) {
+	QString location_string = location.toString();
+	
+	QMimeData *mime_data = new QMimeData();
+	mime_data -> setText(location_string);
+	mime_data -> setData("application/x-qet-titleblock-uri", location_string.toAscii());
+	
+	QDrag *drag = new QDrag(this);
+	drag -> setMimeData(mime_data);
+	drag -> setPixmap(QET::Icons::TitleBlock.pixmap(22, 16));
+	drag -> start(Qt::CopyAction);
+}
+
+/**
 	@param event Object describing the received event 
 */
 bool ElementsPanel::event(QEvent *event) {
@@ -712,10 +744,13 @@
 	QPixmap custom_element_pixmap = cache_ -> pixmap();
 	
 	QString whats_this = tr("Ceci est un \351l\351ment que vous pouvez ins\351rer dans votre sch\351ma par cliquer-d\351placer");
-	QString tool_tip = tr("Cliquer-d\351posez cet \351l\351ment sur le sch\351ma pour ins\351rer un \351l\351ment ");
+	QString status_tip = tr(
+		"Cliquer-d\351posez cet \351l\351ment sur le sch\351ma pour ins\351rer un \351l\351ment \253 %1 \273",
+		"Tip displayed in the status bar when selecting an element"
+	);
 	QString final_name(elmt_name.isEmpty() ? custom_element_name : elmt_name);
 	QTreeWidgetItem *qtwi = new QTreeWidgetItem(qtwi_parent, QStringList(final_name));
-	qtwi -> setStatusTip(0, tool_tip + "\253 " + custom_element_name + " \273");
+	qtwi -> setStatusTip(0, status_tip.arg(custom_element_name));
 	qtwi -> setToolTip(0, element -> location().toString());
 	qtwi -> setWhatsThis(0, whats_this);
 	qtwi -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
@@ -788,6 +823,20 @@
 		TitleBlockTemplateLocation template_location = collection -> location(template_name);
 		
 		QTreeWidgetItem *qtwi_tbt = new QTreeWidgetItem(qtwi_tbt_collection, QStringList(final_name));
+		qtwi_tbt -> setStatusTip(
+			0,
+			tr(
+				"Cliquer-d\351posez ce mod\350le de cartouche sur un sch\351ma pour l'y appliquer.",
+				"Tip displayed when selecting a title block template"
+			)
+		);
+		qtwi_tbt -> setWhatsThis(
+			0,
+			tr(
+				"Ceci est un mod\350le de cartouche, qui peut \320tre appliqu\351 a un sch\351ma.",
+				"\"What's this\" tip"
+			)
+		);
 		qtwi_tbt -> setToolTip(0, template_location.toString());
 		qtwi_tbt -> setIcon(0, QET::Icons::TitleBlock);
 		title_blocks_.insert(qtwi_tbt, template_location);

Modified: branches/0.3/sources/elementspanel.h
===================================================================
--- branches/0.3/sources/elementspanel.h	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/elementspanel.h	2012-01-22 10:40:37 UTC (rev 1471)
@@ -117,6 +117,8 @@
 	void dragMoveEvent(QDragMoveEvent *);
 	void dropEvent(QDropEvent *);
 	void startDrag(Qt::DropActions);
+	void startElementDrag(const ElementsLocation &);
+	void startTitleBlockTemplateDrag(const TitleBlockTemplateLocation &);
 	bool event(QEvent *);
 	
 	private:

Modified: branches/0.3/sources/qetproject.cpp
===================================================================
--- branches/0.3/sources/qetproject.cpp	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/qetproject.cpp	2012-01-22 10:40:37 UTC (rev 1471)
@@ -23,6 +23,7 @@
 #include "qetapp.h"
 #include "qetdiagrameditor.h"
 #include "integrationmoveelementshandler.h"
+#include "movetemplateshandler.h"
 #include "basicmoveelementshandler.h"
 #include "qetmessagebox.h"
 #include "titleblocktemplate.h"
@@ -606,7 +607,7 @@
 		return(QString());
 	}
 	
-	// accede a a categorie d'integration
+	// accede a la categorie d'integration
 	ElementsCategory *integ_cat = integrationCategory();
 	
 	// accede a l'element a integrer
@@ -641,18 +642,18 @@
 	if (ElementDefinition *existing_elmt = target_cat -> element(integ_item -> pathName())) {
 		
 		// l'element existe deja - on demande au handler ce que l'on doit faire
-		QET::Action todo = handler -> elementAlreadyExists(integ_elmt, existing_elmt);
+		QET::Action action = handler -> elementAlreadyExists(integ_elmt, existing_elmt);
 		
-		if (todo == QET::Ignore) {
+		if (action == QET::Ignore) {
 			// il faut conserver et utiliser l'element deja integre
 			return(existing_elmt -> location().toString());
-		} else if (todo == QET::Erase) {
+		} else if (action == QET::Erase) {
 			// il faut ecraser l'element deja integre
 			BasicMoveElementsHandler *erase_handler = new BasicMoveElementsHandler();
 			ElementsLocation result_loc = copyElementWithHandler(integ_elmt, target_cat, erase_handler, error_message);
 			delete erase_handler;
 			return(result_loc.toString());
-		} else if (todo == QET::Rename) {
+		} else if (action == QET::Rename) {
 			// il faut faire cohabiter les deux elements en renommant le nouveau 
 			QString integ_element_name = handler -> nameForRenamingOperation();
 			BasicMoveElementsHandler *rename_handler = new BasicMoveElementsHandler();
@@ -673,6 +674,41 @@
 }
 
 /**
+	Integrate a title block template into this project.
+	@param src_tbt The locaiton of the title block template to be integrated into this project
+	@param handler 
+	@return the name of the template after integration, or an empty QString if a problem occured.
+*/
+QString QETProject::integrateTitleBlockTemplate(const TitleBlockTemplateLocation &src_tbt, MoveTitleBlockTemplatesHandler *handler) {
+	TitleBlockTemplateLocation dst_tbt(src_tbt.name(), &titleblocks_);
+	
+	// check whether a TBT having the same name already exists within this project
+	QString target_name = dst_tbt.name();
+	while (titleblocks_.templates().contains(target_name)) {
+		QET::Action action = handler -> templateAlreadyExists(src_tbt, dst_tbt);
+		if (action == QET::Retry) {
+			continue;
+		} else if (action == QET::Erase) {
+			break;
+		} else if (action == QET::Ignore || action == QET::Abort || action == QET::Managed) {
+			return(QString());
+		} else if (action == QET::Rename) {
+			target_name = handler -> nameForRenamingOperation();
+		}
+	}
+	
+	bool integration = setTemplateXmlDescription(
+		target_name,
+		src_tbt.getTemplateXmlDescription()
+	);
+	if (!integration) {
+		handler -> errorWithATemplate(src_tbt, tr("An error occured when integrating the element.", "error message"));
+		target_name = QString();
+	}
+	return(target_name);
+}
+
+/**
 	Permet de savoir si un element est utilise dans un projet
 	@param location Emplacement d'un element
 	@return true si l'element location est utilise sur au moins un des schemas

Modified: branches/0.3/sources/qetproject.h
===================================================================
--- branches/0.3/sources/qetproject.h	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/qetproject.h	2012-01-22 10:40:37 UTC (rev 1471)
@@ -33,6 +33,7 @@
 class TitleBlockTemplate;
 class XmlElementsCollection;
 class MoveElementsHandler;
+class MoveTitleBlockTemplatesHandler;
 /**
 	Cette classe represente un projet QET. Typiquement enregistre dans un
 	fichier, il s'agit d'un document XML integrant des schemas ainsi qu'une
@@ -105,6 +106,7 @@
 	ElementsCategory *integrationCategory() const;
 	QString integrateElement(const QString &, QString &);
 	QString integrateElement(const QString &, MoveElementsHandler *, QString &);
+	QString integrateTitleBlockTemplate(const TitleBlockTemplateLocation &, MoveTitleBlockTemplatesHandler *handler);
 	bool usesElement(const ElementsLocation &);
 	void cleanUnusedElements(MoveElementsHandler *);
 	void cleanEmptyCategories(MoveElementsHandler *);

Added: branches/0.3/sources/titleblock/integrationmovetemplateshandler.cpp
===================================================================
--- branches/0.3/sources/titleblock/integrationmovetemplateshandler.cpp	                        (rev 0)
+++ branches/0.3/sources/titleblock/integrationmovetemplateshandler.cpp	2012-01-22 10:40:37 UTC (rev 1471)
@@ -0,0 +1,247 @@
+/*
+	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 "integrationmovetemplateshandler.h"
+#include "templatescollection.h"
+#include "qetmessagebox.h"
+
+/**
+	Constructor
+	@param parent Qwidget used as parent when showing the user dialog.
+*/
+IntegrationMoveTitleBlockTemplatesHandler::IntegrationMoveTitleBlockTemplatesHandler(QWidget *parent) :
+	MoveTitleBlockTemplatesHandler(parent),
+	parent_widget_(parent),
+	integ_dialog_(0)
+{
+}
+
+/**
+	Destructor
+*/
+IntegrationMoveTitleBlockTemplatesHandler::~IntegrationMoveTitleBlockTemplatesHandler() {
+}
+
+/**
+	@param src Source template
+	@param dst Target template
+	@return the action to be done if the target template already exists
+*/
+QET::Action IntegrationMoveTitleBlockTemplatesHandler::templateAlreadyExists(const TitleBlockTemplateLocation &src, const TitleBlockTemplateLocation &dst) {
+	QString no_parent_collection_error_message(tr("Impossible d'acc\351der \340 la cat\351gorie parente", "error message"));
+	QString cant_get_xml_description_error_message(tr("Impossible d'obtenir la description XML de cet \351l\351ment", "error message"));
+	
+	// we'll need the parent collection of both templates
+	TitleBlockTemplatesCollection *src_tbt_parent_collection = src.parentCollection();
+	if (!src_tbt_parent_collection) return(errorWithATemplate(src, no_parent_collection_error_message));
+	
+	TitleBlockTemplatesCollection *dst_tbt_parent_collection = dst.parentCollection();
+	if (!dst_tbt_parent_collection) return(errorWithATemplate(dst, no_parent_collection_error_message));
+	
+	
+	// first, we compare templates (actually we compare their XML code... sadly not the most efficient approach)
+	QDomElement src_xml_elmt = src.getTemplateXmlDescription();
+	if (src_xml_elmt.isNull()) return(errorWithATemplate(src, cant_get_xml_description_error_message));
+	QDomElement dst_xml_elmt = dst.getTemplateXmlDescription();
+	if (dst_xml_elmt.isNull()) return(errorWithATemplate(dst, cant_get_xml_description_error_message));
+	
+	QDomDocument src_tbt_document;
+	src_tbt_document.appendChild(src_tbt_document.importNode(src_xml_elmt, true));
+	QDomDocument dst_tbt_document;
+	dst_tbt_document.appendChild(dst_tbt_document.importNode(dst_xml_elmt, true));
+	
+	
+	if (src_tbt_document.toString(0) == dst_tbt_document.toString(0)) {
+		// the templates are the same, consider the integration is done
+		qDebug() << Q_FUNC_INFO << "Not integrating" << src.parentCollection() << "/" << src.name()<< "because it is already present in the project";
+		return(QET::Ignore);
+	} else {
+		return(askUser(src, dst));
+	}
+}
+
+/**
+	Display an error message related to a specific title block template.
+	@param tbt Problematic title block template
+	@param message Error message.
+*/
+QET::Action IntegrationMoveTitleBlockTemplatesHandler::errorWithATemplate(const TitleBlockTemplateLocation &tbt, const QString &message) {
+	QString error_message = QString("Une erreur s'est produite avec le mod\350le %1\240: %2").arg(tbt.toString()).arg(message);
+	QET::MessageBox::critical(
+		parent_widget_,
+		tr("Erreur", "message box title"),
+		error_message,
+		QMessageBox::Ok,
+		QMessageBox::Ok
+	);
+	return(QET::Ignore);
+}
+
+/**
+	@return the name to be used when this object returns QET::Rename
+	@see QET::Action
+*/
+QString IntegrationMoveTitleBlockTemplatesHandler::nameForRenamingOperation() {
+	return(rename_);
+}
+
+/**
+	@return the current date with a filename-friendly format
+*/
+QString IntegrationMoveTitleBlockTemplatesHandler::dateString() const {
+	return(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
+}
+
+/**
+	@param tbt A title block template location
+	@return a name to be used in order to duplicate the title block template.
+	This name is based on the current date.
+*/
+QString IntegrationMoveTitleBlockTemplatesHandler::newNameForTemplate(const TitleBlockTemplateLocation &tbt) {
+	return(QString("%1-%2.elmt").arg(tbt.name()).arg(dateString()));
+}
+
+/**
+	Ask the use whether they wish to erase the already existing template, rename it or cancel the operation.
+	@param src Source title block template
+	@param dst Target title block template
+	@return the user answer
+*/
+QET::Action IntegrationMoveTitleBlockTemplatesHandler::askUser(const TitleBlockTemplateLocation &src, const TitleBlockTemplateLocation &dst) {
+	Q_UNUSED(src)
+	initDialog();
+	int result = integ_dialog_ -> exec();
+	if (result == QDialog::Accepted) {
+		if (use_existing_template_ -> isChecked()) {
+			return(QET::Ignore);
+		} else if (erase_template_ -> isChecked()) {
+			return(QET::Erase);
+		} else {
+			rename_ = newNameForTemplate(dst);
+			return(QET::Rename);
+		}
+	} else {
+		return(QET::Abort);
+	}
+}
+
+/**
+	Initialize the user dialog.
+*/
+void IntegrationMoveTitleBlockTemplatesHandler::initDialog() {
+	if (integ_dialog_) return;
+	integ_dialog_ = new QDialog(parent_widget_);
+	integ_dialog_ -> setWindowTitle(tr("Int\351gration d'un mod\350le de cartouche"));
+	
+	dialog_label_ = new QLabel(
+		QString(
+			tr(
+				"Le mod\350le a d\351j\340 \351t\351 "
+				"int\351gr\351 dans le projet. Toutefois, la version que vous "
+				"tentez d'appliquer semble diff\351rente. Que souhaitez-vous "
+				"faire ?",
+				"dialog content - %1 is a title block template name"
+			)
+		)
+	);
+	
+	use_existing_template_ = new QRadioButton(
+		QString(
+			tr(
+				"Utiliser le mod\350le d\351j\340 int\351gr\351",
+				"dialog content"
+			)
+		)
+	);
+	
+	integrate_new_template_ = new QRadioButton(
+		QString(
+			tr(
+				"Int\351grer le mod\350le d\351pos\351",
+				"dialog content"
+			)
+		)
+	);
+	radioButtonleftMargin(integrate_new_template_);
+	
+	erase_template_ = new QRadioButton(
+		QString(
+			tr(
+				"\311craser l'\351l\351ment d\351j\340 int\351gr\351",
+				"dialog content"
+			)
+		)
+	);
+	radioButtonleftMargin(erase_template_);
+	
+	integrate_both_ = new QRadioButton(
+		QString(
+			tr(
+				"Faire cohabiter les deux mod\350les",
+				"dialog content"
+			)
+		)
+	);
+	
+	button_group1_ = new QButtonGroup(this);
+	button_group1_ -> addButton(use_existing_template_);
+	button_group1_ -> addButton(integrate_new_template_);
+	button_group2_ = new QButtonGroup(this);
+	button_group2_ -> addButton(erase_template_);
+	button_group2_ -> addButton(integrate_both_);
+	
+	integrate_new_template_ -> setChecked(true);
+	integrate_both_ -> setChecked(true);
+	
+	buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+	
+	dialog_glayout = new QGridLayout();
+	dialog_glayout -> setColumnMinimumWidth(0, 20);
+	dialog_glayout -> addWidget(erase_template_,  0, 1);
+	dialog_glayout -> addWidget(integrate_both_, 1, 1);
+	
+	dialog_vlayout_ = new QVBoxLayout(integ_dialog_);
+	dialog_vlayout_ -> addWidget(dialog_label_);
+	dialog_vlayout_ -> addWidget(use_existing_template_);
+	dialog_vlayout_ -> addWidget(integrate_new_template_);
+	dialog_vlayout_ -> addLayout(dialog_glayout);
+	dialog_vlayout_ -> addWidget(buttons_);
+	
+	connect(use_existing_template_,  SIGNAL(toggled(bool)), this,          SLOT(correctRadioButtons()));
+	connect(integrate_new_template_, SIGNAL(toggled(bool)), this,          SLOT(correctRadioButtons()));
+	connect(buttons_,                SIGNAL(accepted()),    integ_dialog_, SLOT(accept()));
+	connect(buttons_,                SIGNAL(rejected()),    integ_dialog_, SLOT(reject()));
+}
+
+/**
+	Increase the left margin of a radiob utton.
+	@param button Radio button
+*/
+void IntegrationMoveTitleBlockTemplatesHandler::radioButtonleftMargin(QRadioButton *button) {
+	int a, b, c, d;
+	button -> getContentsMargins(&a, &b, &c, &d);
+	button -> setContentsMargins(a + 15, b, c, d);
+}
+
+/**
+	Ensure the dialog remains consistent.
+*/
+void IntegrationMoveTitleBlockTemplatesHandler::correctRadioButtons() {
+	erase_template_ -> setEnabled(integrate_new_template_ -> isChecked());
+	integrate_both_ -> setEnabled(integrate_new_template_ -> isChecked());
+}
+

Added: branches/0.3/sources/titleblock/integrationmovetemplateshandler.h
===================================================================
--- branches/0.3/sources/titleblock/integrationmovetemplateshandler.h	                        (rev 0)
+++ branches/0.3/sources/titleblock/integrationmovetemplateshandler.h	2012-01-22 10:40:37 UTC (rev 1471)
@@ -0,0 +1,73 @@
+/*
+	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_INTEGRATION_MOVE_TEMPLATES_HANDLER_H
+#define TITLEBLOCK_SLASH_INTEGRATION_MOVE_TEMPLATES_HANDLER_H
+#include "movetemplateshandler.h"
+#include <QtGui>
+/**
+	This class implements the interface defined by
+	MoveTitleBlockTemplatesHandler to ease the integration of title block
+	templates from files-based collections into projects.
+*/
+class IntegrationMoveTitleBlockTemplatesHandler : public MoveTitleBlockTemplatesHandler {
+	Q_OBJECT
+	
+	// constructors, destructor
+	public:
+	IntegrationMoveTitleBlockTemplatesHandler(QWidget * = 0);
+	virtual ~IntegrationMoveTitleBlockTemplatesHandler();
+	private:
+	IntegrationMoveTitleBlockTemplatesHandler(const IntegrationMoveTitleBlockTemplatesHandler &);
+	
+	// methods
+	public:
+	virtual QET::Action templateAlreadyExists(const TitleBlockTemplateLocation &src, const TitleBlockTemplateLocation &dst);
+	virtual QET::Action errorWithATemplate(const TitleBlockTemplateLocation &, const QString &);
+	virtual QString nameForRenamingOperation();
+	
+	private:
+	QString dateString() const;
+	QString newNameForTemplate(const TitleBlockTemplateLocation &);
+	QET::Action askUser(const TitleBlockTemplateLocation &, const TitleBlockTemplateLocation &);
+	void initDialog();
+	void radioButtonleftMargin(QRadioButton *);
+	
+	private slots:
+	void correctRadioButtons();
+	
+	// attributes
+	private:
+	QWidget *parent_widget_;              ///< Widget used as parent to display dialogs
+	QString rename_;                      ///< Name to be used when renaming a title block template
+	QDialog *integ_dialog_;               ///< Dialog in case of conflict when integrating a title block template
+	QLabel *dialog_label_;
+	QVBoxLayout *dialog_vlayout_;
+	QGridLayout *dialog_glayout;
+	QDialogButtonBox *buttons_;
+	QRadioButton *use_existing_template_;    ///< Radio button the user may click to use the existing template and stop the integration
+	QRadioButton *integrate_new_template_;   ///< Radio button the user may click to integrate the template
+	QRadioButton *erase_template_;           ///< Radio button the user may click for the integrated template to erase the existing one
+	/*
+		Radio button the user may click for the integrated template to be
+		automatically renamed in order to be stored along with the existing one.
+	*/
+	QRadioButton *integrate_both_;
+	QButtonGroup *button_group1_;
+	QButtonGroup *button_group2_;
+};
+#endif

Added: branches/0.3/sources/titleblock/movetemplateshandler.h
===================================================================
--- branches/0.3/sources/titleblock/movetemplateshandler.h	                        (rev 0)
+++ branches/0.3/sources/titleblock/movetemplateshandler.h	2012-01-22 10:40:37 UTC (rev 1471)
@@ -0,0 +1,46 @@
+/*
+	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_MOVE_TEMPLATES_HANDLER_H
+#define TITLEBLOCK_SLASH_MOVE_TEMPLATES_HANDLER_H
+#include <QtCore>
+#include "qet.h"
+#include "templatelocation.h"
+
+/**
+	This class defines the minimal interface required to implement an object
+	able to handle a title block template move or copy.
+	It is a Strategy pattern that embeds the copy/move error handling instead
+	of the whole process.
+*/
+class MoveTitleBlockTemplatesHandler : public QObject {
+	Q_OBJECT
+	
+	// Constructors, destructor
+	public:
+	MoveTitleBlockTemplatesHandler(QObject * = 0) {}
+	virtual ~MoveTitleBlockTemplatesHandler() {}
+	private:
+	MoveTitleBlockTemplatesHandler(const MoveTitleBlockTemplatesHandler &);
+	
+	// methods
+	public:
+	virtual QET::Action templateAlreadyExists(const TitleBlockTemplateLocation &src, const TitleBlockTemplateLocation &dst) = 0;
+	virtual QET::Action errorWithATemplate(const TitleBlockTemplateLocation &, const QString &) = 0;
+	virtual QString nameForRenamingOperation() = 0;
+};
+#endif

Modified: branches/0.3/sources/titleblock/templatescollection.cpp
===================================================================
--- branches/0.3/sources/titleblock/templatescollection.cpp	2012-01-19 21:01:26 UTC (rev 1470)
+++ branches/0.3/sources/titleblock/templatescollection.cpp	2012-01-22 10:40:37 UTC (rev 1471)
@@ -202,7 +202,7 @@
 */
 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) {
+	if (xml_elmt.tagName() != "titleblocktemplate") {
 		return(false);
 	}
 	
@@ -212,6 +212,9 @@
 	// we import the provided XML element in the project document
 	QDomElement import = xml_document_.importNode(xml_elmt, true).toElement();
 	
+	// ensure the name stored in the XML description remains consistent with the provided template name
+	import.setAttribute("name", template_name);
+	
 	// we either replace the previous description
 	if (titleblock_templates_xml_.contains(template_name)) {
 		QDomElement old_description = titleblock_templates_xml_[template_name];


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