mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-12-17 20:50:34 +01:00
Rapatriement de la branche 0.2 dans le trunk
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@558 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
495
sources/fileelementscategory.cpp
Normal file
495
sources/fileelementscategory.cpp
Normal file
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
Copyright 2006-2009 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 "fileelementscategory.h"
|
||||
#include "fileelementscollection.h"
|
||||
#include "fileelementdefinition.h"
|
||||
/**
|
||||
Constructeur
|
||||
@param path Chemin du dossier de la categorie
|
||||
@param parent Categorie parente
|
||||
@param coll Collection parente
|
||||
*/
|
||||
FileElementsCategory::FileElementsCategory(const QString &path, FileElementsCategory *parent, FileElementsCollection *coll) :
|
||||
ElementsCategory(parent, coll),
|
||||
file_parent_collection_(coll),
|
||||
file_parent_category_(parent),
|
||||
cat_dir(path)
|
||||
{
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
FileElementsCategory::~FileElementsCategory() {
|
||||
deleteContent();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom de la categorie utilisable dans un chemin (virtuel ou reel)
|
||||
*/
|
||||
QString FileElementsCategory::pathName() const {
|
||||
return(cat_dir.dirName());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le chemin virtuel de la categorie, sans le protocole
|
||||
*/
|
||||
QString FileElementsCategory::virtualPath() {
|
||||
|
||||
// il n'est pas possible d'avoir un chemin virtuel sans appartenir a une collection
|
||||
if (!hasParentCollection()) return(QString());
|
||||
|
||||
// recupere le chemin absolu de la racine de la collection
|
||||
QString root_abs_path(parentCollection() -> filePath());
|
||||
if (!filePath().startsWith(root_abs_path)) return(QString());
|
||||
|
||||
QString virtual_path(filePath());
|
||||
virtual_path.remove(root_abs_path);
|
||||
virtual_path.remove(QRegExp("^/"));
|
||||
return(virtual_path);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si la categorie possede un chemin sur un systeme de fichiers
|
||||
*/
|
||||
bool FileElementsCategory::hasFilePath() {
|
||||
return(!filePath().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le chemin sur le systeme de fichiers de la categorie
|
||||
*/
|
||||
QString FileElementsCategory::filePath() {
|
||||
return(cat_dir.path());
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le chemin du dossier representant la categorie
|
||||
@param p nouveau chemin du dossier representant la categorie
|
||||
*/
|
||||
void FileElementsCategory::setFilePath(const QString &p) {
|
||||
cat_dir.setPath(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des sous-categories de la categorie
|
||||
*/
|
||||
QList<ElementsCategory *> FileElementsCategory::categories() {
|
||||
QList<ElementsCategory *> result;
|
||||
|
||||
QList<QString> keys(categories_.keys());
|
||||
qSort(keys.begin(), keys.end());
|
||||
foreach(QString key, keys) result << categories_[key];
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la categorie correspondant au chemin virtuel cat_path, ou 0 en cas d'echec
|
||||
@param cat_path Chemin virtuel de la categorie voulue
|
||||
*/
|
||||
ElementsCategory *FileElementsCategory::category(const QString &cat_path) {
|
||||
// recupere les differentes parties du chemin
|
||||
QString cat_path_(cat_path);
|
||||
QStringList path_parts = cat_path_.split(QChar('/'), QString::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
|
||||
if (!path_parts.count()) {
|
||||
return(this);
|
||||
} else {
|
||||
// a-t-on la premiere sous-categorie ?
|
||||
if (!categories_.contains(path_parts.first())) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// on a la premiere sous-categorie
|
||||
ElementsCategory *first_sub_cat = categories_.value(path_parts.first());
|
||||
|
||||
if (path_parts.count() == 1) return(first_sub_cat);
|
||||
|
||||
// on demande a la premiere sous-categorie de fournir la categorie finale
|
||||
path_parts.removeFirst();
|
||||
return(first_sub_cat -> category(path_parts.join("/")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Cree une categorie. La categorie parente doit exister.
|
||||
@param path chemin d'une categorie a creer sous la forme d'une adresse
|
||||
virtuelle comme common://cat1/cat2/cat3
|
||||
@return la nouvelle categorie demandee, ou 0 en cas d'echec
|
||||
*/
|
||||
ElementsCategory *FileElementsCategory::createCategory(const QString &path) {
|
||||
// on ne doit pas etre en lecture seule
|
||||
if (!isWritable()) return(0);
|
||||
|
||||
// recupere les differentes parties du chemin
|
||||
QString cat_path_(path);
|
||||
QStringList path_parts = cat_path_.split(QChar('/'), QString::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
|
||||
if (!path_parts.count()) {
|
||||
// le chemin est vide, on renvoie 0
|
||||
return(0);
|
||||
} else if (path_parts.count() == 1) {
|
||||
// il n'y a plus qu'une categorie dans le chemin : il faut la creer ici
|
||||
|
||||
// on verifie si la categorie n'existe pas deja
|
||||
if (categories_.contains(path_parts[0])) {
|
||||
return(categories_.value(path_parts[0]));
|
||||
}
|
||||
|
||||
// on cree un objet
|
||||
FileElementsCategory *new_category = new FileElementsCategory(
|
||||
cat_dir.absolutePath() + "/" + path_parts[0],
|
||||
this,
|
||||
file_parent_collection_
|
||||
);
|
||||
|
||||
// on l'integre dans la liste des sous-categories connues
|
||||
categories_.insert(path_parts[0], new_category);
|
||||
|
||||
// on le renvoie
|
||||
return(new_category);
|
||||
} else {
|
||||
// il y a plusieurs categories dans le chemin :
|
||||
// on delegue le travail a la premiere sous-categorie
|
||||
|
||||
// a-t-on la premiere sous-categorie ?
|
||||
if (!categories_.contains(path_parts.first())) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// on a la premiere sous-categorie
|
||||
ElementsCategory *first_sub_cat = categories_.value(path_parts.first());
|
||||
|
||||
// on demande a la premiere sous-categorie de fournir la categorie finale
|
||||
path_parts.removeFirst();
|
||||
return(first_sub_cat -> category(path_parts.join("/")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des elements de la categorie
|
||||
*/
|
||||
QList<ElementDefinition *> FileElementsCategory::elements() {
|
||||
QList<ElementDefinition *> result;
|
||||
|
||||
QList<QString> keys(elements_.keys());
|
||||
qSort(keys.begin(), keys.end());
|
||||
foreach(QString key, keys) result << elements_[key];
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'element correspondant au chemin virtuel elmt_path, ou 0 en cas d'echec
|
||||
@param cat_path Chemin virtuel de l'element voulu
|
||||
*/
|
||||
ElementDefinition *FileElementsCategory::element(const QString &elmt_path) {
|
||||
// recupere les differentes parties du chemin
|
||||
QString elmt_path_(elmt_path);
|
||||
QStringList path_parts = elmt_path_.split(QChar('/'), QString::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
|
||||
if (!path_parts.count()) {
|
||||
// chemin vide
|
||||
return(0);
|
||||
} else if (path_parts.count() == 1) {
|
||||
// seulement le nom de fichier
|
||||
QString element_filename = path_parts.takeLast();
|
||||
if (!elements_.contains(element_filename)) {
|
||||
return(0);
|
||||
} else {
|
||||
return(elements_.value(element_filename));
|
||||
}
|
||||
} else {
|
||||
// separe le nom de fichier du chemin de la categorie et recupere celle-ci
|
||||
QString element_filename = path_parts.takeLast();
|
||||
ElementsCategory *elmt_cat = category(path_parts.join("/"));
|
||||
if (!elmt_cat) {
|
||||
return(0);
|
||||
} else {
|
||||
return(elmt_cat -> element(element_filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Cree un element. La categorie parente doit exister.
|
||||
@param path chemin d'un element a creer sous la forme d'une adresse
|
||||
virtuelle comme common://cat1/cat2/cat3/dog.elmt
|
||||
@return le nouvel element demande, ou 0 en cas d'echec
|
||||
*/
|
||||
ElementDefinition *FileElementsCategory::createElement(const QString &path) {
|
||||
// on ne doit pas etre en lecture seule
|
||||
if (!isWritable()) return(0);
|
||||
|
||||
// recupere les differentes parties du chemin
|
||||
QString cat_path_(path);
|
||||
QStringList path_parts = cat_path_.split(QChar('/'), QString::SkipEmptyParts, Qt::CaseInsensitive);
|
||||
|
||||
if (!path_parts.count()) {
|
||||
// le chemin est vide, on renvoie 0
|
||||
return(0);
|
||||
} else if (path_parts.count() == 1) {
|
||||
// il n'y a plus que l'element dans le chemin : il faut le creer ici
|
||||
|
||||
// on verifie si l'element n'existe pas deja
|
||||
if (elements_.contains(path_parts[0])) {
|
||||
return(elements_.value(path_parts[0]));
|
||||
}
|
||||
|
||||
// on cree un objet
|
||||
FileElementDefinition *new_element = new FileElementDefinition(
|
||||
cat_dir.absolutePath() + "/" + path_parts[0],
|
||||
this,
|
||||
file_parent_collection_
|
||||
);
|
||||
|
||||
// on l'integre dans la liste des elements connus
|
||||
elements_.insert(path_parts[0], new_element);
|
||||
|
||||
// on le renvoie
|
||||
return(new_element);
|
||||
} else {
|
||||
// il y a plusieurs categories dans le chemin :
|
||||
// on delegue le travail a la premiere sous-categorie
|
||||
|
||||
// a-t-on la premiere sous-categorie ?
|
||||
if (!categories_.contains(path_parts.first())) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
// on a la premiere sous-categorie
|
||||
ElementsCategory *first_sub_cat = categories_.value(path_parts.first());
|
||||
|
||||
// on demande a la premiere sous-categorie de fournir la categorie finale
|
||||
path_parts.removeFirst();
|
||||
return(first_sub_cat -> createElement(path_parts.join("/")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le dossier representant la categorie existe
|
||||
*/
|
||||
bool FileElementsCategory::exists() {
|
||||
return(cat_dir.exists());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si la categorie est accessible en lecture
|
||||
Cett methode retourne true a partir du moment ou le dossier representant
|
||||
cette categorie est accessible en lecture. Il se peut que les elements ou
|
||||
le fichier qet_directory a l'interieur ne soient pas accessibles en
|
||||
ecriture.
|
||||
*/
|
||||
bool FileElementsCategory::isReadable() {
|
||||
return(QFileInfo(cat_dir.absolutePath()).isReadable());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true s'il est possible d'ecrire le fichier qet_directory dans la
|
||||
categorie
|
||||
*/
|
||||
bool FileElementsCategory::isWritable() {
|
||||
// informations sur le dossier de la categorie
|
||||
QFileInfo category(cat_dir.absolutePath());
|
||||
QFileInfo qet_directory(cat_dir.absolutePath() + "/qet_directory");
|
||||
/*
|
||||
soit qet_directory n'existe pas et le dossier est accessible en ecriture,
|
||||
soit qet_directory existe et est accessible en ecriture
|
||||
*/
|
||||
return(
|
||||
category.isWritable() && // le dossier lui-meme est accessible en ecriture
|
||||
(
|
||||
!qet_directory.exists() ||
|
||||
(qet_directory.exists() && qet_directory.isWritable())
|
||||
) // le fichier qet_directory est accessible en ecriture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Recharge le contenu et les noms de la categorie
|
||||
*/
|
||||
void FileElementsCategory::reload() {
|
||||
// supprime l'ancien contenu
|
||||
deleteContent();
|
||||
category_names.clearNames();
|
||||
|
||||
// la categorie doit exister
|
||||
if (!cat_dir.exists()) return;
|
||||
|
||||
// charge les noms de la categorie
|
||||
loadNames();
|
||||
|
||||
// charge les sous-categories
|
||||
QStringList dirs = cat_dir.entryList(QStringList(), QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::Name);
|
||||
foreach(QString dir, dirs) {
|
||||
categories_.insert(dir, new FileElementsCategory(cat_dir.absoluteFilePath(dir), this, file_parent_collection_));
|
||||
}
|
||||
|
||||
// charge les elements
|
||||
QStringList elmts = cat_dir.entryList(QStringList("*.elmt"), QDir::Files, QDir::Name);
|
||||
foreach(QString elmt, elmts) {
|
||||
elements_.insert(elmt, new FileElementDefinition(cat_dir.absoluteFilePath(elmt), this, file_parent_collection_));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime le contenu de la categorie puis la categorie elle-meme
|
||||
@return true si l'operation s'est bien passee, false sinon
|
||||
*/
|
||||
bool FileElementsCategory::remove() {
|
||||
// suppression du contenu de la categorie
|
||||
if (!removeContent()) return(false);
|
||||
|
||||
// une categorie racine ne se supprime pas elle-meme
|
||||
if (isRootCategory()) return(true);
|
||||
|
||||
// suppression du fichier de description de la categorie
|
||||
if (cat_dir.exists("qet_directory")) {
|
||||
if (!cat_dir.remove("qet_directory")) return(false);
|
||||
}
|
||||
|
||||
// suppression de la categorie elle-meme
|
||||
return(cat_dir.rmdir(cat_dir.absolutePath()));
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime le contenu de la categorie sans supprimer la categorie elle-meme.
|
||||
@return true si l'operation s'est bien passee, false sinon
|
||||
*/
|
||||
bool FileElementsCategory::removeContent() {
|
||||
// suppression des sous-categories
|
||||
foreach(QString cat_name, categories_.keys()) {
|
||||
ElementsCategory *cat = categories_.value(cat_name);
|
||||
if (cat -> remove()) {
|
||||
categories_.take(cat_name);
|
||||
delete cat;
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
// suppression des elements
|
||||
foreach(QString elmt_name, elements_.keys()) {
|
||||
ElementDefinition *elmt = elements_.value(elmt_name);
|
||||
if (elmt -> remove()) {
|
||||
elements_.take(elmt_name);
|
||||
delete elmt;
|
||||
} else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Cree la categorie
|
||||
@return true si la creation a reussi, false sinon
|
||||
*/
|
||||
bool FileElementsCategory::write() {
|
||||
// cree le dossier de la categorie
|
||||
if (!cat_dir.mkpath(cat_dir.path())) return(false);
|
||||
|
||||
// prepare la structure XML
|
||||
QDomDocument document;
|
||||
QDomElement root = document.createElement("qet-directory");
|
||||
document.appendChild(root);
|
||||
root.appendChild(category_names.toXml(document));
|
||||
|
||||
// repere le chemin du fichier de configuration de la categorie
|
||||
QFile directory_conf(cat_dir.absolutePath() + "/qet_directory");
|
||||
|
||||
// ouvre le fichier
|
||||
if (!directory_conf.open(QIODevice::Text | QIODevice::WriteOnly)) return(false);
|
||||
|
||||
// ecrit le fichier
|
||||
QTextStream out(&directory_conf);
|
||||
out.setCodec("UTF-8");
|
||||
out << document.toString(4);
|
||||
|
||||
// ferme le fichier
|
||||
directory_conf.close();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime un repertoire recursivement.
|
||||
@return true si la suppression a reussie, false sinon
|
||||
*/
|
||||
bool FileElementsCategory::rmdir(const QString &path) const {
|
||||
QDir directory(path);
|
||||
|
||||
// supprime les dossiers, recursivement
|
||||
foreach (QString file, directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
|
||||
if (!rmdir(directory.absolutePath() + "/" + file)) return(false);
|
||||
}
|
||||
|
||||
// supprime les fichiers
|
||||
foreach (QString file, directory.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
|
||||
if (!directory.remove(file)) return(false);
|
||||
}
|
||||
|
||||
// supprime le dossier lui-meme
|
||||
return(directory.rmdir(path));
|
||||
}
|
||||
|
||||
/**
|
||||
Charge la liste des noms possibles pour la categorie
|
||||
*/
|
||||
void FileElementsCategory::loadNames() {
|
||||
// repere le chemin du fichier de configuration de la categorie
|
||||
QFile directory_conf(cat_dir.absolutePath() + "/qet_directory");
|
||||
|
||||
// verifie l'existence du fichier
|
||||
if (!directory_conf.exists()) return;
|
||||
|
||||
// ouvre le fichier
|
||||
if (!directory_conf.open(QIODevice::ReadOnly | QIODevice::Text)) return;
|
||||
|
||||
// lit le contenu du fichier dans un QDomDocument XML
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&directory_conf)) return;
|
||||
|
||||
// verifie la racine
|
||||
QDomElement root = document.documentElement();
|
||||
if (root.tagName() != "qet-directory") return;
|
||||
|
||||
category_names.fromXml(root);
|
||||
|
||||
// ferme le fichier
|
||||
directory_conf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime le contenu de la categorie en memoire
|
||||
*/
|
||||
void FileElementsCategory::deleteContent() {
|
||||
// suppression des elements
|
||||
foreach(QString elmt_name, elements_.keys()) {
|
||||
FileElementDefinition *elmt = elements_.take(elmt_name);
|
||||
delete elmt;
|
||||
}
|
||||
|
||||
// suppression des categories
|
||||
foreach(QString cat_name, categories_.keys()) {
|
||||
FileElementsCategory *cat = categories_.take(cat_name);
|
||||
delete cat;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user