From 4795ed206dc53dd8e0b7bfb6a1d99f5ef500d581 Mon Sep 17 00:00:00 2001 From: xavier Date: Sun, 22 Jan 2012 10:40:37 +0000 Subject: [PATCH] Implemented drag'n drop of title block templates to diagrams + automatic integration in the parent project git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/branches/0.3@1471 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- sources/diagramview.cpp | 90 ++++++- sources/diagramview.h | 7 + sources/elementspanel.cpp | 57 +++- sources/elementspanel.h | 2 + sources/qetproject.cpp | 46 +++- sources/qetproject.h | 2 + .../integrationmovetemplateshandler.cpp | 247 ++++++++++++++++++ .../integrationmovetemplateshandler.h | 73 ++++++ sources/titleblock/movetemplateshandler.h | 46 ++++ sources/titleblock/templatescollection.cpp | 5 +- 10 files changed, 560 insertions(+), 15 deletions(-) create mode 100644 sources/titleblock/integrationmovetemplateshandler.cpp create mode 100644 sources/titleblock/integrationmovetemplateshandler.h create mode 100644 sources/titleblock/movetemplateshandler.h diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 99c629fcc..d0cb7a4cc 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -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 @@ DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : QGraphicsView(pare 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::rotateTexts() { 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 @@ void DiagramView::dragMoveEvent(QDragMoveEvent *e) { } /** - 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 @@ -247,6 +269,19 @@ void DiagramView::dropEvent(QDropEvent *e) { emit(aboutToAddElement()); } +/** + 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 */ @@ -672,6 +707,20 @@ bool DiagramView::mustIntegrateElement(const ElementsLocation &location) const { return(must_integrate_element); } +/** + @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 @@ void DiagramView::mouseDoubleClickEvent(QMouseEvent *e) { } /** - 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 @@ void DiagramView::addDroppedElement() { } 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(); +} diff --git a/sources/diagramview.h b/sources/diagramview.h index 69f0e252d..52575648d 100644 --- a/sources/diagramview.h +++ b/sources/diagramview.h @@ -19,6 +19,7 @@ #define DIAGRAMVIEW_H #include #include "elementslocation.h" +#include "templatelocation.h" class Conductor; class Diagram; class Element; @@ -78,8 +79,11 @@ class DiagramView : public QGraphicsView { 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 @@ class DiagramView : public QGraphicsView { 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 @@ class DiagramView : public QGraphicsView { private slots: void addDroppedElement(); + void setDroppedTitleBlockTemplate(const TitleBlockTemplateLocation &); void adjustGridToZoom(); void applyReadOnly(); }; diff --git a/sources/elementspanel.cpp b/sources/elementspanel.cpp index 93214b1bd..6fe0e233c 100644 --- a/sources/elementspanel.cpp +++ b/sources/elementspanel.cpp @@ -493,9 +493,24 @@ void ElementsPanel::dropEvent(QDropEvent *e) { 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; @@ -548,6 +563,23 @@ void ElementsPanel::startDrag(Qt::DropActions supportedActions) { drag -> start(Qt::MoveAction | Qt::CopyAction); } +/** + 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 */ @@ -712,10 +744,13 @@ QTreeWidgetItem *ElementsPanel::addElement(QTreeWidgetItem *qtwi_parent, Element 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 @@ QTreeWidgetItem *ElementsPanel::addTitleBlockTemplatesCollection( 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); diff --git a/sources/elementspanel.h b/sources/elementspanel.h index 4e10d8eaa..164f78124 100644 --- a/sources/elementspanel.h +++ b/sources/elementspanel.h @@ -117,6 +117,8 @@ class ElementsPanel : public QTreeWidget { void dragMoveEvent(QDragMoveEvent *); void dropEvent(QDropEvent *); void startDrag(Qt::DropActions); + void startElementDrag(const ElementsLocation &); + void startTitleBlockTemplateDrag(const TitleBlockTemplateLocation &); bool event(QEvent *); private: diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index d3dcc0b6b..7150342de 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -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 @@ QString QETProject::integrateElement(const QString &elmt_path, MoveElementsHandl 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 @@ QString QETProject::integrateElement(const QString &elmt_path, MoveElementsHandl 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(); @@ -672,6 +673,41 @@ QString QETProject::integrateElement(const QString &elmt_path, MoveElementsHandl } } +/** + 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 diff --git a/sources/qetproject.h b/sources/qetproject.h index 8b47766cf..7820867c2 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -33,6 +33,7 @@ class ElementsLocation; 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 @@ class QETProject : public QObject { 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 *); diff --git a/sources/titleblock/integrationmovetemplateshandler.cpp b/sources/titleblock/integrationmovetemplateshandler.cpp new file mode 100644 index 000000000..5715db082 --- /dev/null +++ b/sources/titleblock/integrationmovetemplateshandler.cpp @@ -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 . +*/ +#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()); +} + diff --git a/sources/titleblock/integrationmovetemplateshandler.h b/sources/titleblock/integrationmovetemplateshandler.h new file mode 100644 index 000000000..de372e527 --- /dev/null +++ b/sources/titleblock/integrationmovetemplateshandler.h @@ -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 . +*/ +#ifndef TITLEBLOCK_SLASH_INTEGRATION_MOVE_TEMPLATES_HANDLER_H +#define TITLEBLOCK_SLASH_INTEGRATION_MOVE_TEMPLATES_HANDLER_H +#include "movetemplateshandler.h" +#include +/** + 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 diff --git a/sources/titleblock/movetemplateshandler.h b/sources/titleblock/movetemplateshandler.h new file mode 100644 index 000000000..b2c82fe14 --- /dev/null +++ b/sources/titleblock/movetemplateshandler.h @@ -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 . +*/ +#ifndef TITLEBLOCK_SLASH_MOVE_TEMPLATES_HANDLER_H +#define TITLEBLOCK_SLASH_MOVE_TEMPLATES_HANDLER_H +#include +#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 diff --git a/sources/titleblock/templatescollection.cpp b/sources/titleblock/templatescollection.cpp index fb61c6976..ed4dffcf9 100644 --- a/sources/titleblock/templatescollection.cpp +++ b/sources/titleblock/templatescollection.cpp @@ -202,7 +202,7 @@ QDomElement TitleBlockTemplatesProjectCollection::getTemplateXmlDescription(cons */ 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 @@ bool TitleBlockTemplatesProjectCollection::setTemplateXmlDescription(const QStri // 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];