qelectrotech-source-mirror/sources/elementdefinition.cpp
scorpio810 c71ed69342 Updated Copyright 2006-2013
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@2288 bfdf4180-ca20-0410-9c96-a3a8aa849046
2013-06-18 11:10:19 +00:00

477 lines
14 KiB
C++

/*
Copyright 2006-2013 The QElectroTech Team
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 "elementdefinition.h"
#include "elementscollection.h"
#include "moveelementshandler.h"
#include "moveelementsdescription.h"
/**
@return true si l'element est rattache a une collection d'elements
Un element appartenant a une collection a forcement un chemin virtuel.
*/
bool ElementDefinition::hasParentCategory() {
return(parent_category_);
}
/**
@return la categorie a laquelle appartient cet element
*/
ElementsCategory *ElementDefinition::parentCategory() {
return(parent_category_);
}
/**
@return la liste des categories parentes de cet item.
*/
QList<ElementsCategory *> ElementDefinition::parentCategories() {
QList<ElementsCategory *> cat_list;
if (ElementsCategory *par_cat = parentCategory()) {
cat_list << par_cat -> parentCategories() << par_cat;
}
return(cat_list);
}
/**
@return true si l'element est rattache a une collection d'elements
Un element appartenant a une collection a forcement un chemin virtuel.
*/
bool ElementDefinition::hasParentCollection() {
return(parent_collection_);
}
/**
@param other_item Autre item
@return true si other_item est parent (direct ou indirect) de cet item, false sinon
*/
bool ElementDefinition::isChildOf(ElementsCollectionItem *other_item) {
// soit l'autre item est le parent direct de cet element
if (ElementsCategory *other_item_cat = other_item -> toCategory()) {
if (other_item_cat == parentCategory()) {
return(true);
}
}
// soit il est un parent indirect, auquel cas, on peut demander a la categorie parente de repondre a la question
if (ElementsCategory *parent_cat = parentCategory()) {
return(parent_cat -> isChildOf(other_item));
}
// arrive ici, l'autre item n'est pas parent de cet item
return(false);
}
/**
@return la collection d'element a laquelle appartient cet element
*/
ElementsCollection *ElementDefinition::parentCollection() {
return(parent_collection_);
}
/**
@return le projet auquel appartient cette categorie, si celle-ci
appartient a une collection.
*/
QETProject *ElementDefinition::project() {
if (hasParentCollection()) {
return(parentCollection() -> project());
}
return(0);
}
/**
Ne fait rien ; le projet doit etre defini au niveau d'une collection
*/
void ElementDefinition::setProject(QETProject *) {
}
/**
@return le protocole utilise par la collection a laquelle appartient cet element
*/
QString ElementDefinition::protocol() {
// il n'est pas possible d'avoir un protocole sans appartenir a une collection
if (!hasParentCollection()) return(QString());
return(parentCollection() -> protocol());
}
/**
Ne fait rien
*/
void ElementDefinition::setProtocol(const QString &) {
}
/**
@return le chemin virtuel complet de cet element (protocole + chemin)
*/
QString ElementDefinition::fullVirtualPath() {
// il n'est pas possible d'avoir un chemin virtuel sans appartenir a une collection
if (!hasParentCollection()) return(QString());
return(protocol() + "://" + virtualPath());
}
/**
@return l'emplacement de l'element
*/
ElementsLocation ElementDefinition::location() {
return(ElementsLocation(fullVirtualPath(), project()));
}
/**
@return une liste vide - un element ne possede pas de categorie
*/
QList<ElementsCategory *> ElementDefinition::categories() {
return(QList<ElementsCategory *>());
}
/**
@return toujours 0 - un element ne possede pas de categorie
*/
ElementsCategory *ElementDefinition::category(const QString &) {
return(0);
}
/**
@return toujours 0 - un element ne possede pas de categorie
*/
ElementsCategory *ElementDefinition::createCategory(const QString &) {
return(0);
}
/**
@return une liste contenant seulement cet element
*/
QList<ElementDefinition *> ElementDefinition::elements() {
return(QList<ElementDefinition *>() << this);
}
/**
@return cet element si path est vide, 0 sinon
*/
ElementDefinition *ElementDefinition::element(const QString &path) {
if (path.isEmpty()) return(this);
return(0);
}
/**
@return toujours 0 - un element n'en cree pas d'autre
*/
ElementDefinition *ElementDefinition::createElement(const QString &) {
return(0);
}
/**
@return always true - an element contains nothing but itself
*/
bool ElementDefinition::isEmpty() {
return(false);
}
/**
@return always 1
*/
int ElementDefinition::count() {
return(1);
}
/**
@return toujours 0 - un element n'est pas une collection
*/
ElementsCollection *ElementDefinition::toCollection() {
return(0);
}
/**
@return la categorie parente de cet element
*/
ElementsCategory *ElementDefinition::toCategory() {
return(parentCategory());
}
/**
@return toujours 0 - un element n'est pas une categorie
*/
ElementsCategory *ElementDefinition::toPureCategory() {
return(0);
}
/**
@return un pointeur ElementDefinition * sur cet element
*/
ElementDefinition *ElementDefinition::toElement() {
return(this);
}
/**
@return true si cette definition d'element est egale (en termes de contenu)
a la definition d'element other, false sinon.
*/
bool ElementDefinition::equals(ElementDefinition &other) {
/*
Pour le moment, cette methode compare simplement l'export au format
texte des documents XML. Cela peut entrainer de faux positifs.
Exemple : un espace de plus ou de moins dans le XML n'en change pas
forcement la semantique. Mais cela changera l'export au format texte.
*/
QDomDocument this_xml_document;
this_xml_document.appendChild(this_xml_document.importNode(xml(), true));
QString this_text = this_xml_document.toString(0);
QDomDocument other_xml_document;
other_xml_document.appendChild(other_xml_document.importNode(other.xml(), true));
QString other_text = other_xml_document.toString(0);
return(other_text == this_text);
}
/**
@param target_category Categorie cible pour la copie ; elle doit exister
@param handler Gestionnaire d'erreurs a utiliser pour effectuer la copie
@param deep_copy Argument ignore - une copie "recursive" n'a pas de sens pour un element
@return La copie de l'element ou 0 si le processus a echoue
*/
ElementsCollectionItem *ElementDefinition::copy(ElementsCategory *target_category, MoveElementsHandler *handler, bool deep_copy) {
Q_UNUSED(deep_copy);
if (!target_category) return(0);
// echec si le path name de cet element est vide
QString elmt_name(pathName());
if (elmt_name.isEmpty()) return(0);
// cree une description du mouvement a effectuer
MoveElementsDescription mvt_desc;
mvt_desc.setDestinationParentCategory(target_category);
// on tente une copie avec le meme nom interne
mvt_desc.setOriginalDestinationInternalName(pathName());
mvt_desc.setFinalDestinationInternalName(pathName());
mvt_desc.setHandler(handler);
copy(&mvt_desc);
return(mvt_desc.createdItem());
}
/**
Methode privee effectuant une copie de cet element a partir d'une
description du mouvement.
@param mvt_desc Description du mouvement
*/
void ElementDefinition::copy(MoveElementsDescription *mvt_desc) {
// quelques pointeurs pour simplifier l'ecriture de la methode
MoveElementsHandler *handler = mvt_desc -> handler();
ElementsCategory *target_category = mvt_desc -> destinationParentCategory();
ElementDefinition *element_copy = 0;
// verifie que la categorie parente cible est accessible en lecture
if (!target_category -> isReadable()) {
if (!handler) {
return;
} else {
do {
QET::Action todo = handler -> categoryIsNotReadable(target_category);
// on agit en fonction de la reponse du handler
if (todo == QET::Abort) {
mvt_desc -> abort();
return;
} else if (todo == QET::Ignore || todo == QET::Managed) {
return;
} else if (todo == QET::Retry || todo == QET::Erase) {
// reessayer = repasser dans la boucle
} else if (todo == QET::Rename) {
// cas non gere
}
} while (!target_category -> isReadable());
}
}
// verifie que la categorie parente cible est accessible en ecriture
if (!target_category -> isWritable()) {
if (!handler) {
return;
} else {
do {
QET::Action todo = handler -> categoryIsNotWritable(target_category);
// on agit en fonction de la reponse du handler
if (todo == QET::Abort) {
mvt_desc -> abort();
return;
} else if (todo == QET::Ignore || todo == QET::Managed) {
return;
} else if (todo == QET::Retry || todo == QET::Erase) {
// reessayer = repasser dans la boucle
} else if (todo == QET::Rename) {
// cas non gere
}
} while (!target_category -> isWritable());
}
}
// verifie que la cible n'existe pas deja
if ((element_copy = target_category -> element(mvt_desc -> finalDestinationInternalName()))) {
if (!handler) {
return;
} else {
do {
// la cible existe deja : on demande au Handler ce qu'on doit faire
QET::Action todo = handler -> elementAlreadyExists(this, element_copy);
// on agit en fonction de la reponse du handler
if (todo == QET::Abort) {
mvt_desc -> abort();
return;
} else if (todo == QET::Ignore || todo == QET::Managed) {
return;
} else if (todo == QET::Erase) {
break;
} else if (todo == QET::Rename) {
mvt_desc -> setFinalDestinationInternalName(handler -> nameForRenamingOperation());
}
} while ((element_copy = target_category -> element(mvt_desc -> finalDestinationInternalName())));
}
}
/*
A ce stade, on peut creer l'element cible : soit il n'existe pas, soit
on a l'autorisation de l'ecraser
*/
// si la cible existe deja, verifie qu'elle est accessible en ecriture
element_copy = target_category -> element(mvt_desc -> finalDestinationInternalName());
if (element_copy && !element_copy -> isWritable()) {
if (!handler) {
return;
} else {
do {
// la cible n'est pas accessible en ecriture : on demande au Handler ce qu'on doit faire
QET::Action todo = handler -> elementIsNotWritable(element_copy);
// on agit en fonction de la reponse du handler
if (todo == QET::Abort) {
mvt_desc -> abort();
return;
} else if (todo == QET::Ignore || todo == QET::Managed) {
return;
} else if (todo == QET::Retry || todo == QET::Erase) {
// reessayer = repasser dans la boucle
} else if (todo == QET::Rename) {
// cas non gere
}
} while (!element_copy -> isWritable());
}
}
// cree l'element cible
element_copy = target_category -> createElement(mvt_desc -> finalDestinationInternalName());
if (!element_copy) {
if (handler) {
handler -> errorWithAnElement(this, tr("L'\351l\351ment cible n'a pu \352tre cr\351\351."));
}
return;
}
// recopie la definition de l'element
element_copy -> setXml(xml());
element_copy -> write();
mvt_desc -> setCreatedItem(element_copy);
}
/**
@param target_category Categorie cible pour le deplacement ; elle doit exister
@param handler Gestionnaire d'erreurs a utiliser pour effectuer le deplacement
@return L'element apres deplacement ou 0 si le processus a echoue
*/
ElementsCollectionItem *ElementDefinition::move(ElementsCategory *target_category, MoveElementsHandler *handler) {
if (!target_category) return(0);
// echec si le path name de cet element est vide
QString elmt_name(pathName());
if (elmt_name.isEmpty()) return(0);
// cree une description du mouvement a effectuer
MoveElementsDescription mvt_desc;
mvt_desc.setDestinationParentCategory(target_category);
// on tente un deplacement avec le meme nom interne
mvt_desc.setOriginalDestinationInternalName(pathName());
mvt_desc.setFinalDestinationInternalName(pathName());
mvt_desc.setHandler(handler);
move(&mvt_desc);
return(mvt_desc.createdItem());
}
/**
Methode privee effectuant un delacement de cet element a partir d'une
description du mouvement.
Pour etre plus exact, cette methode effectue d'abord une copie de l'element,
puis, si celle-ci a reussi, il supprime l'element d'origine.
@param mvt_desc Description du mouvement
*/
void ElementDefinition::move(MoveElementsDescription *mvt_desc) {
// effectue une copie de l'element
copy(mvt_desc);
ElementsCollectionItem *item_copy = mvt_desc -> createdItem();
if (!item_copy) return;
ElementDefinition *element_copy = item_copy -> toElement();
if (!element_copy) return;
// supprime cet element
MoveElementsHandler *handler = mvt_desc -> handler();
// cet element doit etre accessible en ecriture pour etre supprime
if (!isWritable()) {
if (!handler) {
return;
} else {
do {
// on demande au Handler ce qu'on doit faire
QET::Action todo = handler -> elementIsNotWritable(this);
// on agit en fonction de la reponse du handler
if (todo == QET::Abort) {
mvt_desc -> abort();
return;
} else if (todo == QET::Ignore || todo == QET::Managed) {
return;
} else if (todo == QET::Retry || todo == QET::Erase) {
// reessayer = repasser dans la boucle
} else if (todo == QET::Rename) {
// cas non gere
}
} while (!isWritable());
}
}
// supprime cet element (sinon il ne s'agirait que d'une copie, pas d'un deplacement)
bool element_deletion = remove();
mvt_desc -> setSourceItemDeleted(element_deletion);
if (!element_deletion && handler) {
handler -> errorWithAnElement(this, tr("La suppression de cet \351l\351ment a \351chou\351."));
}
}
/**
Cette methode n'a aucun effet
@return toujours true
*/
bool ElementDefinition::removeContent() {
return(true);
}