mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-01-07 14:12:33 +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:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -16,6 +16,7 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <QtGui>
|
||||
#include "qettabwidget.h"
|
||||
#include "aboutqet.h"
|
||||
#include "qet.h"
|
||||
|
||||
@@ -25,16 +26,16 @@
|
||||
*/
|
||||
AboutQET::AboutQET(QWidget *parent) : QDialog(parent) {
|
||||
// Titre, taille, comportement...
|
||||
setWindowTitle(tr("\300 propos de QElectrotech"));
|
||||
setWindowTitle(tr("\300 propos de QElectrotech", "window title"));
|
||||
setMinimumWidth(680);
|
||||
setMinimumHeight(350);
|
||||
setModal(true);
|
||||
|
||||
// Trois onglets
|
||||
QTabWidget *onglets = new QTabWidget(this);
|
||||
onglets -> addTab(ongletAPropos(), tr("\300 &propos"));
|
||||
onglets -> addTab(ongletAuteurs(), tr("A&uteurs"));
|
||||
onglets -> addTab(ongletLicence(), tr("&Accord de licence"));
|
||||
QETTabWidget *onglets = new QETTabWidget(this);
|
||||
onglets -> addTab(ongletAPropos(), tr("\300 &propos","tab title"));
|
||||
onglets -> addTab(ongletAuteurs(), tr("A&uteurs", "tab title"));
|
||||
onglets -> addTab(ongletLicence(), tr("&Accord de licence", "tab title"));
|
||||
|
||||
// Un bouton pour fermer la boite de dialogue
|
||||
QDialogButtonBox *boutons = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
@@ -64,7 +65,7 @@ QWidget *AboutQET::titre() const {
|
||||
QLabel *icone = new QLabel();
|
||||
icone -> setPixmap(QIcon(":/ico/qelectrotech.png").pixmap(48, 48));
|
||||
// label "QElectroTech"
|
||||
QLabel *titre = new QLabel("<span style=\"font-weight:0;font-size:16pt;\">QElectroTech v" + QET::version + "</span>");
|
||||
QLabel *titre = new QLabel("<span style=\"font-weight:0;font-size:16pt;\">QElectroTech v" + QET::displayedVersion + "</span>");
|
||||
titre -> setTextFormat(Qt::RichText);
|
||||
// le tout dans une grille
|
||||
QGridLayout *dispo_horiz = new QGridLayout();
|
||||
@@ -83,10 +84,10 @@ QWidget *AboutQET::ongletAPropos() const {
|
||||
QLabel *apropos = new QLabel(
|
||||
tr("QElectroTech, une application de r\351alisation de sch\351mas \351lectriques.") +
|
||||
"<br><br>" +
|
||||
tr("\251 2006-2008 Les d\351veloppeurs de QElectroTech") +
|
||||
tr("\251 2006-2009 Les d\351veloppeurs de QElectroTech") +
|
||||
"<br><br>"
|
||||
"<a href=\"http://qelectrotech.tuxfamily.org/\">"
|
||||
"http://qelectrotech.tuxfamily.org/</a>"
|
||||
"<a href=\"http://qelectrotech.org/\">"
|
||||
"http://qelectrotech.org/</a>"
|
||||
);
|
||||
apropos -> setAlignment(Qt::AlignCenter);
|
||||
apropos -> setOpenExternalLinks(true);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
126
sources/basicmoveelementshandler.cpp
Normal file
126
sources/basicmoveelementshandler.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "basicmoveelementshandler.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QObject parent
|
||||
*/
|
||||
BasicMoveElementsHandler::BasicMoveElementsHandler(QObject *parent) :
|
||||
MoveElementsHandler(parent),
|
||||
already_exists_(QET::Erase),
|
||||
not_readable_(QET::Ignore),
|
||||
not_writable_(QET::Ignore),
|
||||
error_(QET::Ignore),
|
||||
rename_("renamed")
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
BasicMoveElementsHandler::~BasicMoveElementsHandler() {
|
||||
}
|
||||
|
||||
/**
|
||||
@param action Action a renvoyer si un item existe deja
|
||||
*/
|
||||
void BasicMoveElementsHandler::setActionIfItemAlreadyExists(QET::Action action) {
|
||||
already_exists_ = action;
|
||||
}
|
||||
|
||||
/**
|
||||
@param action Action a renvoyer si un item n'est pas lisible
|
||||
*/
|
||||
void BasicMoveElementsHandler::setActionIfItemIsNotReadable(QET::Action action) {
|
||||
not_readable_ = action;
|
||||
}
|
||||
|
||||
/**
|
||||
@param action Action a renvoyer si un item n'est pas accessible en ecriture
|
||||
*/
|
||||
void BasicMoveElementsHandler::setActionIfItemIsNotWritable(QET::Action action) {
|
||||
not_writable_ = action;
|
||||
}
|
||||
|
||||
/**
|
||||
@param action Action a renvoyer si un item provoque une erreur
|
||||
*/
|
||||
void BasicMoveElementsHandler::setActionIfItemTriggersAnError(QET::Action action) {
|
||||
error_ = action;
|
||||
}
|
||||
|
||||
/**
|
||||
@param name Nom a renvoyer pour une eventuelle operation de renommage
|
||||
Il est toutefois deconseille de proceder a un renommage systematique, vu que
|
||||
cette propriete est invariable.
|
||||
*/
|
||||
void BasicMoveElementsHandler::setNameForRenamingOperation(const QString &name) {
|
||||
rename_ = name;
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si la categorie cible existe deja
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::categoryAlreadyExists(ElementsCategory *, ElementsCategory *) {
|
||||
return(already_exists_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si l'element cible existe deja
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::elementAlreadyExists(ElementDefinition *, ElementDefinition *) {
|
||||
return(already_exists_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si la categorie existe deja
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::categoryIsNotReadable(ElementsCategory *) {
|
||||
return(not_readable_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si l'element existe deja
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::elementIsNotReadable(ElementDefinition *) {
|
||||
return(not_readable_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si la categorie cible n'est pas accessible
|
||||
en ecriture
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::categoryIsNotWritable(ElementsCategory *) {
|
||||
return(not_writable_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer si l'element cible n'est pas accessible
|
||||
en ecriture
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::elementIsNotWritable(ElementDefinition *) {
|
||||
return(not_writable_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer lorsque l'erreur decrite dans la QString
|
||||
s'est produite avec la categorie indiquee
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::errorWithACategory(ElementsCategory *, const QString &) {
|
||||
return(error_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'action a effectuer lorsque l'erreur decrite dans la QString
|
||||
s'est produite avec l'element indique
|
||||
*/
|
||||
QET::Action BasicMoveElementsHandler::errorWithAnElement(ElementDefinition *, const QString &) {
|
||||
return(error_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom a utiliser pour le renommage si une methode de cet objet
|
||||
a precedemment renvoye QET::Rename.
|
||||
*/
|
||||
QString BasicMoveElementsHandler::nameForRenamingOperation() {
|
||||
return(rename_);
|
||||
}
|
||||
62
sources/basicmoveelementshandler.h
Normal file
62
sources/basicmoveelementshandler.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef BASIC_MOVE_ELEMENTS_HANDLER
|
||||
#define BASIC_MOVE_ELEMENTS_HANDLER
|
||||
#include "moveelementshandler.h"
|
||||
/**
|
||||
Cette classe implemente basiquement la classe strategie MoveElementsHandler
|
||||
Elle retourne toujours la meme action (parametrable) pour une methode
|
||||
donnee.
|
||||
*/
|
||||
class BasicMoveElementsHandler : public MoveElementsHandler {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
BasicMoveElementsHandler(QObject * = 0);
|
||||
virtual ~BasicMoveElementsHandler();
|
||||
private:
|
||||
BasicMoveElementsHandler(const BasicMoveElementsHandler &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void setActionIfItemAlreadyExists(QET::Action);
|
||||
virtual void setActionIfItemIsNotReadable(QET::Action);
|
||||
virtual void setActionIfItemIsNotWritable(QET::Action);
|
||||
virtual void setActionIfItemTriggersAnError(QET::Action);
|
||||
virtual void setNameForRenamingOperation(const QString &);
|
||||
|
||||
virtual QET::Action categoryAlreadyExists(ElementsCategory *src, ElementsCategory *dst);
|
||||
virtual QET::Action elementAlreadyExists(ElementDefinition *src, ElementDefinition *dst);
|
||||
virtual QET::Action categoryIsNotReadable(ElementsCategory *);
|
||||
virtual QET::Action elementIsNotReadable(ElementDefinition *);
|
||||
virtual QET::Action categoryIsNotWritable(ElementsCategory *);
|
||||
virtual QET::Action elementIsNotWritable(ElementDefinition *);
|
||||
virtual QET::Action errorWithACategory(ElementsCategory *, const QString &);
|
||||
virtual QET::Action errorWithAnElement(ElementDefinition *, const QString &);
|
||||
virtual QString nameForRenamingOperation();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QET::Action already_exists_;
|
||||
QET::Action not_readable_;
|
||||
QET::Action not_writable_;
|
||||
QET::Action error_;
|
||||
QString rename_;
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <QPainter>
|
||||
#include "borderinset.h"
|
||||
#include "qetapp.h"
|
||||
#include "qetdiagrameditor.h"
|
||||
#include "math.h"
|
||||
|
||||
/**
|
||||
@@ -28,16 +27,17 @@
|
||||
*/
|
||||
BorderInset::BorderInset(QObject *parent) : QObject(parent) {
|
||||
// dimensions par defaut du schema
|
||||
importBorder(QETDiagramEditor::defaultBorderProperties());
|
||||
importBorder(BorderProperties());
|
||||
|
||||
// contenu par defaut du cartouche
|
||||
importInset(QETDiagramEditor::defaultInsetProperties());
|
||||
importInset(InsetProperties());
|
||||
|
||||
// hauteur du cartouche
|
||||
inset_height = 50.0;
|
||||
|
||||
display_inset = true;
|
||||
display_border = true;
|
||||
setFolioData(1, 1);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
@@ -94,9 +94,10 @@ InsetProperties BorderInset::exportInset() {
|
||||
void BorderInset::importInset(const InsetProperties &ip) {
|
||||
bi_author = ip.author;
|
||||
bi_date = ip.date;
|
||||
bi_title = ip.title;
|
||||
setTitle(ip.title);
|
||||
bi_folio = ip.folio;
|
||||
bi_filename = ip.filename;
|
||||
emit(needFolioData());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,6 +159,8 @@ void BorderInset::displayRows(bool dr) {
|
||||
|
||||
/**
|
||||
@param db true pour afficher la bordure du schema, false sinon
|
||||
Note : si l'affichage de la bordure est ainsi desactivee, les lignes et
|
||||
colonnes ne seront pas dessinees.
|
||||
*/
|
||||
void BorderInset::displayBorder(bool db) {
|
||||
bool change = (db != display_border);
|
||||
@@ -208,10 +211,10 @@ void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
|
||||
// dessine le cadre
|
||||
if (display_border) qp -> drawRect(diagram);
|
||||
|
||||
qp -> setFont(QFont(QETApp::diagramTextsFont(), qp -> font().pointSize()));
|
||||
qp -> setFont(QFont(QETApp::diagramTextsFont(), QETApp::diagramTextsSize()));
|
||||
|
||||
// dessine la case vide qui apparait des qu'il y a un entete
|
||||
if (display_columns || display_rows) {
|
||||
if (display_border && (display_columns || display_rows)) {
|
||||
qp -> setBrush(Qt::white);
|
||||
QRectF first_rectangle(
|
||||
diagram.topLeft().x(),
|
||||
@@ -223,7 +226,7 @@ void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
|
||||
}
|
||||
|
||||
// dessine la numerotation des colonnes
|
||||
if (display_columns) {
|
||||
if (display_border && display_columns) {
|
||||
for (int i = 1 ; i <= nb_columns ; ++ i) {
|
||||
QRectF numbered_rectangle = QRectF(
|
||||
diagram.topLeft().x() + (rows_header_width + ((i - 1) * columns_width)),
|
||||
@@ -237,7 +240,7 @@ void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
|
||||
}
|
||||
|
||||
// dessine la numerotation des lignes
|
||||
if (display_rows) {
|
||||
if (display_border && display_rows) {
|
||||
QString row_string("A");
|
||||
for (int i = 1 ; i <= nb_rows ; ++ i) {
|
||||
QRectF lettered_rectangle = QRectF(
|
||||
@@ -258,19 +261,19 @@ void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
|
||||
qp -> drawRect(inset);
|
||||
|
||||
qp -> drawRect(inset_author);
|
||||
qp -> drawText(inset_author, Qt::AlignVCenter | Qt::AlignLeft, tr(" Auteur : ") + bi_author);
|
||||
qp -> drawText(inset_author, Qt::AlignVCenter | Qt::AlignLeft, QString(tr(" Auteur : %1", "inset content")).arg(bi_author));
|
||||
|
||||
qp -> drawRect(inset_date);
|
||||
qp -> drawText(inset_date, Qt::AlignVCenter | Qt::AlignLeft, tr(" Date : ") + bi_date.toString("dd/MM/yyyy"));
|
||||
qp -> drawText(inset_date, Qt::AlignVCenter | Qt::AlignLeft, QString(tr(" Date : %1", "inset content")).arg(bi_date.toString("dd/MM/yyyy")));
|
||||
|
||||
qp -> drawRect(inset_title);
|
||||
qp -> drawText(inset_title, Qt::AlignVCenter | Qt::AlignCenter, tr("Titre du document : ") + bi_title);
|
||||
qp -> drawText(inset_title, Qt::AlignVCenter | Qt::AlignCenter, QString(tr("Titre du document : %1", "inset content")).arg(bi_title));
|
||||
|
||||
qp -> drawRect(inset_file);
|
||||
qp -> drawText(inset_file, Qt::AlignVCenter | Qt::AlignLeft, tr(" Fichier : ") + bi_filename);
|
||||
qp -> drawText(inset_file, Qt::AlignVCenter | Qt::AlignLeft, QString(tr(" Fichier : %1", "inset content")).arg(bi_filename));
|
||||
|
||||
qp -> drawRect(inset_folio);
|
||||
qp -> drawText(inset_folio, Qt::AlignVCenter | Qt::AlignLeft, tr(" Folio : ") + bi_folio);
|
||||
qp -> drawText(inset_folio, Qt::AlignVCenter | Qt::AlignLeft, QString(tr(" Folio : %1", "inset content")).arg(bi_final_folio));
|
||||
}
|
||||
|
||||
qp -> restore();
|
||||
@@ -439,3 +442,20 @@ QString BorderInset::incrementLetters(const QString &string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param index numero du schema (de 1 a total)
|
||||
@param total nombre total de schemas dans le projet
|
||||
*/
|
||||
void BorderInset::setFolioData(int index, int total) {
|
||||
if (index < 1 || total < 1 || index > total) return;
|
||||
|
||||
// memorise les informations
|
||||
folio_index_ = index;
|
||||
folio_total_ = total;
|
||||
|
||||
// regenere le contenu du champ folio
|
||||
bi_final_folio = bi_folio;
|
||||
bi_final_folio.replace("%id", QString::number(folio_index_));
|
||||
bi_final_folio.replace("%total", QString::number(folio_total_));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -130,9 +130,15 @@ class BorderInset : public QObject {
|
||||
/// @param date le nouveau contenu du champ "Date"
|
||||
void setDate (const QDate &date) { bi_date = date; }
|
||||
/// @param title le nouveau contenu du champ "Titre"
|
||||
void setTitle (const QString &title) { bi_title = title; }
|
||||
void setTitle (const QString &title) {
|
||||
if (bi_title != title) {
|
||||
bi_title = title;
|
||||
emit(diagramTitleChanged(title));
|
||||
}
|
||||
}
|
||||
/// @param folio le nouveau contenu du champ "Folio"
|
||||
void setFolio (const QString &folio) { bi_folio = folio; }
|
||||
void setFolioData(int, int);
|
||||
/// @param filename le nouveau contenu du champ "Fichier"
|
||||
void setFileName (const QString &filename) { bi_filename = filename; }
|
||||
|
||||
@@ -164,6 +170,17 @@ class BorderInset : public QObject {
|
||||
*/
|
||||
void displayChanged();
|
||||
|
||||
/**
|
||||
Signal emis lorsque le titre du schema change
|
||||
*/
|
||||
void diagramTitleChanged(const QString &);
|
||||
|
||||
/**
|
||||
Signal emis lorsque le cartouche requiert une mise a jour des donnees
|
||||
utilisees pour generer le folio.
|
||||
*/
|
||||
void needFolioData();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
// informations du cartouche
|
||||
@@ -171,6 +188,9 @@ class BorderInset : public QObject {
|
||||
QDate bi_date;
|
||||
QString bi_title;
|
||||
QString bi_folio;
|
||||
QString bi_final_folio;
|
||||
int folio_index_;
|
||||
int folio_total_;
|
||||
QString bi_filename;
|
||||
|
||||
// dimensions du cadre (lignes et colonnes)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,9 +18,21 @@
|
||||
#include "borderproperties.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
Constructeur. Initialise un objet BorderProperties avec les proprietes par
|
||||
defaut suivantes :
|
||||
* 17 colonnes affichees de 60.0 px de large pour 20.0px de haut
|
||||
* 8 lignes affichees de 80.0 px de haut pour 20.0px de large
|
||||
*/
|
||||
BorderProperties::BorderProperties() {
|
||||
BorderProperties::BorderProperties() :
|
||||
columns_count(17),
|
||||
columns_width(60.0),
|
||||
columns_header_height(20.0),
|
||||
display_columns(true),
|
||||
rows_count(8),
|
||||
rows_height(80.0),
|
||||
rows_header_width(20.0),
|
||||
display_rows(true)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,3 +65,58 @@ bool BorderProperties::operator==(const BorderProperties &bp) {
|
||||
bool BorderProperties::operator!=(const BorderProperties &bp) {
|
||||
return(!(*this == bp));
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte les dimensions sous formes d'attributs XML ajoutes a l'element e.
|
||||
@param e Element XML auquel seront ajoutes des attributs
|
||||
*/
|
||||
void BorderProperties::toXml(QDomElement &e) const {
|
||||
e.setAttribute("cols", columns_count);
|
||||
e.setAttribute("colsize", QString("%1").arg(columns_width));
|
||||
e.setAttribute("rows", rows_count);
|
||||
e.setAttribute("rowsize", QString("%1").arg(rows_height));
|
||||
e.setAttribute("displaycols", display_columns ? "true" : "false");
|
||||
e.setAttribute("displayrows", display_rows ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les dimensions a partir des attributs XML de l'element e
|
||||
@param e Element XML dont les attributs seront lus
|
||||
*/
|
||||
void BorderProperties::fromXml(QDomElement &e) {
|
||||
if (e.hasAttribute("cols")) columns_count = e.attribute("cols").toInt();
|
||||
if (e.hasAttribute("colsize")) columns_width = e.attribute("colsize").toInt();
|
||||
if (e.hasAttribute("rows")) rows_count = e.attribute("rows").toInt();
|
||||
if (e.hasAttribute("rowsize")) rows_height = e.attribute("rowsize").toInt();
|
||||
if (e.hasAttribute("displaycols")) display_columns = e.attribute("displaycols") == "true";
|
||||
if (e.hasAttribute("displayrows")) display_rows = e.attribute("displayrows") == "true";
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte les dimensions dans une configuration.
|
||||
@param settings Parametres a ecrire
|
||||
@param prefix prefixe a ajouter devant les noms des parametres
|
||||
*/
|
||||
void BorderProperties::toSettings(QSettings &settings, const QString &prefix) const {
|
||||
settings.setValue(prefix + "cols", columns_count);
|
||||
settings.setValue(prefix + "colsize", columns_width);
|
||||
settings.setValue(prefix + "displaycols", display_columns);
|
||||
settings.setValue(prefix + "rows", rows_count);
|
||||
settings.setValue(prefix + "rowsize", rows_height);
|
||||
settings.setValue(prefix + "displayrows", display_rows);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les dimensions depuis une configuration.
|
||||
@param settings Parametres a lire
|
||||
@param prefix prefixe a ajouter devant les noms des parametres
|
||||
*/
|
||||
void BorderProperties::fromSettings(QSettings &settings, const QString &prefix) {
|
||||
columns_count = settings.value(prefix + "cols", columns_count).toInt();
|
||||
columns_width = qRound(settings.value(prefix + "colsize", columns_width).toDouble());
|
||||
display_columns = settings.value(prefix + "displaycols", display_columns).toBool();
|
||||
|
||||
rows_count = settings.value(prefix + "rows", rows_count).toInt();
|
||||
rows_height = qRound(settings.value(prefix + "rowsize", rows_height).toDouble());
|
||||
display_rows = settings.value(prefix + "displayrows", display_rows).toBool();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,6 +18,7 @@
|
||||
#ifndef BORDER_PROPERTIES_H
|
||||
#define BORDER_PROPERTIES_H
|
||||
#include <QtCore>
|
||||
#include <QtXml>
|
||||
/**
|
||||
Cette classe est un conteneur pour les dimensions et proprietes d'affichage
|
||||
d'un schema : affichage, nombre et dimensions des colonnes et lignes, ...
|
||||
@@ -31,6 +32,11 @@ class BorderProperties {
|
||||
bool operator==(const BorderProperties &);
|
||||
bool operator!=(const BorderProperties &);
|
||||
|
||||
void toXml(QDomElement &) const;
|
||||
void fromXml(QDomElement &);
|
||||
void toSettings(QSettings &, const QString & = QString()) const;
|
||||
void fromSettings(QSettings &, const QString & = QString());
|
||||
|
||||
// attributs
|
||||
int columns_count; ///< Nombre de colonnes
|
||||
qreal columns_width; ///< Largeur des colonnes
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -59,10 +59,10 @@ const BorderProperties &BorderPropertiesWidget::borderProperties() {
|
||||
void BorderPropertiesWidget::setEditedBorder(const BorderProperties &bp) {
|
||||
border_ = bp;
|
||||
columns_count -> setValue(border_.columns_count);
|
||||
columns_width -> setValue(border_.columns_width);
|
||||
columns_width -> setValue(qRound(border_.columns_width));
|
||||
display_columns -> setChecked(border_.display_columns);
|
||||
rows_count -> setValue(border_.rows_count);
|
||||
rows_height -> setValue(border_.rows_height);
|
||||
rows_height -> setValue(qRound(border_.rows_height));
|
||||
display_rows -> setChecked(border_.display_rows);
|
||||
}
|
||||
|
||||
@@ -85,10 +85,10 @@ void BorderPropertiesWidget::build() {
|
||||
columns_width = new QSpinBox(diagram_size_box);
|
||||
columns_width -> setMinimum(qRound(BorderInset::minColumnsWidth()));
|
||||
columns_width -> setSingleStep(10);
|
||||
columns_width -> setPrefix(tr("\327"));
|
||||
columns_width -> setSuffix(tr("px"));
|
||||
columns_width -> setPrefix(tr("\327", "multiplication symbol"));
|
||||
columns_width -> setSuffix(tr("px", "unit for cols width"));
|
||||
|
||||
display_columns = new QCheckBox(tr("Afficher les en-têtes"), diagram_size_box);
|
||||
display_columns = new QCheckBox(tr("Afficher les en-t\352tes"), diagram_size_box);
|
||||
|
||||
// lignes : nombre et largeur
|
||||
QLabel *ds2 = new QLabel(tr("Lignes :"));
|
||||
@@ -99,10 +99,10 @@ void BorderPropertiesWidget::build() {
|
||||
rows_height = new QSpinBox(diagram_size_box);
|
||||
rows_height -> setMinimum(qRound(BorderInset::minRowsHeight()));
|
||||
rows_height -> setSingleStep(10);
|
||||
rows_height -> setPrefix(tr("\327"));
|
||||
rows_height -> setSuffix(tr("px"));
|
||||
rows_height -> setPrefix(tr("\327", "multiplication symbol"));
|
||||
rows_height -> setSuffix(tr("px", "unit for rows height"));
|
||||
|
||||
display_rows = new QCheckBox(tr("Afficher les en-têtes"), diagram_size_box);
|
||||
display_rows = new QCheckBox(tr("Afficher les en-t\352tes"), diagram_size_box);
|
||||
|
||||
// layout
|
||||
diagram_size_box_layout -> addWidget(ds1, 0, 0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -937,7 +937,7 @@ QDomElement Conductor::toXml(QDomDocument &d, QHash<Terminal *, int> &table_adr_
|
||||
}
|
||||
|
||||
// exporte la "configuration" du conducteur
|
||||
properties_.toXml(d, e);
|
||||
properties_.toXml(e);
|
||||
return(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -159,19 +159,18 @@ void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentT
|
||||
}
|
||||
|
||||
/**
|
||||
exporte les parametres du conducteur unifilaire sous formes d'attributs XML
|
||||
Exporte les parametres du conducteur unifilaire sous formes d'attributs XML
|
||||
ajoutes a l'element e.
|
||||
@param d Document XML ; utilise pour ajouter (potentiellement) des elements XML
|
||||
@param e Element XML auquel seront ajoutes des attributs
|
||||
*/
|
||||
void SingleLineProperties::toXml(QDomDocument &, QDomElement &e) const {
|
||||
void SingleLineProperties::toXml(QDomElement &e) const {
|
||||
e.setAttribute("ground", hasGround ? "true" : "false");
|
||||
e.setAttribute("neutral", hasNeutral ? "true" : "false");
|
||||
e.setAttribute("phase", phases);
|
||||
}
|
||||
|
||||
/**
|
||||
importe les parametres du conducteur unifilaire a partir des attributs XML
|
||||
Importe les parametres du conducteur unifilaire a partir des attributs XML
|
||||
de l'element e
|
||||
@param e Element XML dont les attributs seront lus
|
||||
*/
|
||||
@@ -182,22 +181,21 @@ void SingleLineProperties::fromXml(QDomElement &e) {
|
||||
}
|
||||
|
||||
/**
|
||||
exporte les parametres du conducteur sous formes d'attributs XML
|
||||
Exporte les parametres du conducteur sous formes d'attributs XML
|
||||
ajoutes a l'element e.
|
||||
@param d Document XML ; utilise pour ajouter (potentiellement) des elements XML
|
||||
@param e Element XML auquel seront ajoutes des attributs
|
||||
*/
|
||||
void ConductorProperties::toXml(QDomDocument &d, QDomElement &e) const {
|
||||
void ConductorProperties::toXml(QDomElement &e) const {
|
||||
e.setAttribute("type", typeToString(type));
|
||||
if (type == Single) {
|
||||
singleLineProperties.toXml(d, e);
|
||||
singleLineProperties.toXml(e);
|
||||
} else if (type == Multi) {
|
||||
e.setAttribute("num", text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
importe les parametres du conducteur unifilaire a partir des attributs XML
|
||||
Importe les parametres du conducteur unifilaire a partir des attributs XML
|
||||
de l'element e
|
||||
@param e Element XML dont les attributs seront lus
|
||||
*/
|
||||
@@ -217,7 +215,7 @@ void ConductorProperties::fromXml(QDomElement &e) {
|
||||
|
||||
/**
|
||||
@param settings Parametres a ecrire
|
||||
@param prefix prefix a ajouter devant les noms des parametres
|
||||
@param prefix prefixe a ajouter devant les noms des parametres
|
||||
*/
|
||||
void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) const {
|
||||
settings.setValue(prefix + "type", typeToString(type));
|
||||
@@ -227,7 +225,7 @@ void ConductorProperties::toSettings(QSettings &settings, const QString &prefix)
|
||||
|
||||
/**
|
||||
@param settings Parametres a lire
|
||||
@param prefix prefix a ajouter devant les noms des parametres
|
||||
@param prefix prefixe a ajouter devant les noms des parametres
|
||||
*/
|
||||
void ConductorProperties::fromSettings(QSettings &settings, const QString &prefix) {
|
||||
QString setting_type = settings.value(prefix + "type", typeToString(Multi)).toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -31,7 +31,7 @@ class SingleLineProperties {
|
||||
void setPhasesCount(int);
|
||||
unsigned short int phasesCount();
|
||||
void draw(QPainter *, QET::ConductorSegmentType, const QRectF &);
|
||||
void toXml(QDomDocument &, QDomElement &) const;
|
||||
void toXml(QDomElement &) const;
|
||||
void fromXml(QDomElement &);
|
||||
void toSettings(QSettings &, const QString & = QString()) const;
|
||||
void fromSettings(QSettings &, const QString & = QString());
|
||||
@@ -87,7 +87,7 @@ class ConductorProperties {
|
||||
SingleLineProperties singleLineProperties;
|
||||
|
||||
// methodes
|
||||
void toXml(QDomDocument &, QDomElement &) const;
|
||||
void toXml(QDomElement &) const;
|
||||
void fromXml(QDomElement &);
|
||||
void toSettings(QSettings &, const QString & = QString()) const;
|
||||
void fromSettings(QSettings &, const QString & = QString());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,7 +19,6 @@
|
||||
#define CONDUCTOR_PROPERTIES_WIDGET_H
|
||||
#include "conductorproperties.h"
|
||||
#include <QWidget>
|
||||
|
||||
/**
|
||||
Ce widget permet a l utilisateur d'editer les proprietes d'un conducteur.
|
||||
Par proprietes, on entend non pas le trajet effectue par le conducteur mais
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -24,12 +24,12 @@
|
||||
*/
|
||||
ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
|
||||
|
||||
setWindowTitle(tr("Configurer QElectroTech"));
|
||||
setWindowTitle(tr("Configurer QElectroTech", "window title"));
|
||||
|
||||
// liste des pages
|
||||
pages_list = new QListWidget();
|
||||
pages_list -> setViewMode(QListView::IconMode);
|
||||
pages_list -> setIconSize(QSize(48, 48));
|
||||
pages_list -> setIconSize(QSize(110, 110));
|
||||
pages_list -> setMovement(QListView::Static);
|
||||
pages_list -> setMinimumWidth(135);
|
||||
pages_list -> setMaximumWidth(135);
|
||||
@@ -37,6 +37,7 @@ ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
|
||||
|
||||
// pages
|
||||
pages_widget = new QStackedWidget();
|
||||
addPage(new GeneralConfigurationPage());
|
||||
addPage(new NewDiagramPage());
|
||||
buildPagesList();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -28,10 +28,6 @@
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
NewDiagramPage::NewDiagramPage(QWidget *parent) : ConfigPage(parent) {
|
||||
|
||||
// acces a la configuration de QElectroTech
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
// dimensions par defaut d'un schema
|
||||
bpw = new BorderPropertiesWidget(QETDiagramEditor::defaultBorderProperties());
|
||||
|
||||
@@ -39,14 +35,12 @@ NewDiagramPage::NewDiagramPage(QWidget *parent) : ConfigPage(parent) {
|
||||
ipw = new InsetPropertiesWidget(QETDiagramEditor::defaultInsetProperties(), true);
|
||||
|
||||
// proprietes par defaut des conducteurs
|
||||
ConductorProperties cp;
|
||||
cp.fromSettings(settings, "diagrameditor/defaultconductor");
|
||||
cpw = new ConductorPropertiesWidget(cp);
|
||||
cpw = new ConductorPropertiesWidget(QETDiagramEditor::defaultConductorProperties());
|
||||
cpw -> setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *vlayout1 = new QVBoxLayout();
|
||||
|
||||
QLabel *title = new QLabel(tr("Nouveau sch\351ma"));
|
||||
QLabel *title = new QLabel(this -> title());
|
||||
vlayout1 -> addWidget(title);
|
||||
|
||||
QFrame *horiz_line = new QFrame();
|
||||
@@ -78,28 +72,10 @@ void NewDiagramPage::applyConf() {
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
// dimensions des nouveaux schemas
|
||||
BorderProperties border = bpw -> borderProperties();
|
||||
settings.setValue("diagrameditor/defaultcols", border.columns_count);
|
||||
settings.setValue("diagrameditor/defaultcolsize", border.columns_width);
|
||||
settings.setValue("diagrameditor/defaultdisplaycols", border.display_columns);
|
||||
settings.setValue("diagrameditor/defaultrows", border.rows_count);
|
||||
settings.setValue("diagrameditor/defaultrowsize", border.rows_height);
|
||||
settings.setValue("diagrameditor/defaultdisplayrows", border.display_rows);
|
||||
bpw -> borderProperties().toSettings(settings, "diagrameditor/default");
|
||||
|
||||
// proprietes du cartouche
|
||||
InsetProperties inset = ipw-> insetProperties();
|
||||
settings.setValue("diagrameditor/defaulttitle", inset.title);
|
||||
settings.setValue("diagrameditor/defaultauthor", inset.author);
|
||||
settings.setValue("diagrameditor/defaultfilename", inset.filename);
|
||||
settings.setValue("diagrameditor/defaultfolio", inset.folio);
|
||||
QString date_setting_value;
|
||||
if (inset.useDate == InsetProperties::UseDateValue) {
|
||||
if (inset.date.isNull()) date_setting_value = "null";
|
||||
else date_setting_value = inset.date.toString("yyyyMMdd");
|
||||
} else {
|
||||
date_setting_value = "now";
|
||||
}
|
||||
settings.setValue("diagrameditor/defaultdate", date_setting_value);
|
||||
ipw-> insetProperties().toSettings(settings, "diagrameditor/default");
|
||||
|
||||
// proprietes par defaut des conducteurs
|
||||
cpw -> conductorProperties().toSettings(settings, "diagrameditor/defaultconductor");
|
||||
@@ -107,10 +83,90 @@ void NewDiagramPage::applyConf() {
|
||||
|
||||
/// @return l'icone de cette page
|
||||
QIcon NewDiagramPage::icon() const {
|
||||
return(QIcon(":/ico/conf_new_diagram.png"));
|
||||
return(QIcon(":/ico/conf_new_diagram_110.png"));
|
||||
}
|
||||
|
||||
/// @return le titre de cette page
|
||||
QString NewDiagramPage::title() const {
|
||||
return(tr("Nouveau sch\351ma"));
|
||||
return(tr("Nouveau sch\351ma", "configuration page title"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
GeneralConfigurationPage::GeneralConfigurationPage(QWidget *parent) : ConfigPage(parent) {
|
||||
|
||||
// acces a la configuration de QElectroTech
|
||||
QSettings &settings = QETApp::settings();
|
||||
bool tabbed = settings.value("diagrameditor/viewmode", "windowed") == "tabbed";
|
||||
bool integrate_elements = settings.value("diagrameditor/integrate-elements", true).toBool();
|
||||
|
||||
projects_view_mode_ = new QGroupBox(tr("Projets"), this);
|
||||
windowed_mode_ = new QRadioButton(tr("Utiliser des fen\352tres"), projects_view_mode_);
|
||||
tabbed_mode_ = new QRadioButton(tr("Utiliser des onglets"), projects_view_mode_);
|
||||
warning_view_mode_ = new QLabel(tr("Ces param\350tres s'appliqueront d\350s la prochaine ouverture d'un \351diteur de sch\351mas."));
|
||||
|
||||
elements_management_ = new QGroupBox(tr("Gestion des \351l\351ments"), this);
|
||||
integrate_elements_ = new QCheckBox(tr("Int\351grer automatiquement les \351l\351ments dans les projets (recommand\351)"), elements_management_);
|
||||
|
||||
if (tabbed) {
|
||||
tabbed_mode_ -> setChecked(true);
|
||||
} else {
|
||||
windowed_mode_ -> setChecked(true);
|
||||
}
|
||||
|
||||
integrate_elements_ -> setChecked(integrate_elements);
|
||||
|
||||
QVBoxLayout *projects_view_mode_layout = new QVBoxLayout();
|
||||
projects_view_mode_layout -> addWidget(windowed_mode_);
|
||||
projects_view_mode_layout -> addWidget(tabbed_mode_);
|
||||
projects_view_mode_layout -> addWidget(warning_view_mode_);
|
||||
projects_view_mode_ -> setLayout(projects_view_mode_layout);
|
||||
|
||||
QVBoxLayout *elements_management_layout = new QVBoxLayout();
|
||||
elements_management_layout -> addWidget(integrate_elements_);
|
||||
elements_management_ -> setLayout(elements_management_layout);
|
||||
|
||||
QVBoxLayout *vlayout1 = new QVBoxLayout();
|
||||
|
||||
QLabel *title_label_ = new QLabel(title());
|
||||
vlayout1 -> addWidget(title_label_);
|
||||
|
||||
QFrame *horiz_line_ = new QFrame();
|
||||
horiz_line_ -> setFrameShape(QFrame::HLine);
|
||||
vlayout1 -> addWidget(horiz_line_);
|
||||
|
||||
vlayout1 -> addWidget(projects_view_mode_);
|
||||
vlayout1 -> addWidget(elements_management_);
|
||||
vlayout1 -> addStretch();
|
||||
|
||||
setLayout(vlayout1);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
GeneralConfigurationPage::~GeneralConfigurationPage() {
|
||||
}
|
||||
|
||||
/**
|
||||
Applique la configuration de cette page
|
||||
*/
|
||||
void GeneralConfigurationPage::applyConf() {
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
QString view_mode = tabbed_mode_ -> isChecked() ? "tabbed" : "windowed";
|
||||
settings.setValue("diagrameditor/viewmode", view_mode) ;
|
||||
|
||||
settings.setValue("diagrameditor/integrate-elements", integrate_elements_ -> isChecked());
|
||||
}
|
||||
|
||||
/// @return l'icone de cette page
|
||||
QIcon GeneralConfigurationPage::icon() const {
|
||||
return(QIcon(":/ico/settings.png"));
|
||||
}
|
||||
|
||||
/// @return le titre de cette page
|
||||
QString GeneralConfigurationPage::title() const {
|
||||
return(tr("G\351n\351ral", "configuration page title"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -21,7 +21,6 @@
|
||||
class BorderPropertiesWidget;
|
||||
class ConductorPropertiesWidget;
|
||||
class InsetPropertiesWidget;
|
||||
|
||||
/**
|
||||
Cette classe abstraite contient les methodes que toutes les pages de
|
||||
configuration doivent implementer.
|
||||
@@ -68,4 +67,34 @@ class NewDiagramPage : public ConfigPage {
|
||||
InsetPropertiesWidget *ipw; ///< Widget d'edition des proprietes par defaut du cartouche
|
||||
ConductorPropertiesWidget *cpw; ///< Widget d'edition des proprietes par defaut des conducteurs
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente la page de configuration generale.
|
||||
*/
|
||||
class GeneralConfigurationPage : public ConfigPage {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
GeneralConfigurationPage(QWidget * = 0);
|
||||
virtual ~GeneralConfigurationPage();
|
||||
private:
|
||||
GeneralConfigurationPage(const GeneralConfigurationPage &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void applyConf();
|
||||
QString title() const;
|
||||
QIcon icon() const;
|
||||
|
||||
// attributs
|
||||
public:
|
||||
QLabel *title_label_;
|
||||
QFrame *horiz_line_;
|
||||
QGroupBox *projects_view_mode_;
|
||||
QRadioButton *windowed_mode_;
|
||||
QRadioButton *tabbed_mode_;
|
||||
QLabel *warning_view_mode_;
|
||||
QGroupBox *elements_management_;
|
||||
QCheckBox *integrate_elements_;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,72 +19,103 @@
|
||||
#include "elementtextitem.h"
|
||||
#include "diagram.h"
|
||||
#include "qetapp.h"
|
||||
#include "partline.h"
|
||||
#include "elementdefinition.h"
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
Constructeur de la classe ElementPerso. Permet d'instancier un element
|
||||
utilisable comme un element fixe a la difference que l'element perso lit
|
||||
sa description (noms, dessin, comportement) dans un fichier XML a fournir
|
||||
en parametre.
|
||||
@param nom_fichier Le chemin du fichier XML decrivant l'element
|
||||
Constructeur de la classe CustomElement. Permet d'instancier un element
|
||||
utilisable comme un element fixe a la difference que l'element perso est
|
||||
construit a partir d'une description au format XML. Celle-ci est recuperee
|
||||
a l'emplacement indique.
|
||||
@param location Emplacement de la definition d'element a utiliser
|
||||
@param qgi Le QGraphicsItem parent de cet element
|
||||
@param s Le Schema affichant cet element
|
||||
@param etat Un pointeur facultatif vers un entier. La valeur de cet entier
|
||||
@param state Un pointeur facultatif vers un entier. La valeur de cet entier
|
||||
sera changee de maniere a refleter le deroulement de l'instanciation :
|
||||
- 0 : L'instanciation a reussi
|
||||
- 1 : Le fichier n'existe pas
|
||||
- 2 : Le fichier n'a pu etre ouvert
|
||||
- 3 : Le fichier n'est pas un document XML
|
||||
- 4 : Le document XML n'a pas une "definition" comme racine
|
||||
- 1 : l'emplacement n'a pas permis d'acceder a une definition d'element
|
||||
- 2 : la definition n'etait pas lisible
|
||||
- 3 : la definition n'etait pas valide / exploitable / utilisable
|
||||
- 4 : Le document XML n'est pas un element "definition"
|
||||
- 5 : Les attributs de la definition ne sont pas presents et / ou valides
|
||||
- 6 : La definition est vide
|
||||
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
|
||||
- 8 : Aucune partie du dessin n'a pu etre chargee
|
||||
*/
|
||||
CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *s, int *etat) : FixedElement(qgi, s) {
|
||||
nomfichier = nom_fichier;
|
||||
// pessimisme inside : par defaut, ca foire
|
||||
elmt_etat = -1;
|
||||
|
||||
// le fichier doit exister
|
||||
QFileInfo infos_file(nomfichier);
|
||||
if (!infos_file.exists() || !infos_file.isFile()) {
|
||||
if (etat != NULL) *etat = 1;
|
||||
elmt_etat = 1;
|
||||
CustomElement::CustomElement(const ElementsLocation &location, QGraphicsItem *qgi, Diagram *s, int *state) :
|
||||
FixedElement(qgi, s),
|
||||
elmt_state(-1),
|
||||
location_(location)
|
||||
{
|
||||
// recupere la definition de l'element
|
||||
ElementsCollectionItem *element_item = QETApp::collectionItem(location);
|
||||
ElementDefinition *element_definition;
|
||||
if (
|
||||
!element_item ||\
|
||||
!element_item -> isElement() ||\
|
||||
!(element_definition = qobject_cast<ElementDefinition *>(element_item))
|
||||
) {
|
||||
if (state) *state = 1;
|
||||
elmt_state = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre lisible
|
||||
QFile fichier(nomfichier);
|
||||
if (!fichier.open(QIODevice::ReadOnly)) {
|
||||
if (etat != NULL) *etat = 2;
|
||||
elmt_etat = 2;
|
||||
if (!element_definition -> isReadable()) {
|
||||
if (state) *state = 2;
|
||||
elmt_state = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre un document XML
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(&fichier)) {
|
||||
if (etat != NULL) *etat = 3;
|
||||
elmt_etat = 3;
|
||||
if (element_definition -> isNull()) {
|
||||
if (state) *state = 3;
|
||||
elmt_state = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
// la racine est supposee etre une definition d'element
|
||||
QDomElement racine = document_xml.documentElement();
|
||||
if (racine.tagName() != "definition" || racine.attribute("type") != "element") {
|
||||
if (etat != NULL) *etat = 4;
|
||||
elmt_etat = 4;
|
||||
return;
|
||||
buildFromXml(element_definition -> xml(), &elmt_state);
|
||||
if (state) *state = elmt_state;
|
||||
if (elmt_state) return;
|
||||
|
||||
if (state) *state = 0;
|
||||
elmt_state = 0;
|
||||
}
|
||||
|
||||
CustomElement::CustomElement(const QDomElement &xml_def_elmt, QGraphicsItem *qgi, Diagram *s, int *state) : FixedElement(qgi, s) {
|
||||
int elmt_state = -1;
|
||||
buildFromXml(xml_def_elmt, &elmt_state);
|
||||
if (state) *state = elmt_state;
|
||||
}
|
||||
|
||||
/**
|
||||
Construit l'element personnalise a partir d'un element XML representant sa
|
||||
definition.
|
||||
@param xml_def_elmt
|
||||
@param state Un pointeur facultatif vers un entier. La valeur de cet entier
|
||||
sera changee de maniere a refleter le deroulement de l'instanciation :
|
||||
- 0 : La construction s'est bien passee
|
||||
- 4 : Le document XML n'est pas un element "definition"
|
||||
- 5 : Les attributs de la definition ne sont pas presents et / ou valides
|
||||
- 6 : La definition est vide
|
||||
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
|
||||
- 8 : Aucune partie du dessin n'a pu etre chargee
|
||||
@return true si le chargement a reussi, false sinon
|
||||
*/
|
||||
bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) {
|
||||
|
||||
if (xml_def_elmt.tagName() != "definition" || xml_def_elmt.attribute("type") != "element") {
|
||||
if (state) *state = 4;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// verifie basiquement que la version actuelle est capable de lire ce fichier
|
||||
if (racine.hasAttribute("version")) {
|
||||
if (xml_def_elmt.hasAttribute("version")) {
|
||||
bool conv_ok;
|
||||
qreal element_version = racine.attribute("version").toDouble(&conv_ok);
|
||||
qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok);
|
||||
if (conv_ok && QET::version.toDouble() < element_version) {
|
||||
std::cerr << qPrintable(
|
||||
QObject::tr("Avertissement : l'\351l\351ment ") + nom_fichier
|
||||
+ QObject::tr(" a \351t\351 enregistr\351 avec une version"
|
||||
QObject::tr("Avertissement : l'\351l\351ment "
|
||||
" a \351t\351 enregistr\351 avec une version"
|
||||
" ult\351rieure de QElectroTech.")
|
||||
) << std::endl;
|
||||
}
|
||||
@@ -93,32 +124,30 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
|
||||
// ces attributs doivent etre presents et valides
|
||||
int w, h, hot_x, hot_y;
|
||||
if (
|
||||
!QET::attributeIsAnInteger(racine, QString("width"), &w) ||\
|
||||
!QET::attributeIsAnInteger(racine, QString("height"), &h) ||\
|
||||
!QET::attributeIsAnInteger(racine, QString("hotspot_x"), &hot_x) ||\
|
||||
!QET::attributeIsAnInteger(racine, QString("hotspot_y"), &hot_y) ||\
|
||||
!validOrientationAttribute(racine)
|
||||
!QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\
|
||||
!QET::attributeIsAnInteger(xml_def_elmt, QString("height"), &h) ||\
|
||||
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_x"), &hot_x) ||\
|
||||
!QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_y"), &hot_y) ||\
|
||||
!validOrientationAttribute(xml_def_elmt)
|
||||
) {
|
||||
if (etat != NULL) *etat = 5;
|
||||
elmt_etat = 5;
|
||||
return;
|
||||
if (state) *state = 5;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// on peut d'ores et deja specifier la taille et le hotspot
|
||||
setSize(w, h);
|
||||
setHotspot(QPoint(hot_x, hot_y));
|
||||
setInternalConnections(racine.attribute("ic") == "true");
|
||||
setInternalConnections(xml_def_elmt.attribute("ic") == "true");
|
||||
|
||||
// la definition est supposee avoir des enfants
|
||||
if (racine.firstChild().isNull()) {
|
||||
if (etat != NULL) *etat = 6;
|
||||
elmt_etat = 6;
|
||||
return;
|
||||
if (xml_def_elmt.firstChild().isNull()) {
|
||||
if (state) *state = 6;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// initialisation du QPainter (pour dessiner l'element)
|
||||
QPainter qp;
|
||||
qp.begin(&dessin);
|
||||
qp.begin(&drawing);
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
@@ -126,12 +155,12 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
|
||||
qp.setPen(t);
|
||||
|
||||
// extrait les noms de la definition XML
|
||||
names.fromXml(racine);
|
||||
setToolTip(nom());
|
||||
names.fromXml(xml_def_elmt);
|
||||
setToolTip(name());
|
||||
|
||||
// parcours des enfants de la definition : parties du dessin
|
||||
int nb_elements_parses = 0;
|
||||
for (QDomNode node = racine.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
int parsed_elements_count = 0;
|
||||
for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
QDomElement elmts = node.toElement();
|
||||
if (elmts.isNull()) continue;
|
||||
if (elmts.tagName() == "description") {
|
||||
@@ -140,11 +169,10 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
|
||||
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
|
||||
QDomElement qde = n.toElement();
|
||||
if (qde.isNull()) continue;
|
||||
if (parseElement(qde, qp)) ++ nb_elements_parses;
|
||||
if (parseElement(qde, qp)) ++ parsed_elements_count;
|
||||
else {
|
||||
if (etat != NULL) *etat = 7;
|
||||
elmt_etat = 7;
|
||||
return;
|
||||
if (state) *state = 7;
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,17 +182,13 @@ CustomElement::CustomElement(QString &nom_fichier, QGraphicsItem *qgi, Diagram *
|
||||
qp.end();
|
||||
|
||||
// il doit y avoir au moins un element charge
|
||||
if (!nb_elements_parses) {
|
||||
if (etat != NULL) *etat = 8;
|
||||
elmt_etat = 8;
|
||||
return;
|
||||
if (!parsed_elements_count) {
|
||||
if (state) *state = 8;
|
||||
return(false);
|
||||
} else {
|
||||
if (state) *state = 0;
|
||||
return(true);
|
||||
}
|
||||
|
||||
// fermeture du fichier
|
||||
fichier.close();
|
||||
|
||||
if (etat != NULL) *etat = 0;
|
||||
elmt_etat = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +212,7 @@ QList<Conductor *> CustomElement::conductors() const {
|
||||
/**
|
||||
@return Le nombre de bornes que l'element possede
|
||||
*/
|
||||
int CustomElement::nbTerminals() const {
|
||||
int CustomElement::terminalsCount() const {
|
||||
return(list_terminals.size());
|
||||
}
|
||||
|
||||
@@ -198,7 +222,7 @@ int CustomElement::nbTerminals() const {
|
||||
@param options Les options graphiques
|
||||
*/
|
||||
void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *) {
|
||||
dessin.play(qp);
|
||||
drawing.play(qp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,6 +241,7 @@ void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *) {
|
||||
bool CustomElement::parseElement(QDomElement &e, QPainter &qp) {
|
||||
if (e.tagName() == "terminal") return(parseTerminal(e));
|
||||
else if (e.tagName() == "line") return(parseLine(e, qp));
|
||||
else if (e.tagName() == "rect") return(parseRect(e, qp));
|
||||
else if (e.tagName() == "ellipse") return(parseEllipse(e, qp));
|
||||
else if (e.tagName() == "circle") return(parseCircle(e, qp));
|
||||
else if (e.tagName() == "arc") return(parseArc(e, qp));
|
||||
@@ -244,9 +269,125 @@ bool CustomElement::parseLine(QDomElement &e, QPainter &qp) {
|
||||
if (!QET::attributeIsAReal(e, QString("y1"), &y1)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("x2"), &x2)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y2"), &y2)) return(false);
|
||||
|
||||
QET::EndType first_end = QET::endTypeFromString(e.attribute("end1"));
|
||||
QET::EndType second_end = QET::endTypeFromString(e.attribute("end2"));
|
||||
qreal length1, length2;
|
||||
if (!QET::attributeIsAReal(e, QString("length1"), &length1)) length1 = 1.5;
|
||||
if (!QET::attributeIsAReal(e, QString("length2"), &length2)) length2 = 1.5;
|
||||
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.drawLine(QLineF(x1, y1, x2, y2));
|
||||
QPen t = qp.pen();
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
qp.setPen(t);
|
||||
|
||||
//qp.drawLine(QLineF(x1, y1, x2, y2));
|
||||
QLineF line(x1, y1, x2, y2);
|
||||
QPointF point1(line.p1());
|
||||
QPointF point2(line.p2());
|
||||
|
||||
qreal line_length(line.length());
|
||||
qreal pen_width = qp.pen().widthF();
|
||||
|
||||
// determine s'il faut dessiner les extremites
|
||||
bool draw_1st_end, draw_2nd_end;
|
||||
qreal reduced_line_length = line_length - (length1 * PartLine::requiredLengthForEndType(first_end));
|
||||
draw_1st_end = first_end && reduced_line_length >= 0;
|
||||
if (draw_1st_end) {
|
||||
reduced_line_length -= (length2 * PartLine::requiredLengthForEndType(second_end));
|
||||
} else {
|
||||
reduced_line_length = line_length - (length2 * PartLine::requiredLengthForEndType(second_end));
|
||||
}
|
||||
draw_2nd_end = second_end && reduced_line_length >= 0;
|
||||
|
||||
// dessine la premiere extremite
|
||||
QPointF start_point, stop_point;
|
||||
if (draw_1st_end) {
|
||||
QList<QPointF> four_points1(PartLine::fourEndPoints(point1, point2, length1));
|
||||
if (first_end == QET::Circle) {
|
||||
qp.drawEllipse(QRectF(four_points1[0] - QPointF(length1, length1), QSizeF(length1 * 2.0, length1 * 2.0)));
|
||||
start_point = four_points1[1];
|
||||
} else if (first_end == QET::Diamond) {
|
||||
qp.drawPolygon(QPolygonF() << four_points1[1] << four_points1[2] << point1 << four_points1[3]);
|
||||
start_point = four_points1[1];
|
||||
} else if (first_end == QET::Simple) {
|
||||
qp.drawPolyline(QPolygonF() << four_points1[3] << point1 << four_points1[2]);
|
||||
start_point = point1;
|
||||
|
||||
} else if (first_end == QET::Triangle) {
|
||||
qp.drawPolygon(QPolygonF() << four_points1[0] << four_points1[2] << point1 << four_points1[3]);
|
||||
start_point = four_points1[0];
|
||||
}
|
||||
|
||||
// ajuste le depart selon l'epaisseur du trait
|
||||
if (pen_width && (first_end == QET::Simple || first_end == QET::Circle)) {
|
||||
start_point = QLineF(start_point, point2).pointAt(pen_width / 2.0 / line_length);
|
||||
}
|
||||
} else {
|
||||
start_point = point1;
|
||||
}
|
||||
|
||||
// dessine la seconde extremite
|
||||
if (draw_2nd_end) {
|
||||
QList<QPointF> four_points2(PartLine::fourEndPoints(point2, point1, length2));
|
||||
if (second_end == QET::Circle) {
|
||||
qp.drawEllipse(QRectF(four_points2[0] - QPointF(length2, length2), QSizeF(length2 * 2.0, length2 * 2.0)));
|
||||
stop_point = four_points2[1];
|
||||
} else if (second_end == QET::Diamond) {
|
||||
qp.drawPolygon(QPolygonF() << four_points2[2] << point2 << four_points2[3] << four_points2[1]);
|
||||
stop_point = four_points2[1];
|
||||
} else if (second_end == QET::Simple) {
|
||||
qp.drawPolyline(QPolygonF() << four_points2[3] << point2 << four_points2[2]);
|
||||
stop_point = point2;
|
||||
} else if (second_end == QET::Triangle) {
|
||||
qp.drawPolygon(QPolygonF() << four_points2[0] << four_points2[2] << point2 << four_points2[3] << four_points2[0]);
|
||||
stop_point = four_points2[0];
|
||||
}
|
||||
|
||||
// ajuste l'arrivee selon l'epaisseur du trait
|
||||
if (pen_width && (second_end == QET::Simple || second_end == QET::Circle)) {
|
||||
stop_point = QLineF(point1, stop_point).pointAt((line_length - (pen_width / 2.0)) / line_length);
|
||||
}
|
||||
} else {
|
||||
stop_point = point2;
|
||||
}
|
||||
|
||||
qp.drawLine(start_point, stop_point);
|
||||
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un rectangle. Si l'analyse
|
||||
reussit, le rectangle est ajoute au dessin.
|
||||
Le rectangle est defini par les attributs suivants :
|
||||
- x : abscisse du coin superieur gauche du rectangle
|
||||
- y : ordonnee du coin superieur gauche du rectangle
|
||||
- width : largeur du rectangle
|
||||
- height : hauteur du rectangle
|
||||
|
||||
@param e L'element XML a analyser
|
||||
@param qp Le QPainter a utiliser pour dessiner l'element perso
|
||||
@return true si l'analyse reussit, false sinon
|
||||
*/
|
||||
bool CustomElement::parseRect(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence des attributs obligatoires
|
||||
double rect_x, rect_y, rect_w, rect_h;
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &rect_x)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &rect_y)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("width"), &rect_w)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("height"), &rect_h)) return(false);
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
|
||||
// force le type de jointures pour les rectangles
|
||||
QPen p = qp.pen();
|
||||
p.setJoinStyle(Qt::MiterJoin);
|
||||
qp.setPen(p);
|
||||
|
||||
qp.drawRect(QRectF(rect_x, rect_y, rect_w, rect_h));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
@@ -262,7 +403,6 @@ bool CustomElement::parseLine(QDomElement &e, QPainter &qp) {
|
||||
@param e L'element XML a analyser
|
||||
@param qp Le QPainter a utiliser pour dessiner l'element perso
|
||||
@return true si l'analyse reussit, false sinon
|
||||
@todo utiliser des attributs plus coherents : x et y = centre, rayon = vrai rayon
|
||||
*/
|
||||
bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence des attributs obligatoires
|
||||
@@ -289,7 +429,6 @@ bool CustomElement::parseCircle(QDomElement &e, QPainter &qp) {
|
||||
@param e L'element XML a analyser
|
||||
@param qp Le QPainter a utiliser pour dessiner l'element perso
|
||||
@return true si l'analyse reussit, false sinon
|
||||
@todo utiliser des attributs plus coherents : x et y = centre
|
||||
*/
|
||||
bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence des attributs obligatoires
|
||||
@@ -405,23 +544,23 @@ bool CustomElement::parseText(QDomElement &e, QPainter &qp) {
|
||||
- une taille
|
||||
- le fait de subir les rotations de l'element ou non
|
||||
@param e L'element XML a analyser
|
||||
@param s Le schema sur lequel l'element perso sera affiche
|
||||
@return true si l'analyse reussit, false sinon
|
||||
@return Un pointeur vers l'objet ElementTextItem ainsi cree si l'analyse reussit, 0 sinon
|
||||
*/
|
||||
bool CustomElement::parseInput(QDomElement &e) {
|
||||
ElementTextItem *CustomElement::parseInput(QDomElement &e) {
|
||||
qreal pos_x, pos_y;
|
||||
int size;
|
||||
if (
|
||||
!QET::attributeIsAReal(e, "x", &pos_x) ||\
|
||||
!QET::attributeIsAReal(e, "y", &pos_y) ||\
|
||||
!QET::attributeIsAnInteger(e, "size", &size)
|
||||
) return(false);
|
||||
) return(0);
|
||||
|
||||
ElementTextItem *eti = new ElementTextItem(e.attribute("text"), this);
|
||||
eti -> setFont(QFont(QETApp::diagramTextsFont(), size));
|
||||
eti -> setPos(pos_x, pos_y);
|
||||
eti -> setOriginalPos(QPointF(pos_x, pos_y));
|
||||
if (e.attribute("rotate") == "true") eti -> setFollowParentRotations(true);
|
||||
return(true);
|
||||
return(eti);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,23 +571,23 @@ bool CustomElement::parseInput(QDomElement &e) {
|
||||
- orientation : orientation de la borne = Nord (n), Sud (s), Est (e) ou Ouest (w)
|
||||
|
||||
@param e L'element XML a analyser
|
||||
@param s Le schema sur lequel l'element perso sera affiche
|
||||
@return true si l'analyse reussit, false sinon
|
||||
@return Un pointeur vers l'objet Terminal ainsi cree, 0 sinon
|
||||
*/
|
||||
bool CustomElement::parseTerminal(QDomElement &e) {
|
||||
Terminal *CustomElement::parseTerminal(QDomElement &e) {
|
||||
// verifie la presence et la validite des attributs obligatoires
|
||||
double terminalx, terminaly;
|
||||
QET::Orientation terminalo;
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(false);
|
||||
if (!e.hasAttribute("orientation")) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(0);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(0);
|
||||
if (!e.hasAttribute("orientation")) return(0);
|
||||
if (e.attribute("orientation") == "n") terminalo = QET::North;
|
||||
else if (e.attribute("orientation") == "s") terminalo = QET::South;
|
||||
else if (e.attribute("orientation") == "e") terminalo = QET::East;
|
||||
else if (e.attribute("orientation") == "w") terminalo = QET::West;
|
||||
else return(false);
|
||||
list_terminals << new Terminal(terminalx, terminaly, terminalo, this, qobject_cast<Diagram *>(scene()));
|
||||
return(true);
|
||||
else return(0);
|
||||
Terminal *new_terminal = new Terminal(terminalx, terminaly, terminalo, this, qobject_cast<Diagram *>(scene()));
|
||||
list_terminals << new_terminal;
|
||||
return(new_terminal);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,7 +620,7 @@ void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) {
|
||||
@param e Element XML
|
||||
@return true si l'attribut "orientation" est valide, false sinon
|
||||
*/
|
||||
bool CustomElement::validOrientationAttribute(QDomElement &e) {
|
||||
bool CustomElement::validOrientationAttribute(const QDomElement &e) {
|
||||
return(ori.fromString(e.attribute("orientation")));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -15,13 +15,14 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef ELEMENTPERSO_H
|
||||
#define ELEMENTPERSO_H
|
||||
#ifndef CUSTOM_ELEMENT_H
|
||||
#define CUSTOM_ELEMENT_H
|
||||
#include "fixedelement.h"
|
||||
#include <QtGui>
|
||||
#include "nameslist.h"
|
||||
class CustomElementPart;
|
||||
|
||||
#include "elementslocation.h"
|
||||
class ElementTextItem;
|
||||
class Terminal;
|
||||
/**
|
||||
Cette classe represente un element electrique. Elle est utilisable
|
||||
comme un element fixe. La difference est que l'element perso lit
|
||||
@@ -29,65 +30,69 @@ class CustomElementPart;
|
||||
en parametre.
|
||||
*/
|
||||
class CustomElement : public FixedElement {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL);
|
||||
CustomElement(const ElementsLocation &, QGraphicsItem * = 0, Diagram * = 0, int * = 0);
|
||||
CustomElement(const QDomElement &, QGraphicsItem * = 0, Diagram * = 0, int * = 0);
|
||||
virtual ~CustomElement();
|
||||
|
||||
friend class CustomElementPart;
|
||||
|
||||
private:
|
||||
CustomElement(const CustomElement &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
int elmt_etat; // contient le code d'erreur si l'instanciation a echoue ou 0 si l'instanciation s'est bien passe
|
||||
protected:
|
||||
int elmt_state; // contient le code d'erreur si l'instanciation a echoue ou 0 si l'instanciation s'est bien passe
|
||||
NamesList names;
|
||||
QString nomfichier;
|
||||
QPicture dessin;
|
||||
ElementsLocation location_;
|
||||
QPicture drawing;
|
||||
QList<Terminal *> list_terminals;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual QList<Terminal *> terminals() const;
|
||||
virtual QList<Conductor *> conductors() const;
|
||||
virtual int nbTerminals() const;
|
||||
virtual int terminalsCount() const;
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId() const;
|
||||
QString fichier() const;
|
||||
ElementsLocation location() const;
|
||||
bool isNull() const;
|
||||
int etat() const;
|
||||
QString nom() const;
|
||||
int state() const;
|
||||
QString name() const;
|
||||
|
||||
private:
|
||||
bool parseElement(QDomElement &, QPainter &);
|
||||
bool parseLine(QDomElement &, QPainter &);
|
||||
bool parseEllipse(QDomElement &, QPainter &);
|
||||
bool parseCircle(QDomElement &, QPainter &);
|
||||
bool parseArc(QDomElement &, QPainter &);
|
||||
bool parsePolygon(QDomElement &, QPainter &);
|
||||
bool parseText(QDomElement &, QPainter &);
|
||||
bool parseInput(QDomElement &);
|
||||
bool parseTerminal(QDomElement &);
|
||||
void setQPainterAntiAliasing(QPainter &, bool);
|
||||
bool validOrientationAttribute(QDomElement &);
|
||||
void setPainterStyle(QDomElement &, QPainter &);
|
||||
protected:
|
||||
virtual bool buildFromXml(const QDomElement &, int * = 0);
|
||||
virtual bool parseElement(QDomElement &, QPainter &);
|
||||
virtual bool parseLine(QDomElement &, QPainter &);
|
||||
virtual bool parseRect(QDomElement &, QPainter &);
|
||||
virtual bool parseEllipse(QDomElement &, QPainter &);
|
||||
virtual bool parseCircle(QDomElement &, QPainter &);
|
||||
virtual bool parseArc(QDomElement &, QPainter &);
|
||||
virtual bool parsePolygon(QDomElement &, QPainter &);
|
||||
virtual bool parseText(QDomElement &, QPainter &);
|
||||
virtual ElementTextItem *parseInput(QDomElement &);
|
||||
virtual Terminal *parseTerminal(QDomElement &);
|
||||
virtual void setQPainterAntiAliasing(QPainter &, bool);
|
||||
virtual bool validOrientationAttribute(const QDomElement &);
|
||||
virtual void setPainterStyle(QDomElement &, QPainter &);
|
||||
};
|
||||
|
||||
/**
|
||||
@return L'ID du type de l'element ; pour un CustomElement, cela revient au
|
||||
nom du fichier
|
||||
@see fichier()
|
||||
@see location()
|
||||
*/
|
||||
inline QString CustomElement::typeId() const {
|
||||
return(nomfichier);
|
||||
return(location_.path());
|
||||
}
|
||||
|
||||
/**
|
||||
@return L'adresse du fichier contenant la description XML de cet element
|
||||
*/
|
||||
inline QString CustomElement::fichier() const {
|
||||
return(nomfichier);
|
||||
inline ElementsLocation CustomElement::location() const {
|
||||
return(location_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +100,7 @@ inline QString CustomElement::fichier() const {
|
||||
description XML a echoue
|
||||
*/
|
||||
inline bool CustomElement::isNull() const {
|
||||
return(elmt_etat != 0);
|
||||
return(elmt_state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,15 +115,15 @@ inline bool CustomElement::isNull() const {
|
||||
- 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue
|
||||
- 8 : Aucune partie du dessin n'a pu etre chargee
|
||||
*/
|
||||
inline int CustomElement::etat() const {
|
||||
return(elmt_etat);
|
||||
inline int CustomElement::state() const {
|
||||
return(elmt_state);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nom de l'element
|
||||
*/
|
||||
inline QString CustomElement::nom() const {
|
||||
return(names.name(QFileInfo(nomfichier).baseName()));
|
||||
inline QString CustomElement::name() const {
|
||||
return(names.name(location_.baseName()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "customelement.h"
|
||||
#include "diagram.h"
|
||||
#include "exportdialog.h"
|
||||
#include "ghostelement.h"
|
||||
#include "diagramcommands.h"
|
||||
#include "diagramcontent.h"
|
||||
|
||||
@@ -37,7 +38,9 @@ Diagram::Diagram(QObject *parent) :
|
||||
draw_grid(true),
|
||||
use_border(true),
|
||||
moved_elements_fetched(false),
|
||||
draw_terminals(true)
|
||||
draw_terminals(true),
|
||||
project_(0),
|
||||
read_only_(false)
|
||||
{
|
||||
undo_stack = new QUndoStack();
|
||||
qgi_manager = new QGIManager(this);
|
||||
@@ -51,9 +54,6 @@ Diagram::Diagram(QObject *parent) :
|
||||
conductor_setter -> setPen(t);
|
||||
conductor_setter -> setLine(QLineF(QPointF(0.0, 0.0), QPointF(0.0, 0.0)));
|
||||
connect(this, SIGNAL(selectionChanged()), this, SLOT(slot_checkSelectionEmptinessChange()));
|
||||
|
||||
// lit les caracteristiques des conducteurs par defaut dans la configuration
|
||||
defaultConductorProperties.fromSettings(QETApp::settings(), "diagrameditor/defaultconductor");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +77,7 @@ Diagram::~Diagram() {
|
||||
foreach(QGraphicsItem *qgi_d, deletable_items) {
|
||||
delete qgi_d;
|
||||
}
|
||||
// qDebug() << "Suppression du schema" << ((void*)this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,15 +126,17 @@ void Diagram::drawBackground(QPainter *p, const QRectF &r) {
|
||||
@param e QKeyEvent decrivant l'evenement clavier
|
||||
*/
|
||||
void Diagram::keyPressEvent(QKeyEvent *e) {
|
||||
QPointF movement;
|
||||
switch(e -> key()) {
|
||||
case Qt::Key_Left: movement = QPointF(-xGrid, 0.0); break;
|
||||
case Qt::Key_Right: movement = QPointF(+xGrid, 0.0); break;
|
||||
case Qt::Key_Up: movement = QPointF(0.0, -yGrid); break;
|
||||
case Qt::Key_Down: movement = QPointF(0.0, +yGrid); break;
|
||||
}
|
||||
if (!movement.isNull() && !focusItem()) {
|
||||
moveElements(movement);
|
||||
if (!isReadOnly()) {
|
||||
QPointF movement;
|
||||
switch(e -> key()) {
|
||||
case Qt::Key_Left: movement = QPointF(-xGrid, 0.0); break;
|
||||
case Qt::Key_Right: movement = QPointF(+xGrid, 0.0); break;
|
||||
case Qt::Key_Up: movement = QPointF(0.0, -yGrid); break;
|
||||
case Qt::Key_Down: movement = QPointF(0.0, +yGrid); break;
|
||||
}
|
||||
if (!movement.isNull() && !focusItem()) {
|
||||
moveElements(movement);
|
||||
}
|
||||
}
|
||||
QGraphicsScene::keyPressEvent(e);
|
||||
}
|
||||
@@ -143,16 +146,18 @@ void Diagram::keyPressEvent(QKeyEvent *e) {
|
||||
@param e QKeyEvent decrivant l'evenement clavier
|
||||
*/
|
||||
void Diagram::keyReleaseEvent(QKeyEvent *e) {
|
||||
// detecte le relachement d'une touche de direction ( = deplacement d'elements)
|
||||
if (
|
||||
(e -> key() == Qt::Key_Left || e -> key() == Qt::Key_Right ||\
|
||||
e -> key() == Qt::Key_Up || e -> key() == Qt::Key_Down) &&\
|
||||
!current_movement.isNull() && !e -> isAutoRepeat()
|
||||
) {
|
||||
// cree un objet d'annulation pour le mouvement qui vient de se finir
|
||||
undoStack().push(new MoveElementsCommand(this, selectedContent(), current_movement));
|
||||
invalidateMovedElements();
|
||||
current_movement = QPointF();
|
||||
if (!isReadOnly()) {
|
||||
// detecte le relachement d'une touche de direction ( = deplacement d'elements)
|
||||
if (
|
||||
(e -> key() == Qt::Key_Left || e -> key() == Qt::Key_Right ||\
|
||||
e -> key() == Qt::Key_Up || e -> key() == Qt::Key_Down) &&\
|
||||
!current_movement.isNull() && !e -> isAutoRepeat()
|
||||
) {
|
||||
// cree un objet d'annulation pour le mouvement qui vient de se finir
|
||||
undoStack().push(new MoveElementsCommand(this, selectedContent(), current_movement));
|
||||
invalidateMovedElements();
|
||||
current_movement = QPointF();
|
||||
}
|
||||
}
|
||||
QGraphicsScene::keyReleaseEvent(e);
|
||||
}
|
||||
@@ -227,6 +232,14 @@ QSize Diagram::imageSize() const {
|
||||
return(QSizeF(image_width, image_height).toSize());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le schema est considere comme vide, false sinon.
|
||||
Un schema vide ne contient ni element, ni conducteur, ni champ de texte
|
||||
*/
|
||||
bool Diagram::isEmpty() const {
|
||||
return(!items().count());
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte tout ou partie du schema
|
||||
@param diagram Booleen (a vrai par defaut) indiquant si le XML genere doit
|
||||
@@ -258,7 +271,7 @@ QDomDocument Diagram::toXml(bool diagram) {
|
||||
|
||||
// type de conducteur par defaut
|
||||
QDomElement default_conductor = document.createElement("defaultconductor");
|
||||
defaultConductorProperties.toXml(document, default_conductor);
|
||||
defaultConductorProperties.toXml(default_conductor);
|
||||
racine.appendChild(default_conductor);
|
||||
}
|
||||
document.appendChild(racine);
|
||||
@@ -324,20 +337,38 @@ QDomDocument Diagram::toXml(bool diagram) {
|
||||
}
|
||||
|
||||
/**
|
||||
Importe le diagram decrit dans un document XML. Si une position est
|
||||
Importe le schema decrit dans un document XML. Si une position est
|
||||
precisee, les elements importes sont positionnes de maniere a ce que le
|
||||
coin superieur gauche du plus petit rectangle pouvant les entourant tous
|
||||
(le bounding rect) soit a cette position.
|
||||
@param document Le document XML a analyser
|
||||
@param position La position du diagram importe
|
||||
@param position La position du schema importe
|
||||
@param consider_informations Si vrai, les informations complementaires
|
||||
(auteur, titre, ...) seront prises en compte
|
||||
@param content_ptr si ce pointeur vers un DiagramContentn'est pas NULL, il
|
||||
@param content_ptr si ce pointeur vers un DiagramContent n'est pas NULL, il
|
||||
sera rempli avec le contenu ajoute au schema par le fromXml
|
||||
@return true si l'import a reussi, false sinon
|
||||
*/
|
||||
bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
|
||||
QDomElement root = document.documentElement();
|
||||
return(fromXml(root, position, consider_informations, content_ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
Importe le schema decrit dans un element XML. Si une position est
|
||||
precisee, les elements importes sont positionnes de maniere a ce que le
|
||||
coin superieur gauche du plus petit rectangle pouvant les entourant tous
|
||||
(le bounding rect) soit a cette position.
|
||||
@param document Le document XML a analyser
|
||||
@param position La position du schema importe
|
||||
@param consider_informations Si vrai, les informations complementaires
|
||||
(auteur, titre, ...) seront prises en compte
|
||||
@param content_ptr si ce pointeur vers un DiagramContent n'est pas NULL, il
|
||||
sera rempli avec le contenu ajoute au schema par le fromXml
|
||||
@return true si l'import a reussi, false sinon
|
||||
*/
|
||||
bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_informations, DiagramContent *content_ptr) {
|
||||
QDomElement root = document;
|
||||
// le premier element doit etre un schema
|
||||
if (root.tagName() != "diagram") return(false);
|
||||
|
||||
@@ -390,7 +421,10 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in
|
||||
}
|
||||
|
||||
// si la racine n'a pas d'enfant : le chargement est fini (schema vide)
|
||||
if (root.firstChild().isNull()) return(true);
|
||||
if (root.firstChild().isNull()) {
|
||||
write(document);
|
||||
return(true);
|
||||
}
|
||||
|
||||
// chargement de tous les elements du fichier XML
|
||||
QList<Element *> added_elements;
|
||||
@@ -400,13 +434,17 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in
|
||||
|
||||
// cree un element dont le type correspond a l'id type
|
||||
QString type_id = e.attribute("type");
|
||||
QString chemin_fichier = QETApp::realPath(type_id);
|
||||
CustomElement *nvel_elmt = new CustomElement(chemin_fichier);
|
||||
ElementsLocation element_location = ElementsLocation(type_id);
|
||||
if (type_id.startsWith("embed://")) element_location.setProject(project_);
|
||||
|
||||
CustomElement *nvel_elmt = new CustomElement(element_location);
|
||||
if (nvel_elmt -> isNull()) {
|
||||
QString debug_message = QString("Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(chemin_fichier).arg(nvel_elmt -> etat());
|
||||
QString debug_message = QString("Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(element_location.path()).arg(nvel_elmt -> state());
|
||||
qDebug() << debug_message;
|
||||
delete nvel_elmt;
|
||||
qDebug(debug_message.toLatin1().data());
|
||||
continue;
|
||||
|
||||
qDebug() << "Utilisation d'un GhostElement en lieu et place de cet element.";
|
||||
nvel_elmt = new GhostElement(element_location);
|
||||
}
|
||||
|
||||
// charge les caracteristiques de l'element
|
||||
@@ -484,7 +522,7 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in
|
||||
added_conductors << c;
|
||||
}
|
||||
}
|
||||
} else qDebug() << "Le chargement du conductor" << id_p1 << id_p2 << "a echoue";
|
||||
} else qDebug() << "Le chargement du conducteur" << id_p1 << id_p2 << "a echoue";
|
||||
}
|
||||
|
||||
// remplissage des listes facultatives
|
||||
@@ -494,9 +532,52 @@ bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_in
|
||||
content_ptr -> textFields = added_texts;
|
||||
}
|
||||
|
||||
write(document);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Enregistre le schema XML dans son document XML interne et emet le signal
|
||||
written().
|
||||
*/
|
||||
void Diagram::write() {
|
||||
qDebug() << qPrintable(QString("Diagram::write() : saving changes from diagram \"%1\" [%2]").arg(title()).arg(QET::pointerString(this)));
|
||||
write(toXml().documentElement());
|
||||
undoStack().setClean();
|
||||
}
|
||||
|
||||
/**
|
||||
Enregistre un element XML dans son document XML interne et emet le signal
|
||||
written().
|
||||
@param element xml a enregistrer
|
||||
*/
|
||||
void Diagram::write(const QDomElement &element) {
|
||||
xml_document.clear();
|
||||
xml_document.appendChild(xml_document.importNode(element, true));
|
||||
emit(written());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si la fonction write a deja ete appele (pour etre plus exact :
|
||||
si le document XML utilise en interne n'est pas vide), false sinon
|
||||
*/
|
||||
bool Diagram::wasWritten() const {
|
||||
return(!xml_document.isNull());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le schema en XML tel qu'il doit etre enregistre dans le fichier projet
|
||||
@param xml_doc document XML a utiliser pour creer l'element
|
||||
*/
|
||||
QDomElement Diagram::writeXml(QDomDocument &xml_doc) const {
|
||||
// si le schema n'a pas ete enregistre explicitement, on n'ecrit rien
|
||||
if (!wasWritten()) return(QDomElement());
|
||||
|
||||
QDomElement diagram_elmt = xml_document.documentElement();
|
||||
QDomNode new_node = xml_doc.importNode(diagram_elmt, true);
|
||||
return(new_node.toElement());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait qu'un texte du schema ait ete modifie
|
||||
@param text_item Texte modifie
|
||||
@@ -536,6 +617,26 @@ QRectF Diagram::border() const {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le titre du cartouche
|
||||
*/
|
||||
QString Diagram::title() const {
|
||||
return(border_and_inset.title());
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des elements de ce schema
|
||||
*/
|
||||
QList<CustomElement *> Diagram::customElements() const {
|
||||
QList<CustomElement *> elements_list;
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (CustomElement *elmt = qgraphicsitem_cast<CustomElement *>(qgi)) {
|
||||
elements_list << elmt;
|
||||
}
|
||||
}
|
||||
return(elements_list);
|
||||
}
|
||||
|
||||
/// oublie la liste des elements et conducteurs en mouvement
|
||||
void Diagram::invalidateMovedElements() {
|
||||
if (!moved_elements_fetched) return;
|
||||
@@ -617,6 +718,20 @@ void Diagram::moveElements(const QPointF &diff, QGraphicsItem *dontmove) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si un element est utilise sur un schema
|
||||
@param location Emplacement d'un element
|
||||
@return true si l'element location est utilise sur ce schema, false sinon
|
||||
*/
|
||||
bool Diagram::usesElement(const ElementsLocation &location) {
|
||||
foreach(CustomElement *element, customElements()) {
|
||||
if (element -> location() == location) {
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Definit s'il faut afficher ou non les bornes
|
||||
@param dt true pour afficher les bornes, false sinon
|
||||
@@ -649,6 +764,38 @@ bool Diagram::clipboardMayContainDiagram() {
|
||||
return(may_be_diagram);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le projet auquel ce schema appartient ou 0 s'il s'agit d'un schema
|
||||
independant.
|
||||
*/
|
||||
QETProject *Diagram::project() const {
|
||||
return(project_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param project le nouveau projet auquel ce schema appartient ou 0 s'il
|
||||
s'agit d'un schema independant. Indiquer 0 pour rendre ce schema independant.
|
||||
*/
|
||||
void Diagram::setProject(QETProject *project) {
|
||||
project_ = project;
|
||||
}
|
||||
/**
|
||||
@return true si le schema est en lecture seule
|
||||
*/
|
||||
bool Diagram::isReadOnly() const {
|
||||
return(read_only_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param read_only true pour passer le schema en lecture seule, false sinon
|
||||
*/
|
||||
void Diagram::setReadOnly(bool read_only) {
|
||||
if (read_only_ != read_only) {
|
||||
read_only_ = read_only;
|
||||
emit(readOnlyChanged(read_only_));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le contenu du schema. Les conducteurs sont tous places dans
|
||||
conductorsToMove.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,15 +19,17 @@
|
||||
#define SCHEMA_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include "qetdiagrameditor.h"
|
||||
#include "borderinset.h"
|
||||
#include "qgimanager.h"
|
||||
#include "conductorproperties.h"
|
||||
class Element;
|
||||
class CustomElement;
|
||||
class Terminal;
|
||||
class Conductor;
|
||||
class DiagramTextItem;
|
||||
class DiagramContent;
|
||||
class QETProject;
|
||||
class ElementsLocation;
|
||||
/**
|
||||
Cette classe represente un schema electrique.
|
||||
Elle gere les differents elements et conducteurs qui le composent
|
||||
@@ -78,6 +80,9 @@ class Diagram : public QGraphicsScene {
|
||||
QGIManager *qgi_manager;
|
||||
QUndoStack *undo_stack;
|
||||
bool draw_terminals;
|
||||
QDomDocument xml_document;
|
||||
QETProject *project_;
|
||||
bool read_only_;
|
||||
|
||||
// methodes
|
||||
protected:
|
||||
@@ -88,6 +93,14 @@ class Diagram : public QGraphicsScene {
|
||||
public:
|
||||
static bool clipboardMayContainDiagram();
|
||||
|
||||
// fonctions relatives au projet parent
|
||||
QETProject *project() const;
|
||||
void setProject(QETProject *);
|
||||
|
||||
// fonctions relatives a la lecture seule
|
||||
bool isReadOnly() const;
|
||||
void setReadOnly(bool);
|
||||
|
||||
// fonctions relatives a la pose de conducteurs
|
||||
void setConductor(bool);
|
||||
void setConductorStart (QPointF);
|
||||
@@ -96,6 +109,11 @@ class Diagram : public QGraphicsScene {
|
||||
// fonctions relatives a l'import / export XML
|
||||
QDomDocument toXml(bool = true);
|
||||
bool fromXml(QDomDocument &, QPointF = QPointF(), bool = true, DiagramContent * = NULL);
|
||||
bool fromXml(QDomElement &, QPointF = QPointF(), bool = true, DiagramContent * = NULL);
|
||||
void write();
|
||||
void write(const QDomElement &);
|
||||
bool wasWritten() const;
|
||||
QDomElement writeXml(QDomDocument &) const;
|
||||
|
||||
// fonctions relatives aux options graphiques
|
||||
void setDisplayGrid(bool);
|
||||
@@ -109,9 +127,13 @@ class Diagram : public QGraphicsScene {
|
||||
void setDrawTerminals(bool);
|
||||
|
||||
QRectF border() const;
|
||||
QString title() const;
|
||||
bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio);
|
||||
QSize imageSize() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
QList<CustomElement *> customElements() const;
|
||||
void invalidateMovedElements();
|
||||
void fetchMovedElements();
|
||||
const QSet<Element *> &elementsToMove();
|
||||
@@ -122,6 +144,7 @@ class Diagram : public QGraphicsScene {
|
||||
DiagramContent content() const;
|
||||
DiagramContent selectedContent();
|
||||
void moveElements(const QPointF &, QGraphicsItem * = NULL);
|
||||
bool usesElement(const ElementsLocation &);
|
||||
|
||||
QUndoStack &undoStack();
|
||||
QGIManager &qgiManager();
|
||||
@@ -139,6 +162,8 @@ class Diagram : public QGraphicsScene {
|
||||
vice-versa.
|
||||
*/
|
||||
void selectionEmptinessChanged();
|
||||
void written();
|
||||
void readOnlyChanged(bool);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -33,7 +33,7 @@ AddElementCommand::AddElementCommand(
|
||||
const QPointF &p,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajouter 1 ") + elmt -> nom(), parent),
|
||||
QUndoCommand(QString(QObject::tr("ajouter 1 %1", "undo caption - %1 is an element name")).arg(elmt -> name()), parent),
|
||||
element(elmt),
|
||||
diagram(d),
|
||||
position(p)
|
||||
@@ -66,7 +66,7 @@ void AddElementCommand::redo() {
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AddTextCommand::AddTextCommand(Diagram *dia, DiagramTextItem *text, const QPointF &pos, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("Ajouter un champ de texte"), parent),
|
||||
QUndoCommand(QObject::tr("Ajouter un champ de texte", "undo caption"), parent),
|
||||
textitem(text),
|
||||
diagram(dia),
|
||||
position(pos)
|
||||
@@ -113,7 +113,7 @@ AddConductorCommand::AddConductorCommand(
|
||||
Conductor *c,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajouter un conducteur"), parent),
|
||||
QUndoCommand(QObject::tr("ajouter un conducteur", "undo caption"), parent),
|
||||
conductor(c),
|
||||
diagram(d)
|
||||
{
|
||||
@@ -153,7 +153,14 @@ DeleteElementsCommand::DeleteElementsCommand(
|
||||
removed_content(content),
|
||||
diagram(dia)
|
||||
{
|
||||
setText(QObject::tr("supprimer ") + removed_content.sentence(DiagramContent::All));
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"supprimer %1",
|
||||
"undo caption - %1 is a sentence listing the removed content"
|
||||
)
|
||||
).arg(removed_content.sentence(DiagramContent::All))
|
||||
);
|
||||
diagram -> qgiManager().manage(removed_content.items(DiagramContent::All));
|
||||
}
|
||||
|
||||
@@ -220,7 +227,14 @@ PasteDiagramCommand::PasteDiagramCommand(
|
||||
first_redo(true)
|
||||
{
|
||||
|
||||
setText(QObject::tr("coller ") + content.sentence(filter));
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"coller %1",
|
||||
"undo caption - %1 is a sentence listing the content to paste"
|
||||
).arg(content.sentence(filter))
|
||||
)
|
||||
);
|
||||
diagram -> qgiManager().manage(content.items(filter));
|
||||
}
|
||||
|
||||
@@ -280,7 +294,14 @@ CutDiagramCommand::CutDiagramCommand(
|
||||
) :
|
||||
DeleteElementsCommand(dia, content, parent)
|
||||
{
|
||||
setText(QObject::tr("couper ") + content.sentence(DiagramContent::All));
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"couper %1",
|
||||
"undo caption - %1 is a sentence listing the content to cut"
|
||||
).arg(content.sentence(DiagramContent::All))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -306,7 +327,21 @@ MoveElementsCommand::MoveElementsCommand(
|
||||
movement(m),
|
||||
first_redo(true)
|
||||
{
|
||||
setText(QObject::tr("d\351placer ") + content_to_move.sentence(DiagramContent::Elements|DiagramContent::TextFields|DiagramContent::ConductorsToUpdate|DiagramContent::ConductorsToMove));
|
||||
QString moved_content_sentence = content_to_move.sentence(
|
||||
DiagramContent::Elements |
|
||||
DiagramContent::TextFields |
|
||||
DiagramContent::ConductorsToUpdate |
|
||||
DiagramContent::ConductorsToMove
|
||||
);
|
||||
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"d\351placer %1",
|
||||
"undo caption - %1 is a sentence listing the moved content"
|
||||
).arg(moved_content_sentence)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -367,7 +402,7 @@ ChangeDiagramTextCommand::ChangeDiagramTextCommand(
|
||||
const QString &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier le texte"), parent),
|
||||
QUndoCommand(QObject::tr("modifier le texte", "undo caption"), parent),
|
||||
text_item(dti),
|
||||
text_before(before),
|
||||
text_after(after),
|
||||
@@ -400,9 +435,17 @@ void ChangeDiagramTextCommand::redo() {
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
RotateElementsCommand::RotateElementsCommand(const QHash<Element *, QET::Orientation> &elements, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("pivoter ") + QET::ElementsAndConductorsSentence(elements.count(), 0), parent),
|
||||
QUndoCommand(parent),
|
||||
elements_to_rotate(elements)
|
||||
{
|
||||
setText(
|
||||
QString(
|
||||
QObject::tr(
|
||||
"pivoter %1",
|
||||
"undo caption - %1 is a sentence listing the rotated content"
|
||||
)
|
||||
).arg(QET::ElementsAndConductorsSentence(elements.count(), 0))
|
||||
);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -439,7 +482,7 @@ ChangeConductorCommand::ChangeConductorCommand(
|
||||
Qt::Corner path_t,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier un conducteur"), parent),
|
||||
QUndoCommand(QObject::tr("modifier un conducteur", "undo caption"), parent),
|
||||
conductor(c),
|
||||
old_profile(old_p),
|
||||
new_profile(new_p),
|
||||
@@ -472,9 +515,15 @@ ResetConductorCommand::ResetConductorCommand(
|
||||
const QHash<Conductor *, ConductorProfilesGroup> &cp,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("R\351initialiser ") + QET::ElementsAndConductorsSentence(0, cp.count()), parent),
|
||||
QUndoCommand(parent),
|
||||
conductors_profiles(cp)
|
||||
{
|
||||
setText(
|
||||
QObject::tr(
|
||||
"R\351initialiser %1",
|
||||
"undo caption - %1 is a sentence listing the reset content"
|
||||
).arg(QET::ElementsAndConductorsSentence(0, cp.count()))
|
||||
);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -508,7 +557,7 @@ ChangeInsetCommand::ChangeInsetCommand(
|
||||
const InsetProperties &new_ip,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier le cartouche"), parent),
|
||||
QUndoCommand(QObject::tr("modifier le cartouche", "undo caption"), parent),
|
||||
diagram(d),
|
||||
old_inset(old_ip),
|
||||
new_inset(new_ip)
|
||||
@@ -537,7 +586,7 @@ void ChangeInsetCommand::redo() {
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeBorderCommand::ChangeBorderCommand(Diagram *dia, const BorderProperties &old_bp, const BorderProperties &new_bp, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modifier les dimensions du sch\351ma"), parent),
|
||||
QUndoCommand(QObject::tr("modifier les dimensions du sch\351ma", "undo caption"), parent),
|
||||
diagram(dia),
|
||||
old_properties(old_bp),
|
||||
new_properties(new_bp)
|
||||
@@ -564,7 +613,7 @@ void ChangeBorderCommand::redo() {
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeConductorPropertiesCommand::ChangeConductorPropertiesCommand(Conductor *c, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modifier les propri\351t\351s d'un conducteur"), parent),
|
||||
QUndoCommand(QObject::tr("modifier les propri\351t\351s d'un conducteur", "undo caption"), parent),
|
||||
conductor(c),
|
||||
old_settings_set(false),
|
||||
new_settings_set(false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -16,7 +16,9 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "diagramprintdialog.h"
|
||||
#include "qetprintpreviewdialog.h"
|
||||
#include <math.h>
|
||||
#include "diagramschooser.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@@ -24,52 +26,52 @@
|
||||
@param printer Imprimante a utiliser
|
||||
@param parent Widget parent du dialogue
|
||||
*/
|
||||
DiagramPrintDialog::DiagramPrintDialog(Diagram *dia, QWidget *parent) :
|
||||
DiagramPrintDialog::DiagramPrintDialog(QETProject *project, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
diagram(dia),
|
||||
dialog(0)
|
||||
project_(project),
|
||||
dialog_(0)
|
||||
{
|
||||
// initialise l'imprimante
|
||||
printer = new QPrinter();
|
||||
printer_ = new QPrinter();
|
||||
|
||||
// orientation paysage par defaut
|
||||
printer -> setOrientation(QPrinter::Landscape);
|
||||
printer_ -> setOrientation(QPrinter::Landscape);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
DiagramPrintDialog::~DiagramPrintDialog() {
|
||||
delete dialog;
|
||||
delete printer;
|
||||
delete dialog_;
|
||||
delete printer_;
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le nom du PDF si l'utilisateur choisit une sortie vers un PDF
|
||||
*/
|
||||
void DiagramPrintDialog::setPDFName(const QString &name) {
|
||||
pdf_name = name;
|
||||
void DiagramPrintDialog::setFileName(const QString &name) {
|
||||
file_name_ = name;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom du PDF
|
||||
*/
|
||||
QString DiagramPrintDialog::PDFName() const {
|
||||
return(pdf_name);
|
||||
QString DiagramPrintDialog::fileName() const {
|
||||
return(file_name_);
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le nom du document
|
||||
*/
|
||||
void DiagramPrintDialog::setDocName(const QString &name) {
|
||||
doc_name = name;
|
||||
doc_name_ = name;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom du document
|
||||
*/
|
||||
QString DiagramPrintDialog::docName() const {
|
||||
return(doc_name);
|
||||
return(doc_name_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,31 +79,38 @@ QString DiagramPrintDialog::docName() const {
|
||||
*/
|
||||
void DiagramPrintDialog::exec() {
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
if (!pdf_name.isEmpty()) printer -> setOutputFileName(pdf_name);
|
||||
if (!doc_name.isEmpty()) printer -> setDocName(doc_name);
|
||||
#endif
|
||||
// prise en compte du nom du document
|
||||
if (!doc_name_.isEmpty()) printer_ -> setDocName(doc_name_);
|
||||
|
||||
// affichage du dialogue d'impression standard
|
||||
QPrintDialog print_dialog(printer, parentWidget());
|
||||
print_dialog.setWindowTitle(tr("Options d'impression"));
|
||||
print_dialog.setEnabledOptions(QAbstractPrintDialog::PrintToFile | QAbstractPrintDialog::PrintShowPageSize);
|
||||
// affichage d'un premier dialogue demandant a l'utilisateur le type
|
||||
// d'impression qu'il souhaite effectuer
|
||||
buildPrintTypeDialog();
|
||||
if (dialog_ -> exec() == QDialog::Rejected) return;
|
||||
|
||||
if (print_dialog.exec() == QDialog::Rejected) return;
|
||||
// parametrage de l'imprimante en fonction du type d'impression choisi
|
||||
if (printer_choice_ -> isChecked()) {
|
||||
// affichage du dialogue d'impression standard pour parametrer l'imprimante
|
||||
QPrintDialog print_dialog(printer_, parentWidget());
|
||||
print_dialog.setWindowTitle(tr("Options d'impression", "window title"));
|
||||
print_dialog.setEnabledOptions(QAbstractPrintDialog::PrintShowPageSize);
|
||||
if (print_dialog.exec() == QDialog::Rejected) return;
|
||||
} else if (pdf_choice_ -> isChecked()) {
|
||||
printer_ -> setOutputFormat(QPrinter::PdfFormat);
|
||||
printer_ -> setOutputFileName(filepath_field_ -> text());
|
||||
} else {
|
||||
printer_ -> setOutputFormat(QPrinter::PostScriptFormat);
|
||||
printer_ -> setOutputFileName(filepath_field_ -> text());
|
||||
}
|
||||
|
||||
/*
|
||||
Apres l'execution de ce premier dialogue, on connait le format papier a
|
||||
utiliser, son orientation et on est sur que tout cela est supporte par
|
||||
l'imprimante.
|
||||
On peut donc en deduire le nombre de pages a imprimer
|
||||
*/
|
||||
|
||||
// affichage d'un second dialogue, non standard, pour connaitre les pages a imprimer
|
||||
buildDialog();
|
||||
if (dialog -> exec() == QDialog::Rejected) return;
|
||||
// Apercu avant impression
|
||||
QETPrintPreviewDialog preview_dialog(project_, printer_, parentWidget());
|
||||
connect(&preview_dialog, SIGNAL(paintRequested(const QList<Diagram *> &, bool, QPrinter *)), this, SLOT(print(const QList<Diagram *> &, bool, QPrinter *)));
|
||||
DiagramsChooser *dc = preview_dialog.diagramsChooser();
|
||||
dc -> setSelectedAllDiagrams();
|
||||
if (preview_dialog.exec() == QDialog::Rejected) return;
|
||||
|
||||
// effectue l'impression en elle-meme
|
||||
print();
|
||||
print(dc -> selectedDiagrams(), preview_dialog.fitDiagramsToPages(), printer_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,8 +118,8 @@ void DiagramPrintDialog::exec() {
|
||||
@return Le nombre de pages necessaires pour imprimer le schema
|
||||
avec l'orientation et le format papier utilise dans l'imprimante en cours.
|
||||
*/
|
||||
int DiagramPrintDialog::pagesCount(bool fullpage) const {
|
||||
return(horizontalPagesCount(fullpage) * verticalPagesCount(fullpage));
|
||||
int DiagramPrintDialog::pagesCount(Diagram *diagram, bool fullpage) const {
|
||||
return(horizontalPagesCount(diagram, fullpage) * verticalPagesCount(diagram, fullpage));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,9 +127,9 @@ int DiagramPrintDialog::pagesCount(bool fullpage) const {
|
||||
@return La largeur du "poster" en nombre de pages pour imprimer le schema
|
||||
avec l'orientation et le format papier utilise dans l'imprimante en cours.
|
||||
*/
|
||||
int DiagramPrintDialog::horizontalPagesCount(bool fullpage) const {
|
||||
int DiagramPrintDialog::horizontalPagesCount(Diagram *diagram, bool fullpage) const {
|
||||
// note : pageRect et Paper Rect tiennent compte de l'orientation du papier
|
||||
QRect printable_area = fullpage ? printer -> paperRect() : printer -> pageRect();
|
||||
QRect printable_area = fullpage ? printer_ -> paperRect() : printer_ -> pageRect();
|
||||
QRect diagram_rect = diagram -> border().toRect();
|
||||
|
||||
int h_pages_count = int(ceil(qreal(diagram_rect.width()) / qreal(printable_area.width())));
|
||||
@@ -132,9 +141,9 @@ int DiagramPrintDialog::horizontalPagesCount(bool fullpage) const {
|
||||
@return La largeur du "poster" en nombre de pages pour imprimer le schema
|
||||
avec l'orientation et le format papier utilise dans l'imprimante en cours.
|
||||
*/
|
||||
int DiagramPrintDialog::verticalPagesCount(bool fullpage) const {
|
||||
int DiagramPrintDialog::verticalPagesCount(Diagram *diagram, bool fullpage) const {
|
||||
// note : pageRect et Paper Rect tiennent compte de l'orientation du papier
|
||||
QRect printable_area = fullpage ? printer -> paperRect() : printer -> pageRect();
|
||||
QRect printable_area = fullpage ? printer_ -> paperRect() : printer_ -> pageRect();
|
||||
QRect diagram_rect = diagram -> border().toRect();
|
||||
|
||||
int v_pages_count = int(ceil(qreal(diagram_rect.height()) / qreal(printable_area.height())));
|
||||
@@ -142,128 +151,184 @@ int DiagramPrintDialog::verticalPagesCount(bool fullpage) const {
|
||||
}
|
||||
|
||||
/**
|
||||
Construit un dialogue non standard pour demander les pages a imprimer a l'utilisateur
|
||||
Construit un dialogue non standard pour demander a l'utilisateur quelle type
|
||||
d'impression il souhaite effectuer : PDF, PS ou imprimante physique
|
||||
*/
|
||||
void DiagramPrintDialog::buildDialog() {
|
||||
dialog = new QDialog(parentWidget());
|
||||
dialog -> setMinimumWidth(460);
|
||||
dialog -> setWindowTitle(tr("Options d'impression"));
|
||||
options_label = new QLabel();
|
||||
use_full_page = new QCheckBox(tr("Utiliser toute la feuille"));
|
||||
use_full_page_label_ = new QLabel(tr(
|
||||
"Si cette option est coch\351e, les marges de la feuille seront "
|
||||
"ignor\351es et toute sa surface sera utilis\351e pour l'impression. "
|
||||
"Cela peut ne pas \352tre support\351 par votre imprimante."
|
||||
));
|
||||
use_full_page_label_ -> setWordWrap(true);
|
||||
use_full_page_label_ -> setContentsMargins(20, 0, 0, 0);
|
||||
fit_diagram_to_page = new QCheckBox(tr("Adapter le sch\351ma \340 la page"));
|
||||
fit_diagram_to_page_label_ = new QLabel(tr(
|
||||
"Si cette option est coch\351e, le sch\351ma sera agrandi ou "
|
||||
"r\351tr\351ci de fa\347on \340 remplir toute la surface imprimable "
|
||||
"d'une et une seule page."
|
||||
));
|
||||
fit_diagram_to_page_label_ -> setWordWrap(true);
|
||||
fit_diagram_to_page_label_ -> setContentsMargins(20, 0, 0, 0);
|
||||
fit_diagram_to_page -> setChecked(true);
|
||||
range_from_label = new QLabel(tr("Pages \340 imprimer : plage de "));
|
||||
start_page = new QSpinBox();
|
||||
to_label = new QLabel(tr(" \340 "));
|
||||
end_page = new QSpinBox();
|
||||
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
void DiagramPrintDialog::buildPrintTypeDialog() {
|
||||
// initialisation des widgets
|
||||
dialog_ = new QDialog(parentWidget());
|
||||
printtype_label_ = new QLabel(tr("Quel type d'impression d\351sirez-vous effectuer ?"));
|
||||
printer_icon_ = new QLabel();
|
||||
pdf_icon_ = new QLabel();
|
||||
ps_icon_ = new QLabel();
|
||||
printtype_choice_ = new QButtonGroup();
|
||||
printer_choice_ = new QRadioButton("Impression sur une imprimante physique");
|
||||
pdf_choice_ = new QRadioButton("Impression vers un fichier au format PDF");
|
||||
ps_choice_ = new QRadioButton("Impression vers un fichier au format PostScript (PS)");
|
||||
filepath_field_ = new QLineEdit();
|
||||
browse_button_ = new QPushButton("...");
|
||||
buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
QHBoxLayout *pages_layout = new QHBoxLayout();
|
||||
pages_layout -> addWidget(range_from_label);
|
||||
pages_layout -> addWidget(start_page);
|
||||
pages_layout -> addWidget(to_label);
|
||||
pages_layout -> addWidget(end_page);
|
||||
pages_layout -> addStretch();
|
||||
dialog_ -> setWindowTitle(tr("Choix du type d'impression"));
|
||||
printer_icon_ -> setPixmap(QPixmap(":/ico/printtype_printer.png"));
|
||||
pdf_icon_ -> setPixmap(QPixmap(":/ico/printtype_pdf.png"));
|
||||
ps_icon_ -> setPixmap(QPixmap(":/ico/printtype_ps.png"));
|
||||
printtype_choice_ -> addButton(printer_choice_);
|
||||
printtype_choice_ -> addButton(pdf_choice_);
|
||||
printtype_choice_ -> addButton(ps_choice_);
|
||||
printer_choice_ -> setChecked(true);
|
||||
if (!file_name_.isEmpty()) filepath_field_ -> setText(file_name_ + ".pdf");
|
||||
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(dialog);
|
||||
dialog_layout -> addWidget(options_label);
|
||||
dialog_layout -> addWidget(use_full_page);
|
||||
dialog_layout -> addWidget(use_full_page_label_);
|
||||
dialog_layout -> addWidget(fit_diagram_to_page);
|
||||
dialog_layout -> addWidget(fit_diagram_to_page_label_);
|
||||
dialog_layout -> addLayout(pages_layout);
|
||||
dialog_layout -> addStretch();
|
||||
dialog_layout -> addWidget(buttons);
|
||||
// connexions signaux / slots
|
||||
connect(printer_choice_, SIGNAL(toggled(bool)), this, SLOT(updatePrintTypeDialog()));
|
||||
connect(pdf_choice_, SIGNAL(toggled(bool)), this, SLOT(updatePrintTypeDialog()));
|
||||
connect(ps_choice_, SIGNAL(toggled(bool)), this, SLOT(updatePrintTypeDialog()));
|
||||
connect(browse_button_, SIGNAL(clicked(bool)), this, SLOT(browseFilePrintTypeDialog()));
|
||||
connect(buttons_, SIGNAL(accepted()), this, SLOT(acceptPrintTypeDialog()));
|
||||
connect(buttons_, SIGNAL(rejected()), dialog_, SLOT(reject()));
|
||||
|
||||
connect(use_full_page, SIGNAL(stateChanged(int)), this, SLOT(updateDialog()));
|
||||
connect(fit_diagram_to_page, SIGNAL(stateChanged(int)), this, SLOT(updateDialog()));
|
||||
connect(start_page, SIGNAL(valueChanged(int)), this, SLOT(checkStartPage()));
|
||||
connect(end_page, SIGNAL(valueChanged(int)), this, SLOT(checkEndPage()));
|
||||
connect(buttons, SIGNAL(accepted()), dialog, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), dialog, SLOT(reject()));
|
||||
// organisation graphique
|
||||
glayout0_ = new QGridLayout();
|
||||
hlayout0_ = new QHBoxLayout();
|
||||
vlayout0_ = new QVBoxLayout();
|
||||
|
||||
updateDialog();
|
||||
hlayout0_ -> addWidget(filepath_field_);
|
||||
hlayout0_ -> addWidget(browse_button_);
|
||||
glayout0_ -> addWidget(printer_icon_, 0, 0);
|
||||
glayout0_ -> addWidget(printer_choice_, 0, 1);
|
||||
glayout0_ -> addWidget(pdf_icon_, 1, 0);
|
||||
glayout0_ -> addWidget(pdf_choice_, 1, 1);
|
||||
glayout0_ -> addWidget(ps_icon_, 2, 0);
|
||||
glayout0_ -> addWidget(ps_choice_, 2, 1);
|
||||
glayout0_ -> addLayout(hlayout0_, 3, 1);
|
||||
|
||||
vlayout0_ -> addWidget(printtype_label_);
|
||||
vlayout0_ -> addLayout(glayout0_);
|
||||
vlayout0_ -> addWidget(buttons_);
|
||||
|
||||
dialog_ -> setLayout(vlayout0_);
|
||||
|
||||
updatePrintTypeDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
Assure la coherence du dialogue
|
||||
Assure la coherence du dialogue permettant le choix du type d'impression
|
||||
*/
|
||||
void DiagramPrintDialog::updateDialog() {
|
||||
int pages_count;
|
||||
// si on adapte le schema a la page, alors il n'y a qu'une page a imprimer
|
||||
if (fit_diagram_to_page -> isChecked()) {
|
||||
pages_count = 1;
|
||||
void DiagramPrintDialog::updatePrintTypeDialog() {
|
||||
// imprime-t-on vers un fichier ?
|
||||
bool file_print = !(printer_choice_ -> isChecked());
|
||||
|
||||
// on n'active le champ fichier que pour les impressions vers un fichier
|
||||
filepath_field_ -> setEnabled(file_print);
|
||||
browse_button_ -> setEnabled(file_print);
|
||||
|
||||
// on corrige eventuellement l'extension du fichier deja selectionne
|
||||
if (file_print) {
|
||||
QString filepath = filepath_field_ -> text();
|
||||
if (!filepath.isEmpty()) {
|
||||
if (pdf_choice_ -> isChecked() && filepath.endsWith(".ps")) {
|
||||
QRegExp re("\\.ps$", Qt::CaseInsensitive);
|
||||
filepath.replace(re, ".pdf");
|
||||
filepath_field_ -> setText(filepath);
|
||||
} else if (ps_choice_ -> isChecked() && filepath.endsWith(".pdf")) {
|
||||
QRegExp re("\\.pdf$", Qt::CaseInsensitive);
|
||||
filepath.replace(re, ".ps");
|
||||
filepath_field_ -> setText(filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Verifie l'etat du dialogue permettant le choix du type d'impression lorsque
|
||||
l'utilisateur le valide.
|
||||
*/
|
||||
void DiagramPrintDialog::acceptPrintTypeDialog() {
|
||||
bool file_print = !(printer_choice_ -> isChecked());
|
||||
if (file_print) {
|
||||
// un fichier doit avoir ete entre
|
||||
if (filepath_field_ -> text().isEmpty()) {
|
||||
QMessageBox::information(
|
||||
parentWidget(),
|
||||
tr("Fichier manquant", "message box title"),
|
||||
tr("Vous devez indiquer le chemin du fichier PDF/PS \340 cr\351er.", "message box content")
|
||||
);
|
||||
} else dialog_ -> accept();
|
||||
} else {
|
||||
pages_count = pagesCount(use_full_page -> isChecked());
|
||||
}
|
||||
options_label -> setText(tr("Nombre total de pages : ") + QString("%1").arg(pages_count));
|
||||
setPagesRangeVisible(pages_count > 1);
|
||||
start_page -> setRange(1, pages_count);
|
||||
end_page -> setRange(1, pages_count);
|
||||
end_page -> setValue(pages_count);
|
||||
}
|
||||
|
||||
/**
|
||||
S'assure que la premiere page ne soit pas superieure a la derniere page
|
||||
*/
|
||||
void DiagramPrintDialog::checkStartPage() {
|
||||
if (start_page -> value() > end_page -> value()) {
|
||||
start_page -> blockSignals(true);
|
||||
start_page -> setValue(end_page -> value());
|
||||
start_page -> blockSignals(false);
|
||||
// une imprimante doit avoir ete selectionnee
|
||||
/// @todo
|
||||
dialog_ -> accept();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
S'assure que la derniere page ne soit pas inferieure a la premiere page
|
||||
Permet a l'utilisateur de choisir un fichier
|
||||
*/
|
||||
void DiagramPrintDialog::checkEndPage() {
|
||||
if (end_page -> value() < start_page -> value()) {
|
||||
end_page -> blockSignals(true);
|
||||
end_page -> setValue(start_page -> value());
|
||||
end_page -> blockSignals(false);
|
||||
void DiagramPrintDialog::browseFilePrintTypeDialog() {
|
||||
QString extension;
|
||||
QString filter;
|
||||
if (printer_choice_ -> isChecked()) return;
|
||||
else if (pdf_choice_ -> isChecked()) {
|
||||
extension = ".pdf";
|
||||
filter = tr("Fichiers PDF (*.pdf)", "file filter");
|
||||
}
|
||||
else if (ps_choice_ -> isChecked()) {
|
||||
extension = ".ps";
|
||||
filter = tr("Fichiers PostScript (*.ps)", "file filter");
|
||||
}
|
||||
|
||||
QString filepath = QFileDialog::getSaveFileName(
|
||||
parentWidget(),
|
||||
QString(),
|
||||
filepath_field_ -> text(),
|
||||
filter
|
||||
);
|
||||
|
||||
if (!filepath.isEmpty()) {
|
||||
if (!filepath.endsWith(extension)) filepath += extension;
|
||||
filepath_field_ -> setText(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param visible true pour afficher les pages, false sinon
|
||||
*/
|
||||
void DiagramPrintDialog::setPagesRangeVisible(bool visible) {
|
||||
range_from_label -> setVisible(visible);
|
||||
start_page -> setVisible(visible);
|
||||
to_label -> setVisible(visible);
|
||||
end_page -> setVisible(visible);
|
||||
}
|
||||
|
||||
/**
|
||||
Effectue l'impression elle-meme
|
||||
@param diagrams Schemas a imprimer
|
||||
@param fit_page Booleen indiquant s'il faut adapter les schemas aux pages
|
||||
ou non
|
||||
@param printer L'imprimante a utiliser
|
||||
*/
|
||||
void DiagramPrintDialog::print() {
|
||||
// recupere les informations collectees dans le second dialogue
|
||||
bool full_page = use_full_page -> isChecked();
|
||||
bool fit_page = fit_diagram_to_page -> isChecked();
|
||||
int first_page = start_page -> value();
|
||||
int last_page = end_page -> value();
|
||||
|
||||
// parametre l'imprimante
|
||||
printer -> setFullPage(full_page);
|
||||
void DiagramPrintDialog::print(const QList<Diagram *> &diagrams, bool fit_page, QPrinter */*printer*/) {
|
||||
//qDebug() << "Demande d'impression de " << diagrams.count() << "schemas.";
|
||||
|
||||
// QPainter utiliser pour effectuer le rendu
|
||||
QPainter qp(printer);
|
||||
QPainter qp(printer_);
|
||||
|
||||
// cas special : il n'y a aucun schema a imprimer
|
||||
if (!diagrams.count()) {
|
||||
qp.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// imprime les schemas
|
||||
for (int i = 0 ; i < diagrams.count() ; ++ i) {
|
||||
printDiagram(diagrams[i], fit_page, &qp, printer_);
|
||||
if (i != diagrams.count() - 1) {
|
||||
printer_ -> newPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Imprime un schema
|
||||
@param diagram Schema a imprimer
|
||||
@param fit_page True pour adapter les schemas aux pages, false sinon
|
||||
@param qp QPainter a utiliser (deja initialise sur printer)
|
||||
@param printer Imprimante a utiliser
|
||||
*/
|
||||
void DiagramPrintDialog::printDiagram(Diagram *diagram, bool fit_page, QPainter *qp, QPrinter *printer) {
|
||||
//qDebug() << printer -> paperSize() << printer -> paperRect() << diagram -> title();
|
||||
// l'imprimante utilise-t-elle toute la feuille ?
|
||||
bool full_page = printer -> fullPage ();
|
||||
|
||||
// impression physique (!= fichier PDF)
|
||||
if (printer -> outputFileName().isEmpty()) {
|
||||
@@ -275,15 +340,19 @@ void DiagramPrintDialog::print() {
|
||||
|
||||
if (fit_page) {
|
||||
// impression adaptee sur une seule page
|
||||
diagram -> render(&qp, QRectF(), diagram -> border(), Qt::KeepAspectRatio);
|
||||
diagram -> render(qp, QRectF(), diagram -> border(), Qt::KeepAspectRatio);
|
||||
} else {
|
||||
// impression sur une ou plusieurs pages
|
||||
QRect diagram_rect = diagram -> border().toRect();
|
||||
QRect diagram_rect = diagram -> border().adjusted(0.0, 0.0, 1.0, 1.0).toAlignedRect();
|
||||
QRect printed_area = full_page ? printer -> paperRect() : printer -> pageRect();
|
||||
//qDebug() << "impression sur une ou plusieurs pages";
|
||||
//qDebug() << " schema :" << diagram_rect;
|
||||
//qDebug() << " page :" << printed_area;
|
||||
|
||||
int used_width = printed_area.width();
|
||||
int used_height = printed_area.height();
|
||||
int h_pages_count = horizontalPagesCount(full_page);
|
||||
int v_pages_count = verticalPagesCount(full_page);
|
||||
int h_pages_count = horizontalPagesCount(diagram, full_page);
|
||||
int v_pages_count = verticalPagesCount(diagram, full_page);
|
||||
|
||||
QVector< QVector< QRect > > pages_grid;
|
||||
// le schema est imprime sur une matrice de feuilles
|
||||
@@ -312,18 +381,20 @@ void DiagramPrintDialog::print() {
|
||||
QVector<QRect> pages_to_print;
|
||||
for (int i = 0 ; i < v_pages_count ; ++ i) {
|
||||
for (int j = 0 ; j < h_pages_count ; ++ j) {
|
||||
int page_number = (i * h_pages_count) + j + 1;
|
||||
if (page_number >= first_page && page_number <= last_page) {
|
||||
//int page_number = (i * h_pages_count) + j + 1;
|
||||
//if (page_number >= first_page && page_number <= last_page) {
|
||||
pages_to_print << pages_grid.at(i).at(j);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
//qDebug() << " " << pages_to_print.count() << " pages a imprimer :";
|
||||
|
||||
// parcourt les pages pour impression
|
||||
for (int i = 0 ; i < pages_to_print.count() ; ++ i) {
|
||||
QRect current_rect(pages_to_print.at(i));
|
||||
//qDebug() << " " << current_rect;
|
||||
diagram -> render(
|
||||
&qp,
|
||||
qp,
|
||||
QRect(QPoint(0,0), current_rect.size()),
|
||||
current_rect.translated(diagram_rect.topLeft()),
|
||||
Qt::KeepAspectRatio
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#ifndef DIAGRAM_PRINT_DIALOG_H
|
||||
#define DIAGRAM_PRINT_DIALOG_H
|
||||
#include <QtGui>
|
||||
#include "qetproject.h"
|
||||
#include "diagram.h"
|
||||
/**
|
||||
Cette classe represente le dialogue de configuration de l'impression d'un
|
||||
@@ -29,48 +29,55 @@ class DiagramPrintDialog : public QWidget {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
DiagramPrintDialog(Diagram *, QWidget * = 0);
|
||||
DiagramPrintDialog(QETProject *, QWidget * = 0);
|
||||
virtual ~DiagramPrintDialog();
|
||||
private:
|
||||
DiagramPrintDialog(const DiagramPrintDialog &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setPDFName(const QString &);
|
||||
QString PDFName() const;
|
||||
void setFileName(const QString &);
|
||||
QString fileName() const;
|
||||
void setDocName(const QString &);
|
||||
QString docName() const;
|
||||
int pagesCount(bool = false) const;
|
||||
int horizontalPagesCount(bool = false) const;
|
||||
int verticalPagesCount(bool = false) const;
|
||||
int pagesCount(Diagram *, bool = false) const;
|
||||
int horizontalPagesCount(Diagram *, bool = false) const;
|
||||
int verticalPagesCount(Diagram *, bool = false) const;
|
||||
void exec();
|
||||
|
||||
private:
|
||||
void buildPrintTypeDialog();
|
||||
void buildDialog();
|
||||
void print();
|
||||
|
||||
private slots:
|
||||
void updateDialog();
|
||||
void checkStartPage();
|
||||
void checkEndPage();
|
||||
void setPagesRangeVisible(bool);
|
||||
void print(const QList<Diagram *> &, bool, QPrinter *);
|
||||
void printDiagram(Diagram *, bool, QPainter *, QPrinter * = 0);
|
||||
void updatePrintTypeDialog();
|
||||
void acceptPrintTypeDialog();
|
||||
void browseFilePrintTypeDialog();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
Diagram *diagram;
|
||||
QPrinter *printer;
|
||||
QString doc_name;
|
||||
QString pdf_name;
|
||||
QDialog *dialog;
|
||||
QLabel *options_label;
|
||||
QLabel *range_from_label;
|
||||
QLabel *to_label;
|
||||
QCheckBox *use_full_page;
|
||||
QLabel *use_full_page_label_;
|
||||
QCheckBox *fit_diagram_to_page;
|
||||
QLabel *fit_diagram_to_page_label_;
|
||||
QSpinBox *start_page;
|
||||
QSpinBox *end_page;
|
||||
QDialogButtonBox *buttons;
|
||||
QETProject *project_;
|
||||
QPrinter *printer_;
|
||||
QString doc_name_;
|
||||
QString file_name_;
|
||||
|
||||
/// Attributs relatifs au 1er dialogue
|
||||
QDialog *dialog_;
|
||||
QLabel *printtype_label_;
|
||||
QGridLayout *glayout0_;
|
||||
QVBoxLayout *vlayout0_;
|
||||
QHBoxLayout *hlayout0_;
|
||||
QLabel *printer_icon_;
|
||||
QLabel *pdf_icon_;
|
||||
QLabel *ps_icon_;
|
||||
QButtonGroup *printtype_choice_;
|
||||
QRadioButton *printer_choice_;
|
||||
QRadioButton *pdf_choice_;
|
||||
QRadioButton *ps_choice_;
|
||||
QLineEdit *filepath_field_;
|
||||
QPushButton *browse_button_;
|
||||
QDialogButtonBox *buttons_;
|
||||
};
|
||||
#endif
|
||||
|
||||
159
sources/diagramschooser.cpp
Normal file
159
sources/diagramschooser.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#include "diagramschooser.h"
|
||||
#include "qetproject.h"
|
||||
#include "diagram.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param project Projet dont il faut afficher les schemas
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
DiagramsChooser::DiagramsChooser(QETProject *project, QWidget *parent) :
|
||||
QFrame(parent),
|
||||
project_(project),
|
||||
vlayout0_(0)
|
||||
{
|
||||
setFrameShadow(QFrame::Sunken);
|
||||
setFrameShape(QFrame::StyledPanel);
|
||||
setLineWidth(3);
|
||||
setMidLineWidth(3);
|
||||
updateList();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
DiagramsChooser::~DiagramsChooser() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return le projet dont ce widget affiche les schemas
|
||||
*/
|
||||
QETProject *DiagramsChooser::project() const {
|
||||
return(project_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des schemas selectionnes
|
||||
*/
|
||||
QList<Diagram *> DiagramsChooser::selectedDiagrams() const {
|
||||
QList<Diagram *> selected_diagrams;
|
||||
foreach(Diagram *diagram, project_ -> diagrams()) {
|
||||
QCheckBox *check_box = diagrams_[diagram];
|
||||
if (check_box && check_box -> isChecked()) {
|
||||
selected_diagrams << diagram;
|
||||
}
|
||||
}
|
||||
return(selected_diagrams);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des schemas qui ne sont pas selectionnes
|
||||
*/
|
||||
QList<Diagram *> DiagramsChooser::nonSelectedDiagrams() const {
|
||||
QList<Diagram *> selected_diagrams;
|
||||
foreach(Diagram *diagram, diagrams_.keys()) {
|
||||
if (!(diagrams_[diagram] -> isChecked())) {
|
||||
selected_diagrams << diagram;
|
||||
}
|
||||
}
|
||||
return(selected_diagrams);
|
||||
}
|
||||
|
||||
/**
|
||||
@param diagram Un schema cense etre present dans ce widget
|
||||
*/
|
||||
bool DiagramsChooser::diagramIsSelected(Diagram *const diagram) const {
|
||||
QCheckBox *checkbox = diagrams_.value(diagram);
|
||||
if (!checkbox) return(false);
|
||||
return(checkbox -> isChecked());
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne les schemas contenus dans la liste diagrams_list
|
||||
@param diagrams_list Liste de schemas a selectionner
|
||||
@param select true pour selectionne les schemas de la liste, false pour les
|
||||
deselectionner
|
||||
@param reset true pour deselectionner tous les schemas avant de
|
||||
selectionner ceux de la liste
|
||||
*/
|
||||
void DiagramsChooser::setSelectedDiagrams(const QList<Diagram *> &diagrams_list, bool select, bool reset) {
|
||||
// evite d'emettre une rafale de signaux pour cette operation
|
||||
blockSignals(true);
|
||||
|
||||
// deselectionne tous les schemas si demande
|
||||
if (reset) {
|
||||
foreach(QCheckBox *check_box, diagrams_.values()) {
|
||||
check_box -> setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
int changes = 0;
|
||||
QCheckBox *check_box;
|
||||
foreach(Diagram *diagram, diagrams_list) {
|
||||
if ((check_box = diagrams_[diagram])) {
|
||||
if (check_box -> isChecked() != select) {
|
||||
check_box -> setChecked(select);
|
||||
++ changes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockSignals(false);
|
||||
if (reset || changes) {
|
||||
emit(selectionChanged());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne ou deselectionne tous les schemas
|
||||
@param select true pour selectionne les schemas de la liste, false pour les
|
||||
deselectionner
|
||||
*/
|
||||
void DiagramsChooser::setSelectedAllDiagrams(bool select) {
|
||||
blockSignals(true);
|
||||
foreach(QCheckBox *check_box, diagrams_.values()) {
|
||||
check_box -> setChecked(select);
|
||||
}
|
||||
blockSignals(false);
|
||||
emit(selectionChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la liste des schemas du projet
|
||||
*/
|
||||
void DiagramsChooser::updateList() {
|
||||
if (!project_) return;
|
||||
|
||||
// retient la liste des schemas deja selectionnes
|
||||
QList<Diagram *> selected_diagrams = selectedDiagrams();
|
||||
|
||||
// detruit les checkbox existantes
|
||||
QList<QCheckBox *> checkboxes = diagrams_.values();
|
||||
qDeleteAll(checkboxes.begin(), checkboxes.end());
|
||||
|
||||
buildLayout();
|
||||
|
||||
// recree les checkbox necessaires
|
||||
foreach(Diagram *diagram, project_ -> diagrams()) {
|
||||
// titre du schema
|
||||
QString diagram_title = diagram -> title();
|
||||
if (diagram_title.isEmpty()) diagram_title = tr("Sch\351ma sans titre");
|
||||
|
||||
QCheckBox *checkbox = new QCheckBox(diagram_title);
|
||||
checkbox -> setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum));
|
||||
checkbox -> setChecked(selected_diagrams.contains(diagram));
|
||||
connect(checkbox, SIGNAL(toggled(bool)), this, SIGNAL(selectionChanged()));
|
||||
diagrams_.insert(diagram, checkbox);
|
||||
vlayout0_ -> addWidget(checkbox, 0, Qt::AlignLeft | Qt::AlignTop);
|
||||
}
|
||||
vlayout0_ -> addStretch();
|
||||
}
|
||||
|
||||
/**
|
||||
Met en place la disposition du widget
|
||||
*/
|
||||
void DiagramsChooser::buildLayout() {
|
||||
if (vlayout0_) return;
|
||||
vlayout0_ = new QVBoxLayout();
|
||||
setLayout(vlayout0_);
|
||||
}
|
||||
61
sources/diagramschooser.h
Normal file
61
sources/diagramschooser.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef DIAGRAMS_CHOOSER_H
|
||||
#define DIAGRAMS_CHOOSER_H
|
||||
#include <QtGui>
|
||||
class QETProject;
|
||||
class Diagram;
|
||||
/**
|
||||
Cette classe represente un widget permettant de choisir 0 a n schemas parmi
|
||||
ceux d'un projet.
|
||||
*/
|
||||
class DiagramsChooser : public QFrame {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DiagramsChooser(QETProject *, QWidget * = 0);
|
||||
virtual ~DiagramsChooser();
|
||||
private:
|
||||
DiagramsChooser(const DiagramsChooser &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
QETProject *project() const;
|
||||
QList<Diagram *> selectedDiagrams() const;
|
||||
QList<Diagram *> nonSelectedDiagrams() const;
|
||||
bool diagramIsSelected(Diagram * const) const;
|
||||
void setSelectedDiagrams(const QList<Diagram *> &, bool = true, bool = true);
|
||||
void setSelectedAllDiagrams(bool = true);
|
||||
|
||||
public slots:
|
||||
void updateList();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
|
||||
private:
|
||||
void buildLayout();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QETProject *project_;
|
||||
QVBoxLayout *vlayout0_;
|
||||
QHash<Diagram *, QCheckBox *> diagrams_;
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -28,7 +28,7 @@ DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsTextItem(parent, scene)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFont(QFont(QETApp::diagramTextsFont(), 9));
|
||||
setFont(QFont(QETApp::diagramTextsFont(), QETApp::diagramTextsSize()));
|
||||
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
|
||||
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
|
||||
}
|
||||
@@ -44,7 +44,7 @@ DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, QGr
|
||||
previous_text(text)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFont(QFont(QETApp::diagramTextsFont(), 9));
|
||||
setFont(QFont(QETApp::diagramTextsFont(), QETApp::diagramTextsSize()));
|
||||
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
|
||||
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,48 +18,53 @@
|
||||
#include "diagramview.h"
|
||||
#include "diagram.h"
|
||||
#include "customelement.h"
|
||||
#include "exportdialog.h"
|
||||
#include "diagramprintdialog.h"
|
||||
#include "conductor.h"
|
||||
#include "diagramcommands.h"
|
||||
#include "conductorpropertieswidget.h"
|
||||
#include "insetpropertieswidget.h"
|
||||
#include "qetapp.h"
|
||||
#include "qetproject.h"
|
||||
#include "borderpropertieswidget.h"
|
||||
#include "integrationmoveelementshandler.h"
|
||||
#include "qetdiagrameditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent de cette vue de schema
|
||||
*/
|
||||
DiagramView::DiagramView(QWidget *parent) : QGraphicsView(parent), is_adding_text(false) {
|
||||
DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : QGraphicsView(parent), is_adding_text(false) {
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setInteractive(true);
|
||||
setCacheMode(QGraphicsView::CacheBackground);
|
||||
setOptimizationFlags(QGraphicsView::DontSavePainterState|QGraphicsView::DontAdjustForAntialiasing);
|
||||
|
||||
// active l'antialiasing
|
||||
setRenderHint(QPainter::Antialiasing, true);
|
||||
setRenderHint(QPainter::TextAntialiasing, true);
|
||||
setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
setScene(scene = new Diagram(this));
|
||||
scene = diagram ? diagram : new Diagram(this);
|
||||
setScene(scene);
|
||||
scene -> undoStack().setClean();
|
||||
setDragMode(RubberBandDrag);
|
||||
setAcceptDrops(true);
|
||||
setWindowIcon(QIcon(":/ico/qet-16.png"));
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
setSelectionMode();
|
||||
adjustSceneRect();
|
||||
updateWindowTitle();
|
||||
|
||||
context_menu = new QMenu(this);
|
||||
paste_here = new QAction(QIcon(":/ico/paste.png"), tr("Coller ici"), this);
|
||||
paste_here = new QAction(QIcon(":/ico/paste.png"), tr("Coller ici", "context menu action"), this);
|
||||
connect(paste_here, SIGNAL(triggered()), this, SLOT(pasteHere()));
|
||||
|
||||
connect(scene, SIGNAL(selectionEmptinessChanged()), this, SIGNAL(selectionChanged()));
|
||||
connect(scene, SIGNAL(readOnlyChanged(bool)), this, SLOT(applyReadOnly()));
|
||||
connect(&(scene -> border_and_inset), SIGNAL(borderChanged(QRectF, QRectF)), this, SLOT(adjustSceneRect()));
|
||||
connect(&(scene -> border_and_inset), SIGNAL(displayChanged()), this, SLOT(adjustSceneRect()));
|
||||
connect(&(scene -> border_and_inset), SIGNAL(diagramTitleChanged(const QString &)), this, SLOT(updateWindowTitle()));
|
||||
connect(&(scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(updateWindowTitle()));
|
||||
|
||||
connect(this, SIGNAL(aboutToAddElement()), this, SLOT(addDroppedElement()), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,6 +103,7 @@ void DiagramView::selectInvert() {
|
||||
Supprime les composants selectionnes
|
||||
*/
|
||||
void DiagramView::deleteSelection() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
DiagramContent removed_content = scene -> selectedContent();
|
||||
scene -> clearSelection();
|
||||
scene -> undoStack().push(new DeleteElementsCommand(scene, removed_content));
|
||||
@@ -108,6 +114,7 @@ void DiagramView::deleteSelection() {
|
||||
Pivote les composants selectionnes
|
||||
*/
|
||||
void DiagramView::rotateSelection() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
QHash<Element *, QET::Orientation> elements_to_rotate;
|
||||
foreach (QGraphicsItem *item, scene -> selectedItems()) {
|
||||
if (Element *e = qgraphicsitem_cast<Element *>(item)) {
|
||||
@@ -123,8 +130,11 @@ void DiagramView::rotateSelection() {
|
||||
@param e le QDragEnterEvent correspondant au drag'n drop tente
|
||||
*/
|
||||
void DiagramView::dragEnterEvent(QDragEnterEvent *e) {
|
||||
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
|
||||
else e-> ignore();
|
||||
if (e -> mimeData() -> hasFormat("application/x-qet-element-uri")) {
|
||||
e -> acceptProposedAction();
|
||||
} else {
|
||||
e -> ignore();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,18 +154,23 @@ void DiagramView::dragMoveEvent(QDragMoveEvent *e) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les depots (drop) acceptes sur le Diagram
|
||||
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
|
||||
*/
|
||||
void DiagramView::dropEvent(QDropEvent *e) {
|
||||
QString fichier = e -> mimeData() -> text();
|
||||
int etat;
|
||||
Element *el = new CustomElement(fichier, 0, 0, &etat);
|
||||
if (etat) delete el;
|
||||
else {
|
||||
diagram() -> undoStack().push(new AddElementCommand(diagram(), el, mapToScene(e -> pos())));
|
||||
adjustSceneRect();
|
||||
}
|
||||
// recupere l'emplacement de l'element depuis le drag'n drop
|
||||
QString elmt_path = e -> mimeData() -> text();
|
||||
ElementsLocation location(ElementsLocation::locationFromString(elmt_path));
|
||||
|
||||
// verifie qu'il existe un element correspondant a cet emplacement
|
||||
ElementsCollectionItem *dropped_item = QETApp::collectionItem(location);
|
||||
if (!dropped_item) return;
|
||||
|
||||
next_location_ = location;
|
||||
next_position_ = e-> pos();
|
||||
|
||||
emit(aboutToAddElement());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +178,7 @@ void DiagramView::dropEvent(QDropEvent *e) {
|
||||
*/
|
||||
void DiagramView::setVisualisationMode() {
|
||||
setDragMode(ScrollHandDrag);
|
||||
applyReadOnly();
|
||||
setInteractive(false);
|
||||
emit(modeChanged());
|
||||
}
|
||||
@@ -173,6 +189,7 @@ void DiagramView::setVisualisationMode() {
|
||||
void DiagramView::setSelectionMode() {
|
||||
setDragMode(RubberBandDrag);
|
||||
setInteractive(true);
|
||||
applyReadOnly();
|
||||
emit(modeChanged());
|
||||
}
|
||||
|
||||
@@ -238,6 +255,8 @@ void DiagramView::copy() {
|
||||
@param clipboard_mode Type de presse-papier a prendre en compte
|
||||
*/
|
||||
void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) {
|
||||
if (scene -> isReadOnly()) return;
|
||||
|
||||
QString texte_presse_papier = QApplication::clipboard() -> text(clipboard_mode);
|
||||
if ((texte_presse_papier).isEmpty()) return;
|
||||
|
||||
@@ -270,7 +289,7 @@ void DiagramView::mousePressEvent(QMouseEvent *e) {
|
||||
if (e -> buttons() == Qt::MidButton) {
|
||||
paste(mapToScene(e -> pos()), QClipboard::Selection);
|
||||
} else {
|
||||
if (is_adding_text && e -> buttons() == Qt::LeftButton) {
|
||||
if (!scene -> isReadOnly() && is_adding_text && e -> buttons() == Qt::LeftButton) {
|
||||
addDiagramTextAtPos(mapToScene(e -> pos()));
|
||||
is_adding_text = false;
|
||||
}
|
||||
@@ -278,199 +297,6 @@ void DiagramView::mousePressEvent(QMouseEvent *e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Ouvre un fichier *.qet dans cette DiagramView
|
||||
@param n_fichier Nom du fichier a ouvrir
|
||||
@param erreur Si le pointeur est specifie, cet entier est mis a 0 en cas de reussite de l'ouverture, 1 si le fichier n'existe pas, 2 si le fichier n'est pas lisible, 3 si le fichier n'est pas un element XML, 4 si l'ouverture du fichier a echoue pour une autre raison (c'est pas ca qui manque ^^)
|
||||
@return true si l'ouverture a reussi, false sinon
|
||||
*/
|
||||
bool DiagramView::open(QString n_fichier, int *erreur) {
|
||||
// verifie l'existence du fichier
|
||||
if (!QFileInfo(n_fichier).exists()) {
|
||||
if (erreur != NULL) *erreur = 1;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// ouvre le fichier
|
||||
QFile fichier(n_fichier);
|
||||
if (!fichier.open(QIODevice::ReadOnly)) {
|
||||
if (erreur != NULL) *erreur = 2;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// lit son contenu dans un QDomDocument
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&fichier)) {
|
||||
if (erreur != NULL) *erreur = 3;
|
||||
fichier.close();
|
||||
return(false);
|
||||
}
|
||||
fichier.close();
|
||||
|
||||
/**
|
||||
La notion de projet (ensemble de documents [schemas, nomenclatures,
|
||||
...] et d'elements) n'est pas encore geree.
|
||||
Toutefois, pour gerer au mieux la transition de la 0.1 a la 0.2,
|
||||
les schemas enregistres (element XML "diagram") sont integres dans un
|
||||
pseudo projet (element XML "project").
|
||||
S'il y a plusieurs schemas dans un projet, tous les schemas seront
|
||||
ouverts comme etant des fichiers separes
|
||||
*/
|
||||
// repere les schemas dans le fichier
|
||||
QDomElement root = document.documentElement();
|
||||
// cas 1 : l'element racine est un "diagram" : un seul schema, pas de probleme
|
||||
if (root.tagName() == "diagram") {
|
||||
// construit le schema a partir du QDomDocument
|
||||
QDomDocument &doc = document;
|
||||
if (scene -> fromXml(doc)) {
|
||||
if (erreur != NULL) *erreur = 0;
|
||||
file_name = n_fichier;
|
||||
scene -> undoStack().setClean();
|
||||
updateWindowTitle();
|
||||
return(true);
|
||||
} else {
|
||||
if (erreur != NULL) *erreur = 4;
|
||||
return(false);
|
||||
}
|
||||
// cas 2 : l'element racine est un "project"
|
||||
} else if (root.tagName() == "project") {
|
||||
// verifie basiquement que la version actuelle est capable de lire ce fichier
|
||||
if (root.hasAttribute("version")) {
|
||||
bool conv_ok;
|
||||
qreal diagram_version = root.attribute("version").toDouble(&conv_ok);
|
||||
if (conv_ok && QET::version.toDouble() < diagram_version) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Avertissement"),
|
||||
tr("Ce document semble avoir \351t\351 enregistr\351 avec une "
|
||||
"version ult\351rieure de QElectroTech. Il est possible que "
|
||||
"l'ouverture de tout ou partie de ce document \351choue.")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// compte le nombre de schemas dans le projet
|
||||
QList<QDomElement> diagrams;
|
||||
|
||||
QDomNodeList diagram_nodes = root.elementsByTagName("diagram");
|
||||
for (uint i = 0 ; i < diagram_nodes.length() ; ++ i) {
|
||||
if (diagram_nodes.at(i).isElement()) {
|
||||
diagrams << diagram_nodes.at(i).toElement();
|
||||
}
|
||||
}
|
||||
|
||||
// il n'y aucun schema la-dedans
|
||||
if (!diagrams.count()) {
|
||||
if (erreur != NULL) *erreur = 4;
|
||||
return(false);
|
||||
} else {
|
||||
|
||||
bool keep_doc_name = diagrams.count() == 1;
|
||||
bool current_dv_loaded = false;
|
||||
for (int i = 0 ; i < diagrams.count() ; ++ i) {
|
||||
// cree un QDomDocument representant le schema
|
||||
QDomDocument diagram_doc;
|
||||
diagram_doc.appendChild(diagram_doc.importNode(diagrams[i], true));
|
||||
|
||||
// charge le premier schema valide et cree de nouveau DiagramView pour les suivants
|
||||
if (!current_dv_loaded) {
|
||||
if (scene -> fromXml(diagram_doc)) {
|
||||
if (keep_doc_name) file_name = n_fichier;
|
||||
scene -> undoStack().setClean();
|
||||
updateWindowTitle();
|
||||
current_dv_loaded = true;
|
||||
}
|
||||
} else {
|
||||
DiagramView *new_dv = new DiagramView(parentWidget());
|
||||
if (new_dv -> scene -> fromXml(diagram_doc)) {
|
||||
if (keep_doc_name) new_dv -> file_name = n_fichier;
|
||||
new_dv -> scene -> undoStack().setClean();
|
||||
new_dv -> updateWindowTitle();
|
||||
diagramEditor() -> addDiagramView(new_dv);
|
||||
} else {
|
||||
delete(new_dv);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (erreur != NULL) *erreur = 4;
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere la fermeture du schema.
|
||||
@param event Le QCloseEvent decrivant l'evenement
|
||||
*/
|
||||
void DiagramView::closeEvent(QCloseEvent *event) {
|
||||
bool retour;
|
||||
// si le schema est modifie
|
||||
if (!isWindowModified()) {
|
||||
retour = true;
|
||||
} else {
|
||||
// demande d'abord a l'utilisateur s'il veut enregistrer le schema en cours
|
||||
QMessageBox::StandardButton reponse = QMessageBox::question(
|
||||
this,
|
||||
tr("Enregistrer le sch\351ma en cours ?"),
|
||||
tr("Voulez-vous enregistrer le sch\351ma ") + windowTitle() + tr(" ?"),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
switch(reponse) {
|
||||
case QMessageBox::Cancel: retour = false; break; // l'utilisateur annule : echec de la fermeture
|
||||
case QMessageBox::Yes: retour = save(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
|
||||
default: retour = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
|
||||
}
|
||||
}
|
||||
if (retour) event -> accept();
|
||||
else event -> ignore();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Methode enregistrant le schema dans le dernier nom de fichier connu.
|
||||
Si aucun nom de fichier n'est connu, cette methode appelle la methode saveAs
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
*/
|
||||
bool DiagramView::save() {
|
||||
if (file_name.isEmpty()) return(saveAs());
|
||||
else return(saveDiagramToFile(file_name));
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode demande un nom de fichier a l'utilisateur pour enregistrer le schema
|
||||
Si aucun nom n'est entre, elle renvoie faux.
|
||||
Si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee.
|
||||
Si l'enregistrement reussit, le nom du fichier est conserve et la fonction renvoie true.
|
||||
Sinon, faux est renvoye.
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
*/
|
||||
bool DiagramView::saveAs() {
|
||||
// demande un nom de fichier a l'utilisateur pour enregistrer le schema
|
||||
QString n_fichier = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Enregistrer sous"),
|
||||
(file_name.isEmpty() ? QDir::homePath() : QDir(file_name)).absolutePath(),
|
||||
tr("Sch\351ma QElectroTech (*.qet)")
|
||||
);
|
||||
// si aucun nom n'est entre, renvoie faux.
|
||||
if (n_fichier.isEmpty()) return(false);
|
||||
// si le nom ne se termine pas par l'extension .qet, celle-ci est ajoutee
|
||||
if (!n_fichier.endsWith(".qet", Qt::CaseInsensitive)) n_fichier += ".qet";
|
||||
// tente d'enregistrer le fichier
|
||||
bool resultat_enregistrement = saveDiagramToFile(n_fichier);
|
||||
// si l'enregistrement reussit, le nom du fichier est conserve
|
||||
if (resultat_enregistrement) {
|
||||
file_name = n_fichier;
|
||||
updateWindowTitle();
|
||||
}
|
||||
// retourne un booleen representatif de la reussite de l'enregistrement
|
||||
return(resultat_enregistrement);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les actions liees a la rollette de la souris
|
||||
@param e QWheelEvent decrivant l'evenement rollette
|
||||
@@ -489,70 +315,28 @@ void DiagramView::wheelEvent(QWheelEvent *e) {
|
||||
}
|
||||
|
||||
/**
|
||||
Methode privee gerant l'enregistrement du fichier XML. S'il n'est pas possible
|
||||
d'ecrire dans le fichier, cette fonction affiche un message d'erreur et renvoie false.
|
||||
Autrement, elle renvoie true.
|
||||
@param n_fichier Nom du fichier dans lequel l'arbre XML doit etre ecrit
|
||||
@return true si l'enregistrement a reussi, false sinon
|
||||
@return le titre de cette vue ; cela correspond au titre du schema
|
||||
visualise precede de la mention "Schema". Si le titre du schema est vide,
|
||||
la mention "Schema sans titre" est utilisee
|
||||
@see Diagram::title()
|
||||
*/
|
||||
bool DiagramView::saveDiagramToFile(QString &n_fichier) {
|
||||
QFile fichier(n_fichier);
|
||||
if (!fichier.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
|
||||
return(false);
|
||||
}
|
||||
QTextStream out(&fichier);
|
||||
out.setCodec("UTF-8");
|
||||
|
||||
// l'export XML du schema est encapsule dans un pseudo-projet
|
||||
QDomDocument final_document;
|
||||
QDomElement project_root = final_document.createElement("project");
|
||||
project_root.setAttribute("version", QET::version);
|
||||
project_root.appendChild(final_document.importNode(scene -> toXml().documentElement(), true));
|
||||
final_document.appendChild(project_root);
|
||||
|
||||
out << final_document.toString(4);
|
||||
fichier.close();
|
||||
scene -> undoStack().setClean();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le schema.
|
||||
*/
|
||||
void DiagramView::dialogExport() {
|
||||
ExportDialog ed(scene, diagramEditor());
|
||||
ed.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Imprime le schema.
|
||||
*/
|
||||
void DiagramView::dialogPrint() {
|
||||
|
||||
// determine un nom possible pour le document et le pdf
|
||||
QString doc_name;
|
||||
QString pdf_file_name;
|
||||
if (!file_name.isEmpty()) {
|
||||
doc_name = QFileInfo(file_name).fileName();
|
||||
pdf_file_name = file_name;
|
||||
pdf_file_name.replace(QRegExp("\\.qet$", Qt::CaseInsensitive), "");
|
||||
QString DiagramView::title() const {
|
||||
QString view_title;
|
||||
QString diagram_title(scene -> title());
|
||||
if (diagram_title.isEmpty()) {
|
||||
view_title = tr("Sch\351ma sans titre");
|
||||
} else {
|
||||
doc_name = tr("schema");
|
||||
pdf_file_name = QDir::toNativeSeparators(QDir::homePath() + "/" + tr("schema"));
|
||||
view_title = QString(tr("Sch\351ma %1", "%1 is a diagram title")).arg(diagram_title);
|
||||
}
|
||||
pdf_file_name += ".pdf";
|
||||
|
||||
DiagramPrintDialog print_dialog(scene, this);
|
||||
print_dialog.setDocName(doc_name);
|
||||
print_dialog.setPDFName(pdf_file_name);
|
||||
print_dialog.exec();
|
||||
return(view_title);
|
||||
}
|
||||
|
||||
/**
|
||||
Edite les informations du schema.
|
||||
*/
|
||||
void DiagramView::dialogEditInfos() {
|
||||
void DiagramView::editDiagramProperties() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
|
||||
// recupere le cartouche et les dimensions du schema
|
||||
InsetProperties inset = scene -> border_and_inset.exportInset();
|
||||
BorderProperties border = scene -> border_and_inset.exportBorder();
|
||||
@@ -560,7 +344,7 @@ void DiagramView::dialogEditInfos() {
|
||||
// construit le dialogue
|
||||
QDialog popup(diagramEditor());
|
||||
popup.setMinimumWidth(400);
|
||||
popup.setWindowTitle(tr("Propri\351t\351s du sch\351ma"));
|
||||
popup.setWindowTitle(tr("Propri\351t\351s du sch\351ma", "window title"));
|
||||
|
||||
BorderPropertiesWidget *border_infos = new BorderPropertiesWidget(border, &popup);
|
||||
InsetPropertiesWidget *inset_infos = new InsetPropertiesWidget(inset, false, &popup);
|
||||
@@ -603,6 +387,7 @@ bool DiagramView::hasSelectedItems() {
|
||||
Ajoute une colonne au schema.
|
||||
*/
|
||||
void DiagramView::addColumn() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
BorderProperties old_bp = scene -> border_and_inset.exportBorder();
|
||||
BorderProperties new_bp = scene -> border_and_inset.exportBorder();
|
||||
new_bp.columns_count += 1;
|
||||
@@ -613,6 +398,7 @@ void DiagramView::addColumn() {
|
||||
Enleve une colonne au schema.
|
||||
*/
|
||||
void DiagramView::removeColumn() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
BorderProperties old_bp = scene -> border_and_inset.exportBorder();
|
||||
BorderProperties new_bp = scene -> border_and_inset.exportBorder();
|
||||
new_bp.columns_count -= 1;
|
||||
@@ -623,6 +409,7 @@ void DiagramView::removeColumn() {
|
||||
Agrandit le schema en hauteur
|
||||
*/
|
||||
void DiagramView::addRow() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
BorderProperties old_bp = scene -> border_and_inset.exportBorder();
|
||||
BorderProperties new_bp = scene -> border_and_inset.exportBorder();
|
||||
new_bp.rows_count += 1;
|
||||
@@ -633,6 +420,7 @@ void DiagramView::addRow() {
|
||||
Retrecit le schema en hauteur
|
||||
*/
|
||||
void DiagramView::removeRow() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
BorderProperties old_bp = scene -> border_and_inset.exportBorder();
|
||||
BorderProperties new_bp = scene -> border_and_inset.exportBorder();
|
||||
new_bp.rows_count -= 1;
|
||||
@@ -665,12 +453,19 @@ void DiagramView::adjustSceneRect() {
|
||||
Met a jour le titre du widget
|
||||
*/
|
||||
void DiagramView::updateWindowTitle() {
|
||||
QString window_title;
|
||||
if (file_name.isNull()) window_title += tr("nouveau sch\351ma");
|
||||
else window_title += file_name;
|
||||
window_title += "[*]";
|
||||
setWindowTitle(window_title);
|
||||
setWindowModified(!(scene -> undoStack().isClean()));
|
||||
QString view_title(title());
|
||||
|
||||
// verifie si le document a ete modifie
|
||||
bool modified_diagram = !(scene -> undoStack().isClean());
|
||||
|
||||
// specifie le titre du widget
|
||||
setWindowTitle(view_title + " [*]");
|
||||
setWindowModified(modified_diagram);
|
||||
|
||||
// emet le signal titleChanged en ajoutant manuellement [*] si le schema a ete modifie
|
||||
QString emitted_title = view_title;
|
||||
if (modified_diagram) emitted_title += " [*]";
|
||||
emit(titleChanged(this, emitted_title));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,6 +494,63 @@ QRectF DiagramView::viewedSceneRect() const {
|
||||
return(QRectF(scene_left_top, scene_right_bottom));
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode permet de determiner s'il faut ou non integrer au projet un
|
||||
element dont on connait l'emplacement.
|
||||
L'element droppe est integre a la collection du projet :
|
||||
* s'il appartient a un autre projet, quelque soit la specification de
|
||||
l'utilisateur a ce propos ;
|
||||
* s'il appartient a la collection commune ou a la collection
|
||||
personnelle ET que l'utilisateur a autorise l'integration automatique
|
||||
des elements dans les projets.
|
||||
@param location Emplacement de l'element
|
||||
@return true si l'element doit etre integre, false sinon
|
||||
|
||||
*/
|
||||
bool DiagramView::mustIntegrateElement(const ElementsLocation &location) const {
|
||||
// l'utilisateur a-t-il autorise l'integration automatique des elements dans les projets ?
|
||||
bool auto_integration_enabled = QETApp::settings().value("diagrameditor/integrate-elements", true).toBool();
|
||||
|
||||
// l'element appartient-il a un projet et si oui, est-ce un autre projet ?
|
||||
bool elmt_from_project = location.project();
|
||||
bool elmt_from_another_project = elmt_from_project && location.project() != scene -> project();
|
||||
|
||||
// faut-il integrer l'element ?
|
||||
bool must_integrate_element = (elmt_from_another_project || (auto_integration_enabled && !elmt_from_project));
|
||||
|
||||
return(must_integrate_element);
|
||||
}
|
||||
|
||||
/**
|
||||
@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
|
||||
*/
|
||||
bool DiagramView::addElementAtPos(const ElementsLocation &location, const QPoint &pos) {
|
||||
// construit une instance de l'element correspondant a l'emplacement
|
||||
int etat;
|
||||
Element *el = new CustomElement(location, 0, 0, &etat);
|
||||
if (etat) {
|
||||
delete el;
|
||||
return(false);
|
||||
}
|
||||
|
||||
// pose de l'element sur le schema
|
||||
diagram() -> undoStack().push(new AddElementCommand(diagram(), el, mapToScene(pos)));
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Fait en sorte que le schema ne soit editable que s'il n'est pas en lecture
|
||||
seule
|
||||
*/
|
||||
void DiagramView::applyReadOnly() {
|
||||
if (!scene) return;
|
||||
|
||||
bool is_writable = !scene -> isReadOnly();
|
||||
setInteractive(is_writable);
|
||||
setAcceptDrops(is_writable);
|
||||
}
|
||||
|
||||
/**
|
||||
Affiche un dialogue permettant d'editer le conducteur selectionne.
|
||||
Ne fait rien s'il y a 0 ou plusieurs conducteurs selectionnes.
|
||||
@@ -718,6 +570,7 @@ void DiagramView::editConductor() {
|
||||
@param edited_conductor Conducteur a editer
|
||||
*/
|
||||
void DiagramView::editConductor(Conductor *edited_conductor) {
|
||||
if (scene -> isReadOnly()) return;
|
||||
if (!edited_conductor) return;
|
||||
|
||||
// initialise l'editeur de proprietes pour le conducteur
|
||||
@@ -726,7 +579,7 @@ void DiagramView::editConductor(Conductor *edited_conductor) {
|
||||
|
||||
// l'insere dans un dialogue
|
||||
QDialog conductor_dialog(diagramEditor());
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s d'un conducteur"));
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s d'un conducteur", "window title"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
|
||||
dialog_layout -> addWidget(cpw);
|
||||
dialog_layout -> addStretch();
|
||||
@@ -754,6 +607,7 @@ void DiagramView::editConductor(Conductor *edited_conductor) {
|
||||
Reinitialise le profil des conducteurs selectionnes
|
||||
*/
|
||||
void DiagramView::resetConductors() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
// recupere les conducteurs selectionnes
|
||||
QSet<Conductor *> selected_conductors = scene -> selectedConductors();
|
||||
|
||||
@@ -780,12 +634,13 @@ void DiagramView::resetConductors() {
|
||||
futurs nouveaux conducteurs
|
||||
*/
|
||||
void DiagramView::editDefaultConductorProperties() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
// initialise l'editeur de proprietes pour le conducteur
|
||||
ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(scene -> defaultConductorProperties);
|
||||
|
||||
// l'insere dans un dialogue
|
||||
QDialog conductor_dialog(diagramEditor());
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s par d\351faut des conducteurs"));
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s par d\351faut des conducteurs", "window title"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
|
||||
dialog_layout -> addWidget(cpw);
|
||||
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
@@ -818,6 +673,7 @@ bool DiagramView::event(QEvent *e) {
|
||||
nouveau champ de texte.
|
||||
*/
|
||||
void DiagramView::addText() {
|
||||
if (scene -> isReadOnly()) return;
|
||||
is_adding_text = true;
|
||||
}
|
||||
|
||||
@@ -935,8 +791,36 @@ void DiagramView::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
}
|
||||
} else if (inset_rect.contains(click_pos) || columns_rect.contains(click_pos) || rows_rect.contains(click_pos)) {
|
||||
// edite les proprietes du schema
|
||||
dialogEditInfos();
|
||||
editDiagramProperties();
|
||||
} else {
|
||||
QGraphicsView::mouseDoubleClickEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Cette methode ajoute l'element deisgne par l'emplacement location a la
|
||||
position pos. Si necessaire, elle demande l'integration de l'element au
|
||||
projet.
|
||||
@param location emplacement d'un element a ajouter sur le schema
|
||||
@param pos position voulue de l'element sur le schema
|
||||
@see mustIntegrateElement
|
||||
*/
|
||||
void DiagramView::addDroppedElement() {
|
||||
ElementsLocation location = next_location_;
|
||||
QPoint pos = next_position_;
|
||||
|
||||
if (!mustIntegrateElement(location)) {
|
||||
addElementAtPos(location, pos);
|
||||
} else {
|
||||
QString error_msg;
|
||||
IntegrationMoveElementsHandler *integ_handler = new IntegrationMoveElementsHandler(this);
|
||||
QString integ_path = scene -> project() -> integrateElement(location.toString(), integ_handler, error_msg);
|
||||
delete integ_handler;
|
||||
if (integ_path.isEmpty()) {
|
||||
qDebug() << error_msg;
|
||||
return;
|
||||
}
|
||||
addElementAtPos(ElementsLocation::locationFromString(integ_path), pos);
|
||||
}
|
||||
adjustSceneRect();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,6 +18,7 @@
|
||||
#ifndef DIAGRAMVIEW_H
|
||||
#define DIAGRAMVIEW_H
|
||||
#include <QtGui>
|
||||
#include "elementslocation.h"
|
||||
class Diagram;
|
||||
class DiagramTextItem;
|
||||
class QETDiagramEditor;
|
||||
@@ -30,33 +31,26 @@ class DiagramView : public QGraphicsView {
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DiagramView(QWidget * = 0);
|
||||
DiagramView(Diagram * = 0, QWidget * = 0);
|
||||
virtual ~DiagramView();
|
||||
|
||||
private:
|
||||
DiagramView(const DiagramView &);
|
||||
|
||||
// attributs
|
||||
public:
|
||||
/// Nom de fichier du schema edite
|
||||
QString file_name;
|
||||
|
||||
private:
|
||||
Diagram *scene;
|
||||
QMenu *context_menu;
|
||||
QAction *paste_here;
|
||||
QPoint paste_here_pos;
|
||||
bool is_adding_text;
|
||||
ElementsLocation next_location_;
|
||||
QPoint next_position_;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool open(QString, int * = NULL);
|
||||
void closeEvent(QCloseEvent *);
|
||||
bool save();
|
||||
bool saveAs();
|
||||
void dialogExport();
|
||||
void dialogEditInfos();
|
||||
void dialogPrint();
|
||||
QString title() const;
|
||||
void editDiagramProperties();
|
||||
void addColumn();
|
||||
void removeColumn();
|
||||
void addRow();
|
||||
@@ -75,13 +69,14 @@ class DiagramView : public QGraphicsView {
|
||||
virtual bool event(QEvent *);
|
||||
|
||||
private:
|
||||
bool saveDiagramToFile(QString &);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void dragEnterEvent(QDragEnterEvent *);
|
||||
void dragLeaveEvent(QDragLeaveEvent *);
|
||||
void dragMoveEvent(QDragMoveEvent *);
|
||||
void dropEvent(QDropEvent *);
|
||||
QRectF viewedSceneRect() const;
|
||||
bool mustIntegrateElement(const ElementsLocation &) const;
|
||||
bool addElementAtPos(const ElementsLocation &, const QPoint &);
|
||||
|
||||
signals:
|
||||
/// Signal emis lorsque la selection change
|
||||
@@ -90,6 +85,10 @@ class DiagramView : public QGraphicsView {
|
||||
void modeChanged();
|
||||
/// Signal emis lorsqu'un texte a ete pose
|
||||
void textAdded(bool);
|
||||
/// Signal emis lorsque le titre du schema change
|
||||
void titleChanged(DiagramView *, const QString &);
|
||||
/// Signal emis avant l'integration d'un element
|
||||
void aboutToAddElement();
|
||||
|
||||
public slots:
|
||||
void selectNothing();
|
||||
@@ -115,6 +114,8 @@ class DiagramView : public QGraphicsView {
|
||||
void editDefaultConductorProperties();
|
||||
|
||||
private slots:
|
||||
void addDroppedElement();
|
||||
void adjustGridToZoom();
|
||||
void applyReadOnly();
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -74,6 +74,7 @@ class CustomElementGraphicPart : public CustomElementPart {
|
||||
|
||||
/// Destructeur
|
||||
virtual ~CustomElementGraphicPart() {
|
||||
if (style_editor -> parentWidget()) return; // l'editeur de style sera supprime par son parent
|
||||
delete style_editor;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -29,7 +29,7 @@ DeletePartsCommand::DeletePartsCommand(
|
||||
const QList<QGraphicsItem *> parts,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("suppression"), parent),
|
||||
QUndoCommand(QObject::tr("suppression", "undo caption"), parent),
|
||||
deleted_parts(parts),
|
||||
editor_scene(scene)
|
||||
{
|
||||
@@ -59,6 +59,94 @@ void DeletePartsCommand::redo() {
|
||||
}
|
||||
}
|
||||
|
||||
/*** CutPartsCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@param scene ElementScene concernee
|
||||
@param parts Liste des parties collees
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
PastePartsCommand::PastePartsCommand(
|
||||
ElementView *view,
|
||||
const ElementContent &c,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(parent),
|
||||
content_(c),
|
||||
editor_view_(view),
|
||||
editor_scene_(view -> scene()),
|
||||
uses_offset(false),
|
||||
first_redo(true)
|
||||
{
|
||||
setText(QObject::tr("coller"));
|
||||
editor_scene_ -> qgiManager().manage(content_);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PastePartsCommand::~PastePartsCommand() {
|
||||
editor_scene_ -> qgiManager().release(content_);
|
||||
}
|
||||
|
||||
/// annule le coller
|
||||
void PastePartsCommand::undo() {
|
||||
// enleve les parties
|
||||
foreach(QGraphicsItem *part, content_) editor_scene_ -> removeItem(part);
|
||||
if (uses_offset) {
|
||||
editor_view_ -> offset_paste_count_ = old_offset_paste_count_;
|
||||
editor_view_ -> start_top_left_corner_ = old_start_top_left_corner_;
|
||||
}
|
||||
editor_view_ -> adjustSceneRect();
|
||||
}
|
||||
|
||||
/// refait le coller
|
||||
void PastePartsCommand::redo() {
|
||||
if (first_redo) first_redo = false;
|
||||
else {
|
||||
// pose les parties
|
||||
foreach(QGraphicsItem *part, content_) editor_scene_ -> addItem(part);
|
||||
if (uses_offset) {
|
||||
editor_view_ -> offset_paste_count_ = new_offset_paste_count_;
|
||||
editor_view_ -> start_top_left_corner_ = new_start_top_left_corner_;
|
||||
}
|
||||
}
|
||||
foreach(QGraphicsItem *part, content_) part -> setSelected(true);
|
||||
editor_view_ -> adjustSceneRect();
|
||||
}
|
||||
|
||||
/**
|
||||
Indique a cet objet d'annulation que le c/c a annuler ou refaire etait un
|
||||
c/c avec decalage ; il faut plus d'informations pour annuler ce type de
|
||||
collage.
|
||||
*/
|
||||
void PastePartsCommand::setOffset(int old_offset_pc, const QPointF &old_start_tlc, int new_offset_pc, const QPointF &new_start_tlc) {
|
||||
old_offset_paste_count_ = old_offset_pc;
|
||||
old_start_top_left_corner_ = old_start_tlc;
|
||||
new_offset_paste_count_ = new_offset_pc;
|
||||
new_start_top_left_corner_ = new_start_tlc;
|
||||
uses_offset = true;
|
||||
}
|
||||
|
||||
/*** CutPartsCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@param scene ElementScene concernee
|
||||
@param parts Liste des parties coupees
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
CutPartsCommand::CutPartsCommand(
|
||||
ElementScene *scene,
|
||||
const QList<QGraphicsItem *> parts,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
DeletePartsCommand(scene, parts, parent)
|
||||
{
|
||||
setText(QString(QObject::tr("couper des parties", "undo caption")));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
CutPartsCommand::~CutPartsCommand() {
|
||||
}
|
||||
|
||||
/*** MovePartsCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@@ -73,7 +161,7 @@ MovePartsCommand::MovePartsCommand(
|
||||
const QList<QGraphicsItem *> parts,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("d\351placement"), parent),
|
||||
QUndoCommand(QObject::tr("d\351placement", "undo caption"), parent),
|
||||
movement(m),
|
||||
first_redo(true)
|
||||
{
|
||||
@@ -114,7 +202,7 @@ AddPartCommand::AddPartCommand(
|
||||
QGraphicsItem *p,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajout ") + name, parent),
|
||||
QUndoCommand(QString(QObject::tr("ajout %1", "undo caption")).arg(name), parent),
|
||||
part(p),
|
||||
editor_scene(scene),
|
||||
first_redo(true)
|
||||
@@ -161,7 +249,7 @@ ChangePartCommand::ChangePartCommand(
|
||||
const QVariant &new_v,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification ") + name, parent),
|
||||
QUndoCommand(QString(QObject::tr("modification %1", "undo caption")).arg(name), parent),
|
||||
cep(part),
|
||||
property(prop),
|
||||
old_value(old_v),
|
||||
@@ -196,7 +284,7 @@ ChangePolygonPointsCommand::ChangePolygonPointsCommand(
|
||||
const QVector<QPointF> &n_points,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification points polygone"), parent),
|
||||
QUndoCommand(QObject::tr("modification points polygone", "undo caption"), parent),
|
||||
polygon(p),
|
||||
old_points(o_points),
|
||||
new_points(n_points)
|
||||
@@ -236,7 +324,7 @@ ChangeHotspotCommand::ChangeHotspotCommand(
|
||||
const QPoint &o,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification dimensions/hotspot"), parent),
|
||||
QUndoCommand(QObject::tr("modification dimensions/hotspot", "undo caption"), parent),
|
||||
element(element_scene),
|
||||
size_before(size_1),
|
||||
size_after(size_2),
|
||||
@@ -297,7 +385,7 @@ ChangeNamesCommand::ChangeNamesCommand(
|
||||
const NamesList &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification noms"), parent),
|
||||
QUndoCommand(QObject::tr("modification noms", "undo caption"), parent),
|
||||
names_before(before),
|
||||
names_after(after),
|
||||
element(element_scene)
|
||||
@@ -331,7 +419,7 @@ ChangeOrientationsCommand::ChangeOrientationsCommand(
|
||||
const OrientationSet &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification orientations"), parent),
|
||||
QUndoCommand(QObject::tr("modification orientations", "undo caption"), parent),
|
||||
ori_before(before),
|
||||
ori_after(after),
|
||||
element(element_scene)
|
||||
@@ -375,16 +463,16 @@ ChangeZValueCommand::ChangeZValueCommand(
|
||||
|
||||
// choisit le nom en fonction du traitement
|
||||
if (option == BringForward) {
|
||||
setText(QObject::tr("amener au premier plan"));
|
||||
setText(QObject::tr("amener au premier plan", "undo caption"));
|
||||
applyBringForward(items_list);
|
||||
} else if (option == Raise) {
|
||||
setText(QObject::tr("rapprocher"));
|
||||
setText(QObject::tr("rapprocher", "undo caption"));
|
||||
applyRaise(items_list);
|
||||
} else if (option == Lower) {
|
||||
setText(QObject::tr("\351loigner"));
|
||||
setText(QObject::tr("\351loigner", "undo caption"));
|
||||
applyLower(items_list);
|
||||
} else if (option == SendBackward) {
|
||||
setText(QObject::tr("envoyer au fond"));
|
||||
setText(QObject::tr("envoyer au fond", "undo caption"));
|
||||
applySendBackward(items_list);
|
||||
}
|
||||
}
|
||||
@@ -483,7 +571,7 @@ void ChangeZValueCommand::applySendBackward(const QList<QGraphicsItem *> &items_
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AllowInternalConnectionsCommand::AllowInternalConnectionsCommand(ElementScene *elmt, bool allow, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modification connexions internes"), parent),
|
||||
QUndoCommand(QObject::tr("modification connexions internes", "undo caption"), parent),
|
||||
element(elmt),
|
||||
ic(allow)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,7 +19,9 @@
|
||||
#define EDITOR_COMMANDS_H
|
||||
#include "customelementpart.h"
|
||||
#include "partpolygon.h"
|
||||
#include "elementview.h"
|
||||
#include "elementscene.h"
|
||||
#include "elementcontent.h"
|
||||
#include "qgimanager.h"
|
||||
#include <QtGui>
|
||||
/**
|
||||
@@ -47,6 +49,52 @@ class DeletePartsCommand : public QUndoCommand {
|
||||
ElementScene *editor_scene;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de coller quelque chose dans un element
|
||||
*/
|
||||
class PastePartsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PastePartsCommand(ElementView *, const ElementContent &, QUndoCommand * = 0);
|
||||
virtual ~PastePartsCommand();
|
||||
private:
|
||||
PastePartsCommand(const PastePartsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
virtual void setOffset(int, const QPointF &, int, const QPointF &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// contenu ajoute
|
||||
ElementContent content_;
|
||||
/// schema sur lequel on colle les elements et conducteurs
|
||||
ElementView *editor_view_;
|
||||
ElementScene *editor_scene_;
|
||||
/// Informations pour annuler un c/c avec decalage
|
||||
int old_offset_paste_count_;
|
||||
QPointF old_start_top_left_corner_;
|
||||
int new_offset_paste_count_;
|
||||
QPointF new_start_top_left_corner_;
|
||||
bool uses_offset;
|
||||
/// booleen pour empecher le premier appel a redo
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de supprimer des parties d'un element
|
||||
*/
|
||||
class CutPartsCommand : public DeletePartsCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
CutPartsCommand(ElementScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
|
||||
virtual ~CutPartsCommand();
|
||||
private:
|
||||
CutPartsCommand(const CutPartsCommand &);
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de deplacer une ou plusieurs
|
||||
parties lors de l'edition d'un element
|
||||
|
||||
30
sources/editor/elementcontent.h
Normal file
30
sources/editor/elementcontent.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef ELEMENT_CONTENT_H
|
||||
#define ELEMENT_CONTENT_H
|
||||
#include <QList>
|
||||
class QGraphicsItem;
|
||||
/**
|
||||
Lors de son edition dans l'editeur d'element, un element est decompose en
|
||||
parties graphiques. La classe ElementContent represente un ensemble de parties
|
||||
graphiques constituant tout ou partie d'un element.
|
||||
Note : pour le moment, ElementContent est un typedef pour QList\<QGraphicsItem *\>
|
||||
@see la documentation Qt de la classe QList
|
||||
*/
|
||||
typedef QList<QGraphicsItem *> ElementContent;
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -22,7 +22,7 @@ class QETElementEditor;
|
||||
class ElementScene;
|
||||
class CustomElementPart;
|
||||
/**
|
||||
Cette classe est la classe de base pour les editeurs de aprties dans
|
||||
Cette classe est la classe de base pour les editeurs de parties dans
|
||||
l'editeur d'element. Elle fournit des methodes pour acceder facilement
|
||||
a l'editeur, a la pile d'annulation, a la scene d'edition ou encore pour
|
||||
ajouter facilement une annulation de type ChangePartCommand.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "qetelementeditor.h"
|
||||
#include <cmath>
|
||||
#include "partline.h"
|
||||
#include "partrectangle.h"
|
||||
#include "partellipse.h"
|
||||
#include "partcircle.h"
|
||||
#include "partpolygon.h"
|
||||
@@ -28,9 +29,7 @@
|
||||
#include "partarc.h"
|
||||
#include "hotspoteditor.h"
|
||||
#include "editorcommands.h"
|
||||
|
||||
const int ElementScene::xGrid = 10;
|
||||
const int ElementScene::yGrid = 10;
|
||||
#include "elementcontent.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@@ -47,6 +46,8 @@ ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
||||
element_editor(editor)
|
||||
{
|
||||
current_polygon = NULL;
|
||||
setGrid(1, 1);
|
||||
initPasteArea();
|
||||
undo_stack.setClean();
|
||||
}
|
||||
|
||||
@@ -68,6 +69,13 @@ void ElementScene::slot_addLine() {
|
||||
behavior = Line;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de rectangle"
|
||||
*/
|
||||
void ElementScene::slot_addRectangle() {
|
||||
behavior = Rectangle;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de cercle"
|
||||
*/
|
||||
@@ -104,7 +112,6 @@ void ElementScene::slot_addTerminal() {
|
||||
behavior = Terminal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout d'arc de cercle"
|
||||
*/
|
||||
@@ -124,7 +131,17 @@ void ElementScene::slot_addTextField() {
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
QPointF event_pos = e -> scenePos();
|
||||
if (mustSnapToGrid(e)) snapToGrid(event_pos);
|
||||
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
if (behavior == PasteArea) {
|
||||
QRectF current_rect(paste_area_ -> rect());
|
||||
current_rect.moveCenter(event_pos);
|
||||
paste_area_ -> setRect(current_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
QRectF temp_rect;
|
||||
qreal radius;
|
||||
QPointF temp_point;
|
||||
@@ -132,21 +149,26 @@ void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (e -> buttons() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Line:
|
||||
current_line -> setLine(QLineF(current_line -> line().p1(), e -> scenePos()));
|
||||
current_line -> setLine(QLineF(current_line -> line().p1(), event_pos));
|
||||
break;
|
||||
case Rectangle:
|
||||
temp_rect = current_rectangle -> rect();
|
||||
temp_rect.setBottomRight(event_pos);
|
||||
current_rectangle -> setRect(temp_rect);
|
||||
break;
|
||||
case Ellipse:
|
||||
temp_rect = current_ellipse -> rect();
|
||||
temp_rect.setBottomRight(e -> scenePos());
|
||||
temp_rect.setBottomRight(event_pos);
|
||||
current_ellipse -> setRect(temp_rect);
|
||||
break;
|
||||
case Arc:
|
||||
temp_rect = current_arc -> rect();
|
||||
temp_rect.setBottomRight(e -> scenePos());
|
||||
temp_rect.setBottomRight(event_pos);
|
||||
current_arc -> setRect(temp_rect);
|
||||
break;
|
||||
case Circle:
|
||||
temp_rect = current_circle -> rect();
|
||||
temp_point = e -> scenePos() - current_circle -> mapToScene(temp_rect.center());
|
||||
temp_point = event_pos - current_circle -> mapToScene(temp_rect.center());
|
||||
radius = sqrt(pow(temp_point.x(), 2) + pow(temp_point.y(), 2));
|
||||
temp_rect = QRectF(
|
||||
temp_rect.center() - QPointF(radius, radius),
|
||||
@@ -158,17 +180,35 @@ void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (current_polygon == NULL) break;
|
||||
temp_polygon = current_polygon -> polygon();
|
||||
temp_polygon.pop_back();
|
||||
temp_polygon << e -> scenePos();
|
||||
temp_polygon << event_pos;
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mouseMoveEvent(e);
|
||||
QList<QGraphicsItem *> selected_items = selectedItems();
|
||||
if (!selected_items.isEmpty()) {
|
||||
// mouvement de souris realise depuis le dernier press event
|
||||
QPointF mouse_movement = e -> scenePos() - moving_press_pos;
|
||||
|
||||
// application de ce mouvement a la fsi_pos enregistre dans le dernier press event
|
||||
QPointF new_fsi_pos = fsi_pos + mouse_movement;
|
||||
|
||||
// snap eventuel de la nouvelle fsi_pos
|
||||
if (mustSnapToGrid(e)) snapToGrid(new_fsi_pos);
|
||||
|
||||
// difference entre la fsi_pos finale et la fsi_pos courante = mouvement a appliquer
|
||||
|
||||
QPointF current_fsi_pos = selected_items.first() -> scenePos();
|
||||
QPointF final_movement = new_fsi_pos - current_fsi_pos;
|
||||
foreach(QGraphicsItem *qgi, selected_items) {
|
||||
qgi -> moveBy(final_movement.x(), final_movement.y());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (behavior == Polygon && current_polygon != NULL) {
|
||||
temp_polygon = current_polygon -> polygon();
|
||||
temp_polygon.pop_back();
|
||||
temp_polygon << e -> scenePos();
|
||||
temp_polygon << event_pos;
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
} else QGraphicsScene::mouseMoveEvent(e);
|
||||
}
|
||||
@@ -178,27 +218,34 @@ void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
QPointF event_pos = e -> scenePos();
|
||||
if (mustSnapToGrid(e)) snapToGrid(event_pos);
|
||||
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
QPolygonF temp_polygon;
|
||||
if (e -> button() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Line:
|
||||
current_line = new PartLine(element_editor, 0, this);
|
||||
current_line -> setLine(QLineF(e -> scenePos(), e -> scenePos()));
|
||||
current_line -> setLine(QLineF(event_pos, event_pos));
|
||||
break;
|
||||
case Rectangle:
|
||||
current_rectangle = new PartRectangle(element_editor, 0, this);
|
||||
current_rectangle -> setRect(QRectF(event_pos, QSizeF(0.0, 0.0)));
|
||||
break;
|
||||
case Ellipse:
|
||||
current_ellipse = new PartEllipse(element_editor, 0, this);
|
||||
current_ellipse -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
||||
current_ellipse -> setRect(QRectF(event_pos, QSizeF(0.0, 0.0)));
|
||||
current_ellipse -> setProperty("antialias", true);
|
||||
break;
|
||||
case Arc:
|
||||
current_arc = new PartArc(element_editor, 0, this);
|
||||
current_arc -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
||||
current_arc -> setRect(QRectF(event_pos, QSizeF(0.0, 0.0)));
|
||||
current_arc -> setProperty("antialias", true);
|
||||
break;
|
||||
case Circle:
|
||||
current_circle = new PartCircle(element_editor, 0, this);
|
||||
current_circle -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
||||
current_circle -> setRect(QRectF(event_pos, QSizeF(0.0, 0.0)));
|
||||
current_circle -> setProperty("antialias", true);
|
||||
break;
|
||||
case Polygon:
|
||||
@@ -207,14 +254,23 @@ void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
temp_polygon = QPolygonF(0);
|
||||
} else temp_polygon = current_polygon -> polygon();
|
||||
// au debut, on insere deux points
|
||||
if (!temp_polygon.count()) temp_polygon << e -> scenePos();
|
||||
temp_polygon << e -> scenePos();
|
||||
if (!temp_polygon.count()) temp_polygon << event_pos;
|
||||
temp_polygon << event_pos;
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mousePressEvent(e);
|
||||
if (!selectedItems().isEmpty()) fsi_pos = selectedItems().first() -> scenePos();
|
||||
// gestion des deplacements de parties
|
||||
if (!selectedItems().isEmpty()) {
|
||||
fsi_pos = selectedItems().first() -> scenePos();
|
||||
moving_press_pos = e -> scenePos();
|
||||
moving_parts_ = true;
|
||||
} else {
|
||||
fsi_pos = QPoint();
|
||||
moving_press_pos = QPoint();
|
||||
moving_parts_ = false;
|
||||
}
|
||||
}
|
||||
} else QGraphicsScene::mousePressEvent(e);
|
||||
}
|
||||
@@ -224,71 +280,97 @@ void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
QPointF event_pos = e -> scenePos();
|
||||
if (mustSnapToGrid(e)) snapToGrid(event_pos);
|
||||
|
||||
PartTerminal *terminal;
|
||||
PartText *text;
|
||||
PartTextField *textfield;
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
|
||||
if (behavior == PasteArea) {
|
||||
defined_paste_area_ = paste_area_ -> rect();
|
||||
removeItem(paste_area_);
|
||||
emit(pasteAreaDefined(defined_paste_area_));
|
||||
behavior = Normal;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e -> button() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Line:
|
||||
if (qgiManager().manages(current_line)) break;
|
||||
undo_stack.push(new AddPartCommand(tr("ligne"), this, current_line));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Rectangle:
|
||||
if (qgiManager().manages(current_rectangle)) break;
|
||||
current_rectangle -> setRect(current_rectangle -> rect().normalized());
|
||||
undo_stack.push(new AddPartCommand(tr("rectangle"), this, current_rectangle));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Ellipse:
|
||||
if (qgiManager().manages(current_ellipse)) break;
|
||||
current_ellipse -> setRect(current_ellipse -> rect().normalized());
|
||||
undo_stack.push(new AddPartCommand(tr("ellipse"), this, current_ellipse));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Arc:
|
||||
if (qgiManager().manages(current_arc)) break;
|
||||
current_arc-> setRect(current_arc -> rect().normalized());
|
||||
undo_stack.push(new AddPartCommand(tr("arc"), this, current_arc));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Circle:
|
||||
if (qgiManager().manages(current_circle)) break;
|
||||
current_circle -> setRect(current_circle -> rect().normalized());
|
||||
undo_stack.push(new AddPartCommand(tr("cercle"), this, current_circle));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Terminal:
|
||||
terminal = new PartTerminal(element_editor, 0, this);
|
||||
terminal -> setPos(e -> scenePos());
|
||||
terminal -> setPos(event_pos);
|
||||
undo_stack.push(new AddPartCommand(tr("borne"), this, terminal));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Text:
|
||||
text = new PartText(element_editor, 0, this);
|
||||
text -> setPos(e -> scenePos());
|
||||
text -> setPos(event_pos);
|
||||
undo_stack.push(new AddPartCommand(tr("texte"), this, text));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case TextField:
|
||||
textfield = new PartTextField(element_editor, 0, this);
|
||||
textfield -> setPos(e -> scenePos());
|
||||
textfield -> setPos(event_pos);
|
||||
undo_stack.push(new AddPartCommand(tr("champ de texte"), this, textfield));
|
||||
emit(partsAdded());
|
||||
endCurrentBehavior(e);
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mouseReleaseEvent(e);
|
||||
// detecte les deplacements de parties
|
||||
if (!selectedItems().isEmpty()) {
|
||||
if (!selectedItems().isEmpty() && moving_parts_) {
|
||||
QPointF movement = selectedItems().first() -> scenePos() - fsi_pos;
|
||||
if (!movement.isNull()) {
|
||||
undo_stack.push(new MovePartsCommand(movement, this, selectedItems()));
|
||||
}
|
||||
}
|
||||
QGraphicsScene::mouseReleaseEvent(e);
|
||||
moving_parts_ = false;
|
||||
}
|
||||
} else if (e -> button() & Qt::RightButton) {
|
||||
if (behavior == Polygon && current_polygon != NULL) {
|
||||
behavior = Normal;
|
||||
undo_stack.push(new AddPartCommand(tr("polygone"), this, current_polygon));
|
||||
current_polygon = NULL;
|
||||
emit(partsAdded());
|
||||
emit(needNormalMode());
|
||||
endCurrentBehavior(e);
|
||||
} else QGraphicsScene::mouseReleaseEvent(e);
|
||||
} else QGraphicsScene::mouseReleaseEvent(e);
|
||||
}
|
||||
@@ -317,6 +399,10 @@ void ElementScene::drawBackground(QPainter *p, const QRectF &r) {
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
p -> drawRect(drawable_area);
|
||||
|
||||
// on dessine un point de la grille sur 10
|
||||
int drawn_x_grid = x_grid * 10;
|
||||
int drawn_y_grid = y_grid * 10;
|
||||
|
||||
if (r.width() < 2500 && r.height() < 2500) {
|
||||
// dessine les points de la grille
|
||||
p -> setPen(Qt::black);
|
||||
@@ -325,12 +411,12 @@ void ElementScene::drawBackground(QPainter *p, const QRectF &r) {
|
||||
qreal limite_y = r.y() + r.height();
|
||||
|
||||
int g_x = (int)ceil(r.x());
|
||||
while (g_x % xGrid) ++ g_x;
|
||||
while (g_x % drawn_x_grid) ++ g_x;
|
||||
int g_y = (int)ceil(r.y());
|
||||
while (g_y % yGrid) ++ g_y;
|
||||
while (g_y % drawn_y_grid) ++ g_y;
|
||||
|
||||
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
|
||||
for (int gx = g_x ; gx < limite_x ; gx += drawn_x_grid) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += drawn_y_grid) {
|
||||
p -> drawPoint(gx, gy);
|
||||
}
|
||||
}
|
||||
@@ -358,11 +444,50 @@ void ElementScene::drawForeground(QPainter *p, const QRectF &) {
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
A partir d'un evenement souris, cette methode regarde si la touche shift est
|
||||
enfoncee ou non. Si oui, elle laisse le comportement en cours (cercle,
|
||||
texte, polygone, ...). Si non, elle repasse en mode normal / selection.
|
||||
@param e objet decrivant l'evenement souris
|
||||
*/
|
||||
void ElementScene::endCurrentBehavior(const QGraphicsSceneMouseEvent *event) {
|
||||
if (!(event -> modifiers() & Qt::ShiftModifier)) {
|
||||
// la touche Shift n'est pas enfoncee : on demande le mode normal
|
||||
behavior = Normal;
|
||||
emit(needNormalMode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return la taille horizontale de la grille
|
||||
*/
|
||||
int ElementScene::xGrid() const {
|
||||
return(x_grid);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la taille verticale de la grille
|
||||
*/
|
||||
int ElementScene::yGrid() const {
|
||||
return(y_grid);
|
||||
}
|
||||
|
||||
/**
|
||||
@param x_grid Taille horizontale de la grille
|
||||
@param y_grid Taille verticale de la grille
|
||||
*/
|
||||
void ElementScene::setGrid(int x_g, int y_g) {
|
||||
x_grid = x_g ? x_g : 1;
|
||||
y_grid = y_g ? y_g : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte l'element en XML
|
||||
@param diagram Booleen (a vrai par defaut) indiquant si le XML genere doit
|
||||
representer tout l'element ou seulement les elements selectionnes
|
||||
@return un document XML decrivant l'element
|
||||
*/
|
||||
const QDomDocument ElementScene::toXml() const {
|
||||
const QDomDocument ElementScene::toXml(bool all_parts) const {
|
||||
// document XML
|
||||
QDomDocument xml_document;
|
||||
|
||||
@@ -383,6 +508,8 @@ const QDomDocument ElementScene::toXml() const {
|
||||
QDomElement description = xml_document.createElement("description");
|
||||
// description de l'element
|
||||
foreach(QGraphicsItem *qgi, zItems(true)) {
|
||||
// si l'export ne concerne que la selection, on ignore les parties non selectionnees
|
||||
if (!all_parts && !qgi -> isSelected()) continue;
|
||||
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
|
||||
if (ce -> isUseless()) continue;
|
||||
description.appendChild(ce -> toXml(xml_document));
|
||||
@@ -395,91 +522,90 @@ const QDomDocument ElementScene::toXml() const {
|
||||
}
|
||||
|
||||
/**
|
||||
Lit un element depuis un document XML
|
||||
@param xml_document un document XML decrivant l'element
|
||||
@param xml_document un document XML decrivant un element
|
||||
@return le boundingRect du contenu de l'element
|
||||
*/
|
||||
void ElementScene::fromXml(const QDomDocument &xml_document) {
|
||||
QRectF ElementScene::boundingRectFromXml(const QDomDocument &xml_document) {
|
||||
// charge les parties depuis le document XML
|
||||
ElementContent loaded_content = loadContent(xml_document);
|
||||
if (loaded_content.isEmpty()) return(QRectF());
|
||||
|
||||
// calcule le boundingRect
|
||||
QRectF bounding_rect = elementContentBoundingRect(loaded_content);
|
||||
|
||||
// detruit les parties chargees
|
||||
qDeleteAll(loaded_content);
|
||||
|
||||
return(bounding_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe l'element decrit dans un document XML. Si une position est
|
||||
precisee, les elements importes sont positionnes de maniere a ce que le
|
||||
coin superieur gauche du plus petit rectangle pouvant les entourant tous
|
||||
(le bounding rect) soit a cette position.
|
||||
@param xml_document un document XML decrivant l'element
|
||||
@param position La position des parties importees
|
||||
@param consider_informations Si vrai, les informations complementaires
|
||||
(dimensions, hotspot, etc.) seront prises en compte
|
||||
@param content_ptr si ce pointeur vers un ElementContent est different de 0,
|
||||
il sera rempli avec le contenu ajoute a l'element par le fromXml
|
||||
@return true si l'import a reussi, false sinon
|
||||
*/
|
||||
void ElementScene::fromXml(
|
||||
const QDomDocument &xml_document,
|
||||
const QPointF &position,
|
||||
bool consider_informations,
|
||||
ElementContent *content_ptr
|
||||
) {
|
||||
QString error_message;
|
||||
bool state = true;
|
||||
|
||||
// la racine est supposee etre une definition d'element
|
||||
QDomElement root = xml_document.documentElement();
|
||||
if (root.tagName() != "definition" || root.attribute("type") != "element") {
|
||||
state = false;
|
||||
error_message = tr("Ce document XML n'est pas une definition d'\351l\351ment.");
|
||||
}
|
||||
|
||||
// dimensions et hotspot
|
||||
if (state) {
|
||||
// ces attributs doivent etre presents et valides
|
||||
int w, h, hot_x, hot_y;
|
||||
if (
|
||||
!QET::attributeIsAnInteger(root, QString("width"), &w) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("height"), &h) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("hotspot_x"), &hot_x) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("hotspot_y"), &hot_y)
|
||||
) {
|
||||
state = false;
|
||||
error_message = tr("Les dimensions ou le point de saisie ne sont pas valides.");
|
||||
} else {
|
||||
setWidth(w);
|
||||
setHeight(h);
|
||||
setHotspot(QPoint(hot_x, hot_y));
|
||||
}
|
||||
}
|
||||
|
||||
// orientations et connexions internes
|
||||
if (state) {
|
||||
internal_connections = (root.attribute("ic") == "true");
|
||||
|
||||
if (!ori.fromString(root.attribute("orientation"))) {
|
||||
state = false;
|
||||
error_message = tr("Les orientations ne sont pas valides.");
|
||||
}
|
||||
}
|
||||
|
||||
// extrait les noms de la definition XML
|
||||
if (state) {
|
||||
_names.fromXml(root);
|
||||
// prend en compte les informations de l'element
|
||||
if (consider_informations) {
|
||||
state = applyInformations(xml_document, &error_message);
|
||||
}
|
||||
|
||||
// parcours des enfants de la definition : parties de l'element
|
||||
if (state) {
|
||||
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
QDomElement elmts = node.toElement();
|
||||
if (elmts.isNull()) continue;
|
||||
if (elmts.tagName() == "description") {
|
||||
// gestion de la description graphique de l'element
|
||||
// = parcours des differentes parties du dessin
|
||||
int z = 1;
|
||||
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
|
||||
QDomElement qde = n.toElement();
|
||||
if (qde.isNull()) continue;
|
||||
CustomElementPart *cep;
|
||||
if (qde.tagName() == "line") cep = new PartLine (element_editor, 0, this);
|
||||
else if (qde.tagName() == "ellipse") cep = new PartEllipse (element_editor, 0, this);
|
||||
else if (qde.tagName() == "circle") cep = new PartCircle (element_editor, 0, this);
|
||||
else if (qde.tagName() == "polygon") cep = new PartPolygon (element_editor, 0, this);
|
||||
else if (qde.tagName() == "terminal") cep = new PartTerminal (element_editor, 0, this);
|
||||
else if (qde.tagName() == "text") cep = new PartText (element_editor, 0, this);
|
||||
else if (qde.tagName() == "input") cep = new PartTextField(element_editor, 0, this);
|
||||
else if (qde.tagName() == "arc") cep = new PartArc (element_editor, 0, this);
|
||||
else continue;
|
||||
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) qgi -> setZValue(z++);
|
||||
cep -> fromXml(qde);
|
||||
}
|
||||
}
|
||||
ElementContent loaded_content = loadContent(xml_document, &error_message);
|
||||
if (position != QPointF()) {
|
||||
addContentAtPos(loaded_content, position, &error_message);
|
||||
} else {
|
||||
addContent(loaded_content, &error_message);
|
||||
}
|
||||
|
||||
// renvoie le contenu ajoute a l'element
|
||||
if (content_ptr) {
|
||||
*content_ptr = loaded_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle representant les limites de l'element.
|
||||
Ce rectangle a pour dimensions la taille de l'element et pour coin
|
||||
superieur gauche les coordonnees opposees du hotspot.
|
||||
*/
|
||||
QRectF ElementScene::borderRect() const {
|
||||
return(QRectF(-_hotspot, QSizeF(width(), height())));
|
||||
}
|
||||
|
||||
/**
|
||||
@return un rectangle englobant toutes les parties ainsi que le
|
||||
"bounding rect" de l'element
|
||||
*/
|
||||
QRectF ElementScene::sceneContent() const {
|
||||
return(itemsBoundingRect().unite(QRectF(-_hotspot, QSizeF(width(), height()))));
|
||||
return(itemsBoundingRect().unite(borderRect()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si toutes les parties graphiques composant l'element sont
|
||||
integralement contenues dans le rectangle representant les limites de
|
||||
l'element.
|
||||
*/
|
||||
bool ElementScene::borderContainsEveryParts() const {
|
||||
return(borderRect().contains(itemsBoundingRect()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,6 +622,64 @@ QGIManager &ElementScene::qgiManager() {
|
||||
return(qgi_manager);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le presse-papier semble contenir un element
|
||||
*/
|
||||
bool ElementScene::clipboardMayContainElement() {
|
||||
QString clipboard_text = QApplication::clipboard() -> text().trimmed();
|
||||
bool may_be_element = clipboard_text.startsWith("<definition") && clipboard_text.endsWith("</definition>");
|
||||
return(may_be_element);
|
||||
}
|
||||
|
||||
/**
|
||||
@param clipboard_content chaine de caractere, provenant vraisemblablement du
|
||||
presse-papier.
|
||||
@return true si clipboard_content a ete copie depuis cet element.
|
||||
*/
|
||||
bool ElementScene::wasCopiedFromThisElement(const QString &clipboard_content) {
|
||||
return(clipboard_content == last_copied_);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de couper la selection = l'exporter en XML dans le
|
||||
presse-papier puis la supprimer.
|
||||
*/
|
||||
void ElementScene::cut() {
|
||||
copy();
|
||||
QList<QGraphicsItem *> cut_content = selectedItems();
|
||||
clearSelection();
|
||||
undoStack().push(new CutPartsCommand(this, cut_content));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de copier la selection = l'exporter en XML dans le
|
||||
presse-papier.
|
||||
*/
|
||||
void ElementScene::copy() {
|
||||
// accede au presse-papier
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
|
||||
// genere la description XML de la selection
|
||||
QString clipboard_content = toXml(false).toString(4);
|
||||
|
||||
// met la description XML dans le presse-papier
|
||||
if (clipboard -> supportsSelection()) {
|
||||
clipboard -> setText(clipboard_content, QClipboard::Selection);
|
||||
}
|
||||
clipboard -> setText(clipboard_content);
|
||||
|
||||
// retient le dernier contenu copie
|
||||
last_copied_ = clipboard_content;
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de coller le contenu du presse-papier = l'importer dans le
|
||||
presse-papier a une position donnee.
|
||||
*/
|
||||
void ElementScene::paste() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne tout
|
||||
*/
|
||||
@@ -538,7 +722,7 @@ void ElementScene::slot_editSizeHotSpot() {
|
||||
// cree un dialogue
|
||||
QDialog dialog_sh(element_editor);
|
||||
dialog_sh.setModal(true);
|
||||
dialog_sh.setWindowTitle(tr("\311diter la taille et le point de saisie"));
|
||||
dialog_sh.setWindowTitle(tr("\311diter la taille et le point de saisie", "window title"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_sh);
|
||||
|
||||
// ajoute un HotspotEditor au dialogue
|
||||
@@ -578,7 +762,7 @@ void ElementScene::slot_editOrientations() {
|
||||
QDialog dialog_ori(element_editor);
|
||||
dialog_ori.setModal(true);
|
||||
dialog_ori.setMinimumSize(400, 260);
|
||||
dialog_ori.setWindowTitle(tr("\311diter les orientations"));
|
||||
dialog_ori.setWindowTitle(tr("\311diter les orientations", "window title"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_ori);
|
||||
|
||||
// ajoute un champ explicatif au dialogue
|
||||
@@ -624,7 +808,7 @@ void ElementScene::slot_editNames() {
|
||||
QDialog dialog(element_editor);
|
||||
dialog.setModal(true);
|
||||
dialog.setMinimumSize(400, 330);
|
||||
dialog.setWindowTitle(tr("\311diter les noms"));
|
||||
dialog.setWindowTitle(tr("\311diter les noms", "window title"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog);
|
||||
|
||||
// ajoute un champ explicatif au dialogue
|
||||
@@ -716,6 +900,30 @@ QList<QGraphicsItem *> ElementScene::zItems(bool include_terminals) const {
|
||||
return(all_items_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@return les parties graphiques selectionnees
|
||||
*/
|
||||
ElementContent ElementScene::selectedContent() const {
|
||||
ElementContent content;
|
||||
foreach(QGraphicsItem *qgi, zItems(true)) {
|
||||
if (qgi -> isSelected()) content << qgi;
|
||||
}
|
||||
return(content);
|
||||
}
|
||||
|
||||
/**
|
||||
@param to_paste Rectangle englobant les parties a coller
|
||||
@return le rectangle ou il faudra coller ces parties
|
||||
*/
|
||||
void ElementScene::getPasteArea(const QRectF &to_paste) {
|
||||
// on le dessine sur la scene
|
||||
paste_area_ -> setRect(to_paste);
|
||||
addItem(paste_area_);
|
||||
|
||||
// on passe la scene en mode "recherche de zone pour copier/coller"
|
||||
behavior = PasteArea;
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime les parties de l'element et les objets d'annulations.
|
||||
Les autres caracteristiques sont conservees.
|
||||
@@ -729,3 +937,200 @@ void ElementScene::reset() {
|
||||
qgiManager().release(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param content Contenu ( = parties) d'un element
|
||||
@return le boundingRect de ces parties, exprime dans les coordonnes de la
|
||||
scene
|
||||
*/
|
||||
QRectF ElementScene::elementContentBoundingRect(const ElementContent &content) {
|
||||
QRectF bounding_rect;
|
||||
foreach(QGraphicsItem *qgi, content) {
|
||||
bounding_rect |= qgi -> sceneBoundingRect();
|
||||
}
|
||||
return(bounding_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Applique les informations (dimensions, hostpot, orientations, connexions
|
||||
internes et noms) contenu dans un document XML.
|
||||
@param xml_document Document XML a analyser
|
||||
@param error_message pointeur vers une QString ; si error_message est
|
||||
different de 0, un message d'erreur sera stocke dedans si necessaire
|
||||
@return true si la lecture et l'application des informations s'est bien
|
||||
passee, false sinon.
|
||||
*/
|
||||
bool ElementScene::applyInformations(const QDomDocument &xml_document, QString *error_message) {
|
||||
// la racine est supposee etre une definition d'element
|
||||
QDomElement root = xml_document.documentElement();
|
||||
if (root.tagName() != "definition" || root.attribute("type") != "element") {
|
||||
if (error_message) {
|
||||
*error_message = tr("Ce document XML n'est pas une d\351finition d'\351l\351ment.", "error message");
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
// dimensions et hotspot : ces attributs doivent etre presents et valides
|
||||
int w, h, hot_x, hot_y;
|
||||
if (
|
||||
!QET::attributeIsAnInteger(root, QString("width"), &w) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("height"), &h) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("hotspot_x"), &hot_x) ||\
|
||||
!QET::attributeIsAnInteger(root, QString("hotspot_y"), &hot_y)
|
||||
) {
|
||||
if (error_message) {
|
||||
*error_message = tr("Les dimensions ou le point de saisie ne sont pas valides.", "error message");
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
//
|
||||
setWidth(w);
|
||||
setHeight(h);
|
||||
setHotspot(QPoint(hot_x, hot_y));
|
||||
|
||||
// orientations
|
||||
internal_connections = (root.attribute("ic") == "true");
|
||||
|
||||
// connexions internes
|
||||
if (!ori.fromString(root.attribute("orientation"))) {
|
||||
if (error_message) {
|
||||
*error_message = tr("Les orientations ne sont pas valides.", "error message");
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
// extrait les noms de la definition XML
|
||||
_names.fromXml(root);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Par le document XML xml_document et retourne le contenu ( = liste de
|
||||
parties) correspondant.
|
||||
@param xml_document Document XML a analyser
|
||||
@param error_message pointeur vers une QString ; si error_message est
|
||||
different de 0, un message d'erreur sera stocke dedans si necessaire
|
||||
*/
|
||||
ElementContent ElementScene::loadContent(const QDomDocument &xml_document, QString *error_message) {
|
||||
ElementContent loaded_parts;
|
||||
|
||||
// la racine est supposee etre une definition d'element
|
||||
QDomElement root = xml_document.documentElement();
|
||||
if (root.tagName() != "definition" || root.attribute("type") != "element") {
|
||||
if (error_message) {
|
||||
*error_message = tr("Ce document XML n'est pas une d\351finition d'\351l\351ment.", "error message");
|
||||
}
|
||||
return(loaded_parts);
|
||||
}
|
||||
|
||||
// chargement de la description graphique de l'element
|
||||
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
QDomElement elmts = node.toElement();
|
||||
if (elmts.isNull()) continue;
|
||||
if (elmts.tagName() == "description") {
|
||||
|
||||
// = parcours des differentes parties du dessin
|
||||
int z = 1;
|
||||
for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) {
|
||||
QDomElement qde = n.toElement();
|
||||
if (qde.isNull()) continue;
|
||||
CustomElementPart *cep;
|
||||
if (qde.tagName() == "line") cep = new PartLine (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "rect") cep = new PartRectangle(element_editor, 0, 0);
|
||||
else if (qde.tagName() == "ellipse") cep = new PartEllipse (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "circle") cep = new PartCircle (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "polygon") cep = new PartPolygon (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "terminal") cep = new PartTerminal (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "text") cep = new PartText (element_editor, 0, 0);
|
||||
else if (qde.tagName() == "input") cep = new PartTextField(element_editor, 0, 0);
|
||||
else if (qde.tagName() == "arc") cep = new PartArc (element_editor, 0, 0);
|
||||
else continue;
|
||||
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) {
|
||||
qgi -> setZValue(z++);
|
||||
loaded_parts << qgi;
|
||||
}
|
||||
cep -> fromXml(qde);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(loaded_parts);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute le contenu content a cet element
|
||||
@param content contenu ( = liste de parties) a charger
|
||||
@param error_message pointeur vers une QString ; si error_message est
|
||||
different de 0, un message d'erreur sera stocke dedans si necessaire
|
||||
@return Le contenu ajoute
|
||||
*/
|
||||
ElementContent ElementScene::addContent(const ElementContent &content, QString */*error_message*/) {
|
||||
foreach(QGraphicsItem *part, content) {
|
||||
addItem(part);
|
||||
}
|
||||
return(content);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute le contenu content a cet element
|
||||
@param content contenu ( = liste de parties) a charger
|
||||
@param pos Position du coin superieur gauche du contenu apres avoir ete ajoute
|
||||
@param error_message pointeur vers une QString ; si error_message est
|
||||
different de 0, un message d'erreur sera stocke dedans si necessaire
|
||||
@return Le contenu ajoute
|
||||
*/
|
||||
ElementContent ElementScene::addContentAtPos(const ElementContent &content, const QPointF &pos, QString */*error_message*/) {
|
||||
// calcule le boundingRect du contenu a ajouter
|
||||
QRectF bounding_rect = elementContentBoundingRect(content);
|
||||
|
||||
// en deduit le decalage a appliquer aux parties pour les poser au point demander
|
||||
QPointF offset = pos - bounding_rect.topLeft();
|
||||
|
||||
// ajoute les parties avec le decalage adequat
|
||||
foreach(QGraphicsItem *part, content) {
|
||||
part -> setPos(part -> pos() + offset);
|
||||
addItem(part);
|
||||
}
|
||||
return(content);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialise la zone de collage
|
||||
*/
|
||||
void ElementScene::initPasteArea() {
|
||||
paste_area_ = new QGraphicsRectItem();
|
||||
paste_area_ -> setZValue(1000000);
|
||||
|
||||
QPen paste_area_pen;
|
||||
paste_area_pen.setStyle(Qt::DashDotLine);
|
||||
paste_area_pen.setColor(QColor(30, 56, 86, 255));
|
||||
|
||||
QBrush paste_area_brush;
|
||||
paste_area_brush.setStyle(Qt::SolidPattern);
|
||||
paste_area_brush.setColor(QColor(90, 167, 255, 64));
|
||||
|
||||
paste_area_ -> setPen(paste_area_pen);
|
||||
paste_area_ -> setBrush(paste_area_brush);
|
||||
}
|
||||
|
||||
/**
|
||||
Arrondit les coordonnees du point passees en parametre de facon a ce que ce
|
||||
point soit aligne sur la grille.
|
||||
@param point une reference vers un QPointF. Cet objet sera modifie.
|
||||
|
||||
*/
|
||||
void ElementScene::snapToGrid(QPointF &point) {
|
||||
point.rx() = qRound(point.x() / x_grid) * x_grid;
|
||||
point.ry() = qRound(point.y() / y_grid) * y_grid;
|
||||
}
|
||||
|
||||
/**
|
||||
@param e Evenement souris
|
||||
@return true s'il faut utiliser le snap-to-grid
|
||||
Typiquement, cette methode retourne true si l'evenement souris se produit
|
||||
sans la touche Ctrl enfoncee.
|
||||
*/
|
||||
bool ElementScene::mustSnapToGrid(QGraphicsSceneMouseEvent *e) {
|
||||
return(!(e -> modifiers() & Qt::ControlModifier));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -22,8 +22,10 @@
|
||||
#include "nameslistwidget.h"
|
||||
#include "orientationsetwidget.h"
|
||||
#include "qgimanager.h"
|
||||
#include "elementcontent.h"
|
||||
class QETElementEditor;
|
||||
class PartLine;
|
||||
class PartRectangle;
|
||||
class PartEllipse;
|
||||
class PartCircle;
|
||||
class PartPolygon;
|
||||
@@ -38,7 +40,7 @@ class ElementScene : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
|
||||
// enum
|
||||
enum Behavior { Normal, Line, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField };
|
||||
enum Behavior { Normal, Line, Rectangle, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField, PasteArea };
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
@@ -49,10 +51,6 @@ class ElementScene : public QGraphicsScene {
|
||||
ElementScene(const ElementScene &);
|
||||
|
||||
// attributs
|
||||
public:
|
||||
static const int xGrid; ///< Taille horizontale de la grille
|
||||
static const int yGrid; ///< Taille verticale de la grille
|
||||
|
||||
private:
|
||||
/// longueur de l'element en dizaines de pixels
|
||||
uint _width;
|
||||
@@ -72,16 +70,31 @@ class ElementScene : public QGraphicsScene {
|
||||
QUndoStack undo_stack;
|
||||
/// Position du premier item selectionne (utilise pour annuler les deplacements)
|
||||
QPointF fsi_pos;
|
||||
QPointF moving_press_pos;
|
||||
bool moving_parts_;
|
||||
|
||||
/// Variables relatives a la gestion du dessin des parties sur la scene
|
||||
Behavior behavior;
|
||||
PartLine *current_line;
|
||||
PartRectangle *current_rectangle;
|
||||
PartEllipse *current_ellipse;
|
||||
PartCircle *current_circle;
|
||||
PartPolygon *current_polygon;
|
||||
PartArc *current_arc;
|
||||
QETElementEditor *element_editor;
|
||||
|
||||
/// Variables relatives a la gestion de la zone de collage sur la scene
|
||||
QGraphicsRectItem *paste_area_;
|
||||
QRectF defined_paste_area_;
|
||||
|
||||
/// Variables relatives au copier-coller avec decalage
|
||||
QString last_copied_;
|
||||
|
||||
///< Taille horizontale de la grille
|
||||
int x_grid;
|
||||
///< Taille verticale de la grille
|
||||
int y_grid;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setWidth(const uint &);
|
||||
@@ -96,13 +109,26 @@ class ElementScene : public QGraphicsScene {
|
||||
void setOrientations(const OrientationSet &);
|
||||
bool internalConnections();
|
||||
void setInternalConnections(bool);
|
||||
virtual const QDomDocument toXml() const;
|
||||
virtual void fromXml(const QDomDocument &);
|
||||
virtual int xGrid() const;
|
||||
virtual int yGrid() const;
|
||||
virtual void setGrid(int, int);
|
||||
virtual const QDomDocument toXml(bool = true) const;
|
||||
virtual QRectF boundingRectFromXml(const QDomDocument &);
|
||||
virtual void fromXml(const QDomDocument &, const QPointF & = QPointF(), bool = true, ElementContent * = 0);
|
||||
virtual void reset();
|
||||
virtual QList<QGraphicsItem *> zItems(bool = false) const;
|
||||
virtual ElementContent selectedContent() const;
|
||||
virtual void getPasteArea(const QRectF &);
|
||||
QRectF borderRect() const;
|
||||
QRectF sceneContent() const;
|
||||
bool borderContainsEveryParts() const;
|
||||
QUndoStack &undoStack();
|
||||
QGIManager &qgiManager();
|
||||
static bool clipboardMayContainElement();
|
||||
bool wasCopiedFromThisElement(const QString &);
|
||||
void cut();
|
||||
void copy();
|
||||
void paste();
|
||||
|
||||
protected:
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
@@ -110,10 +136,22 @@ class ElementScene : public QGraphicsScene {
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void drawBackground(QPainter *, const QRectF &);
|
||||
virtual void drawForeground(QPainter *, const QRectF &);
|
||||
virtual void endCurrentBehavior(const QGraphicsSceneMouseEvent *);
|
||||
|
||||
private:
|
||||
QRectF elementContentBoundingRect(const ElementContent &);
|
||||
bool applyInformations(const QDomDocument &, QString * = 0);
|
||||
ElementContent loadContent(const QDomDocument &, QString * = 0);
|
||||
ElementContent addContent(const ElementContent &, QString * = 0);
|
||||
ElementContent addContentAtPos(const ElementContent &, const QPointF &, QString * = 0);
|
||||
void initPasteArea();
|
||||
void snapToGrid(QPointF &);
|
||||
bool mustSnapToGrid(QGraphicsSceneMouseEvent *);
|
||||
|
||||
public slots:
|
||||
void slot_move();
|
||||
void slot_addLine();
|
||||
void slot_addRectangle();
|
||||
void slot_addCircle();
|
||||
void slot_addEllipse();
|
||||
void slot_addPolygon();
|
||||
@@ -145,6 +183,8 @@ class ElementScene : public QGraphicsScene {
|
||||
void partsRemoved();
|
||||
/// Signal emis lorsque la zValue d'une ou plusieurs parties change
|
||||
void partsZValueChanged();
|
||||
/// Signal emis lorsque l'utilisateur a fini de choisir une zone pour un copier/coller
|
||||
void pasteAreaDefined(const QRectF &);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -16,6 +16,8 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "elementview.h"
|
||||
#include "qetelementeditor.h"
|
||||
#include "editorcommands.h"
|
||||
/**
|
||||
Constructeur
|
||||
@param scene ElementScene visualisee par cette ElementView
|
||||
@@ -23,12 +25,14 @@
|
||||
*/
|
||||
ElementView::ElementView(ElementScene *scene, QWidget *parent) :
|
||||
QGraphicsView(scene, parent),
|
||||
scene_(scene)
|
||||
scene_(scene),
|
||||
offset_paste_count_(0)
|
||||
{
|
||||
setInteractive(true);
|
||||
setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
zoomReset();
|
||||
connect(scene_, SIGNAL(pasteAreaDefined(const QRectF &)), this, SLOT(pasteAreaDefined(const QRectF &)));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -40,6 +44,24 @@ ElementScene *ElementView::scene() const {
|
||||
return(scene_);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle de l'element visualise par cet ElementView
|
||||
*/
|
||||
QRectF ElementView::viewedSceneRect() const {
|
||||
// recupere la taille du widget viewport
|
||||
QSize viewport_size = viewport() -> size();
|
||||
|
||||
// recupere la transformation viewport -> scene
|
||||
QTransform view_to_scene = viewportTransform().inverted();
|
||||
|
||||
// mappe le coin superieur gauche et le coin inferieur droit de la viewport sur la scene
|
||||
QPointF scene_left_top = view_to_scene.map(QPointF(0.0, 0.0));
|
||||
QPointF scene_right_bottom = view_to_scene.map(QPointF(viewport_size.width(), viewport_size.height()));
|
||||
|
||||
// en deduit le rectangle visualise par la scene
|
||||
return(QRectF(scene_left_top, scene_right_bottom));
|
||||
}
|
||||
|
||||
/**
|
||||
Definit l'ElementScene visualisee par cette ElementView
|
||||
@param s l'ElementScene visualisee par cette ElementView
|
||||
@@ -110,6 +132,196 @@ void ElementView::adjustSceneRect() {
|
||||
scene_ -> update(old_scene_rect.united(new_scene_rect));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de couper la selection = l'exporter en XML dans le
|
||||
presse-papier puis la supprimer.
|
||||
*/
|
||||
void ElementView::cut() {
|
||||
// delegue cette action a la scene
|
||||
scene_ -> cut();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de copier la selection = l'exporter en XML dans le
|
||||
presse-papier.
|
||||
*/
|
||||
void ElementView::copy() {
|
||||
// delegue cette action a la scene
|
||||
scene_ -> copy();
|
||||
offset_paste_count_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de coller le contenu du presse-papier = l'importer dans
|
||||
l'element. Cette methode examine le contenu du presse-papier. Si celui-ci
|
||||
semble avoir ete copie depuis cet element, il est colle a cote de sa zone
|
||||
d'origine ; s'il est recolle, il sera colle un cran a cote de la zone deja
|
||||
recollee, etc.
|
||||
Sinon, cette methode demande a l'utilisateur de definir la zone ou le
|
||||
collage devra s'effectuer.
|
||||
@see pasteAreaDefined(const QRectF &)
|
||||
*/
|
||||
void ElementView::paste() {
|
||||
QString clipboard_text = QApplication::clipboard() -> text();
|
||||
if (clipboard_text.isEmpty()) return;
|
||||
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(clipboard_text)) return;
|
||||
|
||||
if (scene_ -> wasCopiedFromThisElement(clipboard_text)) {
|
||||
// copier/coller avec decalage
|
||||
pasteWithOffset(document_xml);
|
||||
} else {
|
||||
// copier/coller par choix de la zone de collage
|
||||
QRectF pasted_content_bounding_rect = scene_ -> boundingRectFromXml(document_xml);
|
||||
if (pasted_content_bounding_rect.isEmpty()) return;
|
||||
|
||||
to_paste_in_area_ = clipboard_text;
|
||||
getPasteArea(pasted_content_bounding_rect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Colle le contenu du presse-papier en demandant systematiquement a
|
||||
l'utilisateur de choisir une zone de collage
|
||||
*/
|
||||
void ElementView::pasteInArea() {
|
||||
QString clipboard_text = QApplication::clipboard() -> text();
|
||||
if (clipboard_text.isEmpty()) return;
|
||||
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(clipboard_text)) return;
|
||||
|
||||
QRectF pasted_content_bounding_rect = scene_ -> boundingRectFromXml(document_xml);
|
||||
if (pasted_content_bounding_rect.isEmpty()) return;
|
||||
|
||||
// copier/coller par choix de la zone de collage
|
||||
to_paste_in_area_ = clipboard_text;
|
||||
getPasteArea(pasted_content_bounding_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait de coller le contenu du presse-papier = l'importer dans
|
||||
l'element. Cette methode examine le contenu du presse-papier. Si celui-ci
|
||||
est exploitable, elle le colle a la position passee en parametre.
|
||||
@see pasteAreaDefined(const QRectF &)
|
||||
@param position Point de collage
|
||||
*/
|
||||
ElementContent ElementView::paste(const QPointF &position) {
|
||||
QString clipboard_text = QApplication::clipboard() -> text();
|
||||
if (clipboard_text.isEmpty()) return(ElementContent());
|
||||
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(clipboard_text)) return(ElementContent());
|
||||
|
||||
// objet pour recuperer le contenu ajoute au schema par le coller
|
||||
return(paste(document_xml, position));
|
||||
}
|
||||
|
||||
/**
|
||||
@param to_paste Rectangle englobant les parties a coller
|
||||
*/
|
||||
void ElementView::getPasteArea(const QRectF &to_paste) {
|
||||
// on copie le rectangle fourni - on s'interesse a ses dimensions, pas a sa position
|
||||
QRectF used_rect(to_paste);
|
||||
|
||||
// on lui attribue pour centre l'origine du repere
|
||||
if (underMouse()) {
|
||||
used_rect.moveCenter(mapToScene(mapFromGlobal(QCursor::pos())));
|
||||
} else {
|
||||
used_rect.moveCenter(QPointF(0.0, 0.0));
|
||||
}
|
||||
scene_ -> getPasteArea(used_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Slot appele lorsque la scene annonce avoir defini une zone de collage
|
||||
@param target_rect Rectangle cible pour le collage
|
||||
*/
|
||||
ElementContent ElementView::pasteAreaDefined(const QRectF &target_rect) {
|
||||
if (to_paste_in_area_.isEmpty()) return(ElementContent());
|
||||
|
||||
QDomDocument xml_document;
|
||||
if (!xml_document.setContent(to_paste_in_area_)) {
|
||||
to_paste_in_area_.clear();
|
||||
return(ElementContent());
|
||||
} else {
|
||||
return(paste(xml_document, target_rect.topLeft()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Colle le document XML xml_document a la position pos
|
||||
@param xml_document Document XML a coller
|
||||
@param pos Coin superieur gauche du rectangle cible
|
||||
*/
|
||||
ElementContent ElementView::paste(const QDomDocument &xml_document, const QPointF &pos) {
|
||||
// objet pour recuperer le contenu ajoute au schema par le coller
|
||||
ElementContent content_pasted;
|
||||
scene_ -> fromXml(xml_document, pos, false, &content_pasted);
|
||||
|
||||
// si quelque chose a effectivement ete ajoute au schema, on cree un objet d'annulation
|
||||
if (content_pasted.count()) {
|
||||
scene_ -> clearSelection();
|
||||
PastePartsCommand *undo_object = new PastePartsCommand(this, content_pasted);
|
||||
scene_ -> undoStack().push(undo_object);
|
||||
}
|
||||
return(content_pasted);
|
||||
}
|
||||
|
||||
/**
|
||||
Colle le document XML xml_document a la position pos
|
||||
@param xml_document Document XML a coller
|
||||
*/
|
||||
ElementContent ElementView::pasteWithOffset(const QDomDocument &xml_document) {
|
||||
// objet pour recuperer le contenu ajoute au schema par le coller
|
||||
ElementContent content_pasted;
|
||||
|
||||
// rectangle source
|
||||
QRectF pasted_content_bounding_rect = scene_ -> boundingRectFromXml(xml_document);
|
||||
if (pasted_content_bounding_rect.isEmpty()) return(content_pasted);
|
||||
|
||||
// copier/coller avec decalage
|
||||
++ offset_paste_count_;
|
||||
if (offset_paste_count_ == 1) {
|
||||
start_top_left_corner_ = pasted_content_bounding_rect.topLeft();
|
||||
} else {
|
||||
pasted_content_bounding_rect.moveTopLeft(start_top_left_corner_);
|
||||
}
|
||||
|
||||
// on applique le decalage qui convient
|
||||
QRectF final_pasted_content_bounding_rect = applyMovement(
|
||||
pasted_content_bounding_rect,
|
||||
QETElementEditor::pasteMovement(),
|
||||
QETElementEditor::pasteOffset()
|
||||
);
|
||||
|
||||
QPointF old_start_top_left_corner_ = start_top_left_corner_;
|
||||
start_top_left_corner_ = final_pasted_content_bounding_rect.topLeft();
|
||||
scene_ -> fromXml(xml_document, start_top_left_corner_, false, &content_pasted);
|
||||
|
||||
// si quelque chose a effectivement ete ajoute au schema, on cree un objet d'annulation
|
||||
if (content_pasted.count()) {
|
||||
scene_ -> clearSelection();
|
||||
PastePartsCommand *undo_object = new PastePartsCommand(this, content_pasted);
|
||||
undo_object -> setOffset(offset_paste_count_ - 1, old_start_top_left_corner_, offset_paste_count_, start_top_left_corner_);
|
||||
scene_ -> undoStack().push(undo_object);
|
||||
}
|
||||
return(content_pasted);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les clics sur la vue - permet de coller lorsaue l'on enfonce le bouton
|
||||
du milieu de la souris.
|
||||
@param e QMouseEvent decrivant l'evenement souris
|
||||
*/
|
||||
void ElementView::mousePressEvent(QMouseEvent *e) {
|
||||
if (e -> buttons() & Qt::MidButton) {
|
||||
paste(mapToScene(e -> pos()));
|
||||
}
|
||||
QGraphicsView::mousePressEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les actions liees a la rollette de la souris
|
||||
@param e QWheelEvent decrivant l'evenement rollette
|
||||
@@ -126,3 +338,107 @@ void ElementView::wheelEvent(QWheelEvent *e) {
|
||||
QAbstractScrollArea::wheelEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'arriere-plan de l'editeur, cad la grille.
|
||||
@param p Le QPainter a utiliser pour dessiner
|
||||
@param r Le rectangle de la zone a dessiner
|
||||
*/
|
||||
void ElementView::drawBackground(QPainter *p, const QRectF &r) {
|
||||
p -> save();
|
||||
|
||||
// desactive tout antialiasing, sauf pour le texte
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, true);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
|
||||
// dessine un fond blanc
|
||||
p -> setPen(Qt::NoPen);
|
||||
p -> setBrush(Qt::white);
|
||||
p -> drawRect(r);
|
||||
|
||||
// encadre la zone dessinable de l'element
|
||||
QRectF drawable_area(-scene_ -> hotspot().x(), -scene_ -> hotspot().y(), scene_ -> width(), scene_ -> height());
|
||||
p -> setPen(Qt::black);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
p -> drawRect(drawable_area);
|
||||
|
||||
// determine le zoom en cours
|
||||
qreal zoom_factor = matrix().m11();
|
||||
|
||||
// choisit la granularite de la grille en fonction du zoom en cours
|
||||
int drawn_x_grid = scene_ -> xGrid();
|
||||
int drawn_y_grid = scene_ -> yGrid();
|
||||
bool draw_grid = true;
|
||||
bool draw_cross = false;
|
||||
if (zoom_factor < (4.0/3.0)) {
|
||||
// pas de grille du tout
|
||||
draw_grid = false;
|
||||
} else if (zoom_factor < 4.0) {
|
||||
// grille a 10 px
|
||||
drawn_x_grid *= 10;
|
||||
drawn_y_grid *= 10;
|
||||
} else if (zoom_factor < 6.0) {
|
||||
// grille a 2 px (avec croix)
|
||||
drawn_x_grid *= 2;
|
||||
drawn_y_grid *= 2;
|
||||
draw_cross = true;
|
||||
} else {
|
||||
// grille a 1 px (avec croix)
|
||||
draw_cross = true;
|
||||
}
|
||||
|
||||
if (draw_grid) {
|
||||
// dessine les points de la grille
|
||||
p -> setPen(Qt::black);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
qreal limite_x = r.x() + r.width();
|
||||
qreal limite_y = r.y() + r.height();
|
||||
|
||||
int g_x = (int)ceil(r.x());
|
||||
while (g_x % drawn_x_grid) ++ g_x;
|
||||
int g_y = (int)ceil(r.y());
|
||||
while (g_y % drawn_y_grid) ++ g_y;
|
||||
|
||||
for (int gx = g_x ; gx < limite_x ; gx += drawn_x_grid) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += drawn_y_grid) {
|
||||
if (draw_cross) {
|
||||
if (!(gx % 10) && !(gy % 10)) {
|
||||
p -> drawLine(QLineF(gx - 0.25, gy, gx + 0.25, gy));
|
||||
p -> drawLine(QLineF(gx, gy - 0.25, gx, gy + 0.25));
|
||||
} else {
|
||||
p -> drawPoint(gx, gy);
|
||||
}
|
||||
} else {
|
||||
p -> drawPoint(gx, gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Applique le decalage offset dans le sens movement au rectangle start
|
||||
@param start rectangle a decaler
|
||||
@param movement Orientation du decalage a appliquer
|
||||
@param offset Decalage a appliquer
|
||||
*/
|
||||
QRectF ElementView::applyMovement(const QRectF &start, const QET::OrientedMovement &movement, const QPointF &offset) {
|
||||
// calcule le decalage a appliquer a partir de l'offset indique et du mouvement
|
||||
QPointF final_offset;
|
||||
if (movement == QET::ToNorthEast || movement == QET::ToEast || movement == QET::ToSouthEast) {
|
||||
final_offset.rx() = start.width() + offset.x();
|
||||
} else if (movement == QET::ToNorthWest || movement == QET::ToWest || movement == QET::ToSouthWest) {
|
||||
final_offset.rx() = -start.width() - offset.x();
|
||||
}
|
||||
|
||||
if (movement == QET::ToNorthWest || movement == QET::ToNorth || movement == QET::ToNorthEast) {
|
||||
final_offset.ry() = -start.height() - offset.y();
|
||||
} else if (movement == QET::ToSouthWest || movement == QET::ToSouth || movement == QET::ToSouthEast) {
|
||||
final_offset.ry() = start.height() + offset.y();
|
||||
}
|
||||
|
||||
// applique le decalage ainsi calcule
|
||||
return(start.translated(final_offset));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
class ElementView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
friend class PastePartsCommand;
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementView(ElementScene *, QWidget * = 0);
|
||||
@@ -37,9 +39,16 @@ class ElementView : public QGraphicsView {
|
||||
public:
|
||||
ElementScene *scene() const;
|
||||
void setScene(ElementScene *);
|
||||
QRectF viewedSceneRect() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void wheelEvent(QWheelEvent *);
|
||||
virtual void drawBackground(QPainter *, const QRectF &);
|
||||
|
||||
private:
|
||||
QRectF applyMovement(const QRectF &, const QET::OrientedMovement &, const QPointF &);
|
||||
|
||||
// slots
|
||||
public slots:
|
||||
@@ -48,9 +57,23 @@ class ElementView : public QGraphicsView {
|
||||
void zoomFit();
|
||||
void zoomReset();
|
||||
void adjustSceneRect();
|
||||
void cut();
|
||||
void copy();
|
||||
void paste();
|
||||
void pasteInArea();
|
||||
|
||||
private slots:
|
||||
void getPasteArea(const QRectF &);
|
||||
ElementContent pasteAreaDefined(const QRectF &);
|
||||
ElementContent paste(const QPointF &);
|
||||
ElementContent paste(const QDomDocument &, const QPointF &);
|
||||
ElementContent pasteWithOffset(const QDomDocument &);
|
||||
|
||||
//attributs
|
||||
private:
|
||||
ElementScene *scene_;
|
||||
QString to_paste_in_area_;
|
||||
int offset_paste_count_;
|
||||
QPointF start_top_left_corner_;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -63,9 +63,9 @@ EllipseEditor::~EllipseEditor() {
|
||||
*/
|
||||
void EllipseEditor::updateEllipse() {
|
||||
part -> setProperty("x", x -> text().toDouble());
|
||||
part -> setProperty("y", x -> text().toDouble());
|
||||
part -> setProperty("diameter_h", x -> text().toDouble());
|
||||
part -> setProperty("diameter_v", x -> text().toDouble());
|
||||
part -> setProperty("y", y -> text().toDouble());
|
||||
part -> setProperty("diameter_h", h -> text().toDouble());
|
||||
part -> setProperty("diameter_v", v -> text().toDouble());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du centre de l'ellipse et cree un objet d'annulation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
#include "lineeditor.h"
|
||||
#include "partline.h"
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@@ -38,16 +39,46 @@ LineEditor::LineEditor(QETElementEditor *editor, PartLine *line, QWidget *parent
|
||||
x2 -> setValidator(new QDoubleValidator(x2));
|
||||
y2 -> setValidator(new QDoubleValidator(y2));
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
grid -> addWidget(new QLabel("x1"), 0, 0);
|
||||
grid -> addWidget(x1, 0, 1);
|
||||
grid -> addWidget(new QLabel("y1"), 0, 2);
|
||||
grid -> addWidget(y1, 0, 3);
|
||||
grid -> addWidget(new QLabel("x2"), 1, 0);
|
||||
grid -> addWidget(x2, 1, 1);
|
||||
grid -> addWidget(new QLabel("y2"), 1, 2);
|
||||
grid -> addWidget(y2, 1, 3);
|
||||
end1_type = new QComboBox();
|
||||
end1_type -> addItem(QIcon(":/ico/endline-none.png"), tr("Normale", "type of the 1st end of a line"), QET::None );
|
||||
end1_type -> addItem(QIcon(":/ico/endline-simple.png"), tr("Fl\350che simple", "type of the 1st end of a line"), QET::Simple );
|
||||
end1_type -> addItem(QIcon(":/ico/endline-triangle.png"), tr("Fl\350che triangulaire", "type of the 1st end of a line"), QET::Triangle);
|
||||
end1_type -> addItem(QIcon(":/ico/endline-circle.png"), tr("Cercle", "type of the 1st end of a line"), QET::Circle );
|
||||
end1_type -> addItem(QIcon(":/ico/endline-diamond.png"), tr("Carr\351", "type of the 1st end of a line"), QET::Diamond );
|
||||
end2_type = new QComboBox();
|
||||
end2_type -> addItem(QIcon(":/ico/endline-none.png"), tr("Normale", "type of the 2nd end of a line"), QET::None );
|
||||
end2_type -> addItem(QIcon(":/ico/endline-simple.png"), tr("Fl\350che simple", "type of the 2nd end of a line"), QET::Simple );
|
||||
end2_type -> addItem(QIcon(":/ico/endline-triangle.png"), tr("Fl\350che triangulaire", "type of the 2nd end of a line"), QET::Triangle);
|
||||
end2_type -> addItem(QIcon(":/ico/endline-circle.png"), tr("Cercle", "type of the 2nd end of a line"), QET::Circle );
|
||||
end2_type -> addItem(QIcon(":/ico/endline-diamond.png"), tr("Carr\351", "type of the 2nd end of a line"), QET::Diamond );
|
||||
|
||||
end1_length = new QLineEdit();
|
||||
end2_length = new QLineEdit();
|
||||
|
||||
end1_length -> setValidator(new QDoubleValidator(end1_length));
|
||||
end2_length -> setValidator(new QDoubleValidator(end2_length));
|
||||
|
||||
QGridLayout *grid = new QGridLayout();
|
||||
grid -> addWidget(new QLabel("x1"), 0, 0);
|
||||
grid -> addWidget(x1, 0, 1);
|
||||
grid -> addWidget(new QLabel("y1"), 0, 2);
|
||||
grid -> addWidget(y1, 0, 3);
|
||||
grid -> addWidget(new QLabel("x2"), 1, 0);
|
||||
grid -> addWidget(x2, 1, 1);
|
||||
grid -> addWidget(new QLabel("y2"), 1, 2);
|
||||
grid -> addWidget(y2, 1, 3);
|
||||
|
||||
QGridLayout *grid2 = new QGridLayout();
|
||||
grid2 -> addWidget(new QLabel(tr("Fin 1")), 0, 0);
|
||||
grid2 -> addWidget(end1_type, 0, 1);
|
||||
grid2 -> addWidget(end1_length, 0, 2);
|
||||
grid2 -> addWidget(new QLabel(tr("Fin 2")), 1, 0);
|
||||
grid2 -> addWidget(end2_type, 1, 1);
|
||||
grid2 -> addWidget(end2_length, 1, 2);
|
||||
|
||||
QVBoxLayout *v_layout = new QVBoxLayout(this);
|
||||
v_layout -> addLayout(grid);
|
||||
v_layout -> addLayout(grid2);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
@@ -59,6 +90,10 @@ LineEditor::~LineEditor() {
|
||||
Met a jour la ligne a partir des donnees du formulaire
|
||||
*/
|
||||
void LineEditor::updateLine() {
|
||||
part -> setFirstEndType(static_cast<QET::EndType>(end1_type -> currentIndex()));
|
||||
part -> setFirstEndLength(end1_length -> text().toDouble());
|
||||
part -> setSecondEndType(static_cast<QET::EndType>(end2_type -> currentIndex()));
|
||||
part -> setSecondEndLength(end2_length -> text().toDouble());
|
||||
part -> setLine(
|
||||
QLineF(
|
||||
part -> mapFromScene(
|
||||
@@ -81,6 +116,14 @@ void LineEditor::updateLineY1() { addChangePartCommand(tr("ordonn\351e point 1")
|
||||
void LineEditor::updateLineX2() { addChangePartCommand(tr("abscisse point 2"), part, "x2", x2 -> text().toDouble()); }
|
||||
/// Met a jour l'ordonnee du second point de la ligne et cree un objet d'annulation
|
||||
void LineEditor::updateLineY2() { addChangePartCommand(tr("ordonn\351e point 2"), part, "y2", y2 -> text().toDouble()); }
|
||||
/// Met a jour le type de la premiere extremite
|
||||
void LineEditor::updateLineEndType1() { addChangePartCommand(tr("type fin 1"), part, "end1", end1_type -> currentIndex()); }
|
||||
/// Met a jour la longueur de la premiere extremite
|
||||
void LineEditor::updateLineEndLength1() { addChangePartCommand(tr("longueur fin 1"), part, "length1", end1_length -> text()); }
|
||||
/// Met a jour le type de la seconde extremite
|
||||
void LineEditor::updateLineEndType2() { addChangePartCommand(tr("type fin 2"), part, "end2", end2_type -> currentIndex()); }
|
||||
/// Met a jour la longueur de la seconde extremite
|
||||
void LineEditor::updateLineEndLength2() { addChangePartCommand(tr("longueur fin 2"), part, "length2", end2_length -> text()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
@@ -93,6 +136,10 @@ void LineEditor::updateForm() {
|
||||
y1 -> setText(QString("%1").arg(p1.y()));
|
||||
x2 -> setText(QString("%1").arg(p2.x()));
|
||||
y2 -> setText(QString("%1").arg(p2.y()));
|
||||
end1_type -> setCurrentIndex(part -> firstEndType());
|
||||
end1_length -> setText(QString("%1").arg(part -> firstEndLength()));
|
||||
end2_type -> setCurrentIndex(part -> secondEndType());
|
||||
end2_length -> setText(QString("%1").arg(part -> secondEndLength()));
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
@@ -106,10 +153,18 @@ void LineEditor::activeConnections(bool active) {
|
||||
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLineY1()));
|
||||
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLineX2()));
|
||||
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLineY2()));
|
||||
connect(end1_type, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLineEndType1()));
|
||||
connect(end1_length, SIGNAL(editingFinished()), this, SLOT(updateLineEndLength1()));
|
||||
connect(end2_type, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLineEndType2()));
|
||||
connect(end2_length, SIGNAL(editingFinished()), this, SLOT(updateLineEndLength2()));
|
||||
} else {
|
||||
connect(x1, SIGNAL(editingFinished()), this, SLOT(updateLineX1()));
|
||||
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLineY1()));
|
||||
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLineX2()));
|
||||
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLineY2()));
|
||||
disconnect(x1, SIGNAL(editingFinished()), this, SLOT(updateLineX1()));
|
||||
disconnect(y1, SIGNAL(editingFinished()), this, SLOT(updateLineY1()));
|
||||
disconnect(x2, SIGNAL(editingFinished()), this, SLOT(updateLineX2()));
|
||||
disconnect(y2, SIGNAL(editingFinished()), this, SLOT(updateLineY2()));
|
||||
disconnect(end1_type, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLineEndType1()));
|
||||
disconnect(end1_length, SIGNAL(editingFinished()), this, SLOT(updateLineEndLength1()));
|
||||
disconnect(end2_type, SIGNAL(currentIndexChanged(int)), this, SLOT(updateLineEndType2()));
|
||||
disconnect(end2_length, SIGNAL(editingFinished()), this, SLOT(updateLineEndLength2()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -37,6 +37,8 @@ class LineEditor : public ElementItemEditor {
|
||||
private:
|
||||
PartLine *part;
|
||||
QLineEdit *x1, *y1, *x2, *y2;
|
||||
QComboBox *end1_type, *end2_type;
|
||||
QLineEdit *end1_length, *end2_length;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
@@ -45,6 +47,10 @@ class LineEditor : public ElementItemEditor {
|
||||
void updateLineY1();
|
||||
void updateLineX2();
|
||||
void updateLineY2();
|
||||
void updateLineEndType1();
|
||||
void updateLineEndLength1();
|
||||
void updateLineEndType2();
|
||||
void updateLineEndLength2();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -159,6 +159,7 @@ void PartArc::setProperty(const QString &property, const QVariant &value) {
|
||||
} else if (property == "angle") {
|
||||
setAngle(value.toInt());
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -48,7 +48,7 @@ class PartArc : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual QString name() const { return(QObject::tr("arc")); }
|
||||
virtual QString name() const { return(QObject::tr("arc", "element part name")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -125,6 +125,7 @@ void PartCircle::setProperty(const QString &property, const QVariant &value) {
|
||||
current_rect.setSize(QSizeF(new_diameter, new_diameter));
|
||||
setRect(current_rect);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -46,7 +46,7 @@ class PartCircle : public QGraphicsEllipseItem, public CustomElementGraphicPart
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual QString name() const { return(QObject::tr("cercle")); }
|
||||
virtual QString name() const { return(QObject::tr("cercle", "element part name")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -129,6 +129,7 @@ void PartEllipse::setProperty(const QString &property, const QVariant &value) {
|
||||
current_rect.setHeight(new_height);
|
||||
setRect(current_rect);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -46,7 +46,7 @@ class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual QString name() const { return(QObject::tr("ellipse")); }
|
||||
virtual QString name() const { return(QObject::tr("ellipse", "element part name")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -25,7 +25,14 @@
|
||||
@param parent Le QGraphicsItem parent de cette ligne
|
||||
@param scene La scene sur laquelle figure cette ligne
|
||||
*/
|
||||
PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsLineItem(parent, scene), CustomElementGraphicPart(editor) {
|
||||
PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsLineItem(parent, scene),
|
||||
CustomElementGraphicPart(editor),
|
||||
first_end(QET::None),
|
||||
first_length(1.5),
|
||||
second_end(QET::None),
|
||||
second_length(1.5)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new LineEditor(elementEditor(), this);
|
||||
@@ -38,6 +45,20 @@ PartLine::PartLine(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsSce
|
||||
PartLine::~PartLine() {
|
||||
}
|
||||
|
||||
/**
|
||||
@param end_type Type d'extremite
|
||||
@return Le nombre de "longueurs" requises pour dessiner une extremite de type end_type
|
||||
*/
|
||||
uint PartLine::requiredLengthForEndType(const QET::EndType &end_type) {
|
||||
uint length_count_required = 0;
|
||||
if (end_type == QET::Circle || end_type == QET::Diamond) {
|
||||
length_count_required = 2;
|
||||
} else if (end_type == QET::Simple || end_type == QET::Triangle) {
|
||||
length_count_required = 1;
|
||||
}
|
||||
return(length_count_required);
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine la ligne
|
||||
@param painter QPainter a utiliser pour rendre le dessin
|
||||
@@ -45,14 +66,91 @@ PartLine::~PartLine() {
|
||||
@param widget Widget sur lequel le rendu est effectue
|
||||
*/
|
||||
void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
|
||||
// inutile de dessiner une ligne nulle
|
||||
if (line().p1() == line().p2()) return;
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
painter -> setBrush(Qt::NoBrush);
|
||||
painter -> drawLine(line());
|
||||
painter -> setPen(t);
|
||||
|
||||
QPointF point1(line().p1());
|
||||
QPointF point2(line().p2());
|
||||
|
||||
qreal line_length(line().length());
|
||||
qreal pen_width = painter -> pen().widthF();
|
||||
|
||||
qreal length1 = first_length;
|
||||
qreal length2 = second_length;
|
||||
|
||||
//debugPaint(painter);
|
||||
|
||||
// determine s'il faut dessiner les extremites
|
||||
bool draw_1st_end, draw_2nd_end;
|
||||
qreal reduced_line_length = line_length - (length1 * requiredLengthForEndType(first_end));
|
||||
draw_1st_end = first_end && reduced_line_length >= 0;
|
||||
if (draw_1st_end) {
|
||||
reduced_line_length -= (length2 * requiredLengthForEndType(second_end));
|
||||
} else {
|
||||
reduced_line_length = line_length - (length2 * requiredLengthForEndType(second_end));
|
||||
}
|
||||
draw_2nd_end = second_end && reduced_line_length >= 0;
|
||||
|
||||
// dessine la premiere extremite
|
||||
QPointF start_point, stop_point;
|
||||
if (draw_1st_end) {
|
||||
QList<QPointF> four_points1(fourEndPoints(point1, point2, length1));
|
||||
if (first_end == QET::Circle) {
|
||||
painter -> drawEllipse(QRectF(four_points1[0] - QPointF(length1, length1), QSizeF(length1 * 2.0, length1 * 2.0)));
|
||||
start_point = four_points1[1];
|
||||
} else if (first_end == QET::Diamond) {
|
||||
painter -> drawPolygon(QPolygonF() << four_points1[1] << four_points1[2] << point1 << four_points1[3]);
|
||||
start_point = four_points1[1];
|
||||
} else if (first_end == QET::Simple) {
|
||||
painter -> drawPolyline(QPolygonF() << four_points1[3] << point1 << four_points1[2]);
|
||||
start_point = point1;
|
||||
|
||||
} else if (first_end == QET::Triangle) {
|
||||
painter -> drawPolygon(QPolygonF() << four_points1[0] << four_points1[2] << point1 << four_points1[3]);
|
||||
start_point = four_points1[0];
|
||||
}
|
||||
|
||||
// ajuste le depart selon l'epaisseur du trait
|
||||
if (pen_width && (first_end == QET::Simple || first_end == QET::Circle)) {
|
||||
start_point = QLineF(start_point, point2).pointAt(pen_width / 2.0 / line_length);
|
||||
}
|
||||
} else {
|
||||
start_point = point1;
|
||||
}
|
||||
|
||||
// dessine la seconde extremite
|
||||
if (draw_2nd_end) {
|
||||
QList<QPointF> four_points2(fourEndPoints(point2, point1, length2));
|
||||
if (second_end == QET::Circle) {
|
||||
painter -> drawEllipse(QRectF(four_points2[0] - QPointF(length2, length2), QSizeF(length2 * 2.0, length2 * 2.0)));
|
||||
stop_point = four_points2[1];
|
||||
} else if (second_end == QET::Diamond) {
|
||||
painter -> drawPolygon(QPolygonF() << four_points2[2] << point2 << four_points2[3] << four_points2[1]);
|
||||
stop_point = four_points2[1];
|
||||
} else if (second_end == QET::Simple) {
|
||||
painter -> drawPolyline(QPolygonF() << four_points2[3] << point2 << four_points2[2]);
|
||||
stop_point = point2;
|
||||
} else if (second_end == QET::Triangle) {
|
||||
painter -> drawPolygon(QPolygonF() << four_points2[0] << four_points2[2] << point2 << four_points2[3] << four_points2[0]);
|
||||
stop_point = four_points2[0];
|
||||
}
|
||||
|
||||
// ajuste l'arrivee selon l'epaisseur du trait
|
||||
if (pen_width && (second_end == QET::Simple || second_end == QET::Circle)) {
|
||||
stop_point = QLineF(point1, stop_point).pointAt((line_length - (pen_width / 2.0)) / line_length);
|
||||
}
|
||||
} else {
|
||||
stop_point = point2;
|
||||
}
|
||||
|
||||
painter -> drawLine(start_point, stop_point);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,6 +168,11 @@ const QDomElement PartLine::toXml(QDomDocument &xml_document) const {
|
||||
xml_element.setAttribute("y1", QString("%1").arg(p1.y()));
|
||||
xml_element.setAttribute("x2", QString("%1").arg(p2.x()));
|
||||
xml_element.setAttribute("y2", QString("%1").arg(p2.y()));
|
||||
xml_element.setAttribute("end1", QET::endTypeToString(first_end));
|
||||
xml_element.setAttribute("length1", first_length);
|
||||
xml_element.setAttribute("end2", QET::endTypeToString(second_end));
|
||||
xml_element.setAttribute("length2", second_length);
|
||||
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
@@ -92,6 +195,10 @@ void PartLine::fromXml(const QDomElement &qde) {
|
||||
)
|
||||
)
|
||||
);
|
||||
first_end = QET::endTypeFromString(qde.attribute("end1"));
|
||||
first_length = qde.attribute("length1", "1.5").toDouble();
|
||||
second_end = QET::endTypeFromString(qde.attribute("end2"));
|
||||
second_length = qde.attribute("length2", "1.5").toDouble();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,6 +208,8 @@ void PartLine::fromXml(const QDomElement &qde) {
|
||||
* y1 : ordonnee du second point
|
||||
* x2 : abscisse du premier point
|
||||
* y2 : ordonnee du second point
|
||||
*end1 : type d'embout du premier point
|
||||
*end2 : type d'embout du second point
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartLine::setProperty(const QString &property, const QVariant &value) {
|
||||
@@ -116,8 +225,20 @@ void PartLine::setProperty(const QString &property, const QVariant &value) {
|
||||
new_p2.setX(value.toDouble());
|
||||
} else if (property == "y2") {
|
||||
new_p2.setY(value.toDouble());
|
||||
} else setline = false;
|
||||
setLine(QLineF(mapFromScene(new_p1), mapFromScene(new_p2)));
|
||||
} else {
|
||||
setline = false;
|
||||
if (property == "end1") {
|
||||
setFirstEndType(static_cast<QET::EndType>(value.toUInt()));
|
||||
} else if (property == "end2") {
|
||||
setSecondEndType(static_cast<QET::EndType>(value.toUInt()));
|
||||
} else if (property == "length1") {
|
||||
setFirstEndLength(value.toDouble());
|
||||
} else if (property == "length2") {
|
||||
setSecondEndLength(value.toDouble());
|
||||
}
|
||||
}
|
||||
if (setline) setLine(QLineF(mapFromScene(new_p1), mapFromScene(new_p2)));
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +263,14 @@ QVariant PartLine::property(const QString &property) {
|
||||
return(sceneP2().x());
|
||||
} else if (property == "y2") {
|
||||
return(sceneP2().y());
|
||||
} else if (property == "end1") {
|
||||
return(firstEndType());
|
||||
} else if (property == "end2") {
|
||||
return(secondEndType());
|
||||
} else if (property == "length1") {
|
||||
return(firstEndLength());
|
||||
} else if (property == "length2") {
|
||||
return(secondEndLength());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
@@ -186,6 +315,24 @@ QPainterPath PartLine::shape() const {
|
||||
t.lineTo(points.at(2));
|
||||
t.lineTo(points.at(3));
|
||||
t.lineTo(points.at(0));
|
||||
|
||||
// n'en fait pas plus si la ligne se ramene a un point
|
||||
if (line().p1() == line().p2()) return(t);
|
||||
|
||||
// ajoute un cercle pour l'extremite 1 si besoin
|
||||
if (first_end) {
|
||||
QPainterPath t2;
|
||||
t2.addEllipse(firstEndCircleRect());
|
||||
t.addPath(t2.subtracted(t));
|
||||
}
|
||||
|
||||
// ajoute un cercle pour l'extremite 2 si besoin
|
||||
if (second_end) {
|
||||
QPainterPath t2;
|
||||
t2.addEllipse(secondEndCircleRect());
|
||||
t.addPath(t2.subtracted(t));
|
||||
}
|
||||
|
||||
return(t);
|
||||
}
|
||||
|
||||
@@ -233,12 +380,86 @@ QList<QPointF> PartLine::fourShapePoints() const {
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle encadrant l'integralite de la premiere extremite
|
||||
*/
|
||||
QRectF PartLine::firstEndCircleRect() const {
|
||||
QList<QPointF> interesting_points = fourEndPoints(
|
||||
line().p1(),
|
||||
line().p2(),
|
||||
first_length
|
||||
);
|
||||
|
||||
QRectF end_rect(
|
||||
interesting_points[0] - QPointF(first_length, first_length),
|
||||
QSizeF(2.0 * first_length, 2.0 * first_length)
|
||||
);
|
||||
|
||||
return(end_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle encadrant l'integralite de la seconde extremite
|
||||
*/
|
||||
QRectF PartLine::secondEndCircleRect() const {
|
||||
QList<QPointF> interesting_points = fourEndPoints(
|
||||
line().p2(),
|
||||
line().p1(),
|
||||
second_length
|
||||
);
|
||||
|
||||
QRectF end_rect(
|
||||
interesting_points[0] - QPointF(second_length, second_length),
|
||||
QSizeF(2.0 * second_length, 2.0 * second_length)
|
||||
);
|
||||
|
||||
return(end_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
Affiche differentes composantes du dessin :
|
||||
- le boundingRect
|
||||
- les point speciaux a chaque extremite
|
||||
- la quadrature du cercle a chaque extremite, meme si celle-ci est d'un
|
||||
autre type
|
||||
*/
|
||||
void PartLine::debugPaint(QPainter *painter) {
|
||||
painter -> save();
|
||||
painter -> setPen(Qt::gray);
|
||||
painter -> drawRect(boundingRect());
|
||||
|
||||
painter -> setPen(Qt::green);
|
||||
painter -> drawRect(firstEndCircleRect());
|
||||
painter -> drawRect(secondEndCircleRect());
|
||||
|
||||
painter -> setPen(Qt::red);
|
||||
foreach(QPointF pointy, fourEndPoints(line().p1(), line().p2(), first_length)) {
|
||||
painter -> drawEllipse(pointy, 0.1, 0.1);
|
||||
}
|
||||
foreach(QPointF pointy, fourEndPoints(line().p2(), line().p1(), second_length)) {
|
||||
painter -> drawEllipse(pointy, 0.1, 0.1);
|
||||
}
|
||||
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartLine::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsLineItem::boundingRect());
|
||||
|
||||
// cas special : le cercle sort largement du bounding rect originel
|
||||
if (first_end == QET::Circle) {
|
||||
r = r.united(firstEndCircleRect());
|
||||
}
|
||||
|
||||
if (second_end == QET::Circle) {
|
||||
r = r.united(secondEndCircleRect());
|
||||
}
|
||||
|
||||
// la taille du bounding rect est ajustee de 0.2px
|
||||
qreal adjust = 0.6;
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
@@ -251,3 +472,91 @@ QRectF PartLine::boundingRect() const {
|
||||
bool PartLine::isUseless() const {
|
||||
return(sceneP1() == sceneP2());
|
||||
}
|
||||
|
||||
/**
|
||||
@param end_type nouveau type d'embout pour l'extremite 1
|
||||
*/
|
||||
void PartLine::setFirstEndType(const QET::EndType &end_type) {
|
||||
first_end = end_type;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le type d'embout pour l'extremite 1
|
||||
*/
|
||||
QET::EndType PartLine::firstEndType() const {
|
||||
return(first_end);
|
||||
}
|
||||
|
||||
/**
|
||||
@param end_type Nouveau type d'embout pour l'extremite 2
|
||||
*/
|
||||
void PartLine::setSecondEndType(const QET::EndType &end_type) {
|
||||
second_end = end_type;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le type d'embout pour l'extremite 2
|
||||
*/
|
||||
QET::EndType PartLine::secondEndType() const {
|
||||
return(second_end);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Les quatre points interessants a l'extremite d'une droite
|
||||
Ces points sont, dans l'ordre :
|
||||
* O : point sur la ligne, a une distance length de l'extremite
|
||||
* A : point sur la ligne a une distance 2 x length de l'extremite
|
||||
* B : point a une distance length de O - O est le projete de B sur la droite
|
||||
* C : point a une distance length de O - O est le projete de C sur la droite
|
||||
B et C sont situes de part et d'autre de la ligne
|
||||
@param end_point Extremite concernee
|
||||
@param other_point Autre point permettant de definir une ligne
|
||||
@param length Longueur a utiliser entre l'extremite et le point O
|
||||
*/
|
||||
QList<QPointF> PartLine::fourEndPoints(const QPointF &end_point, const QPointF &other_point, const qreal &length) {
|
||||
// vecteur et longueur de la ligne
|
||||
QPointF line_vector = end_point - other_point;
|
||||
qreal line_length = sqrt(pow(line_vector.x(), 2) + pow(line_vector.y(), 2));
|
||||
|
||||
// vecteur unitaire et vecteur perpendiculaire
|
||||
QPointF u(line_vector / line_length * length);
|
||||
QPointF v(-u.y(), u.x());
|
||||
|
||||
// points O, A, B et C
|
||||
QPointF o(end_point - u);
|
||||
QPointF a(o - u);
|
||||
QPointF b(o + v);
|
||||
QPointF c(o - v);
|
||||
|
||||
return(QList<QPointF>() << o << a << b << c);
|
||||
}
|
||||
|
||||
/**
|
||||
@param length nouvelle longueur de la premiere extremite
|
||||
la longueur de l'extemite ne peut exceder celle de la ligne
|
||||
*/
|
||||
void PartLine::setFirstEndLength(const qreal &length) {
|
||||
first_length = qMin(qAbs(length), line().length());
|
||||
}
|
||||
|
||||
/**
|
||||
@return longueur de la premiere extremite
|
||||
*/
|
||||
qreal PartLine::firstEndLength() const {
|
||||
return(first_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@param length nouvelle longueur de la seconde extremite
|
||||
la longueur de l'extemite ne peut exceder celle de la ligne
|
||||
*/
|
||||
void PartLine::setSecondEndLength(const qreal &length) {
|
||||
second_length = qMin(qAbs(length), line().length());
|
||||
}
|
||||
|
||||
/**
|
||||
@return longueur de la seconde extremite
|
||||
*/
|
||||
qreal PartLine::secondEndLength() const {
|
||||
return(second_length);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -19,10 +19,18 @@
|
||||
#define PART_LINE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
#include "qet.h"
|
||||
class LineEditor;
|
||||
/**
|
||||
Cette classe represente une ligne pouvant etre utilisee pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
Une ligne est composee de deux points. Elle peut comporter des extremites
|
||||
speciales definissables grace aux methodes setFirstEndType et
|
||||
setSecondEndType. La taille des extremites est definissable via les
|
||||
methodes setFirstEndLength et setSecondEndLength.
|
||||
A noter que les extremites ne sont pas dessinees si la longueur requise
|
||||
pour leur dessin n'est pas contenue dans la ligne. S'il n'y a de la place
|
||||
que pour une seule extremite, c'est la premiere qui est privilegiee.
|
||||
*/
|
||||
class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
@@ -36,17 +44,22 @@ class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
|
||||
// attributs
|
||||
private:
|
||||
LineEditor *informations;
|
||||
QET::EndType first_end;
|
||||
qreal first_length;
|
||||
QET::EndType second_end;
|
||||
qreal second_length;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1104 };
|
||||
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartLine avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual QString name() const { return(QObject::tr("ligne")); }
|
||||
virtual QString name() const { return(QObject::tr("ligne", "element part name")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneP1() const;
|
||||
@@ -56,11 +69,23 @@ class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
virtual void setFirstEndType(const QET::EndType &);
|
||||
virtual QET::EndType firstEndType() const;
|
||||
virtual void setSecondEndType(const QET::EndType &);
|
||||
virtual QET::EndType secondEndType() const;
|
||||
virtual void setFirstEndLength(const qreal &);
|
||||
virtual qreal firstEndLength() const;
|
||||
virtual void setSecondEndLength(const qreal &);
|
||||
virtual qreal secondEndLength() const;
|
||||
static uint requiredLengthForEndType(const QET::EndType &);
|
||||
static QList<QPointF> fourEndPoints(const QPointF &, const QPointF &, const qreal &);
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
|
||||
private:
|
||||
QList<QPointF> fourShapePoints() const;
|
||||
QRectF firstEndCircleRect() const;
|
||||
QRectF secondEndCircleRect() const;
|
||||
void debugPaint(QPainter *);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -114,6 +114,7 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWi
|
||||
void PartPolygon::setProperty(const QString &property, const QVariant &value) {
|
||||
CustomElementGraphicPart::setProperty(property, value);
|
||||
if (property == "closed") closed = value.toBool();
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -58,7 +58,7 @@ class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("polygone")); }
|
||||
virtual QString name() const { return(QObject::tr("polygone", "element part name")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
virtual QRectF boundingRect() const;
|
||||
|
||||
207
sources/editor/partrectangle.cpp
Normal file
207
sources/editor/partrectangle.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
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 "partrectangle.h"
|
||||
#include "rectangleeditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de ce rectangle
|
||||
@param scene La scene sur laquelle figure ce rectangle
|
||||
*/
|
||||
PartRectangle::PartRectangle(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsRectItem(parent, scene), CustomElementGraphicPart(editor) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new RectangleEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartRectangle::~PartRectangle() {
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le rectangle
|
||||
@param painter QPainter a utiliser pour rendre le dessin
|
||||
@param options Options pour affiner le rendu
|
||||
@param widget Widget sur lequel le rendu est effectue
|
||||
*/
|
||||
void PartRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
}
|
||||
|
||||
// force le type de jointures pour les rectangles
|
||||
t.setJoinStyle(Qt::MiterJoin);
|
||||
|
||||
// force le dessin avec un trait fin si l'une des dimensions du rectangle est nulle
|
||||
if (!rect().width() || !rect().height()) {
|
||||
t.setWidth(0);
|
||||
}
|
||||
|
||||
painter -> setPen(t);
|
||||
painter -> drawRect(rect());
|
||||
if (isSelected()) {
|
||||
painter -> setRenderHint(QPainter::Antialiasing, false);
|
||||
painter -> setPen((painter -> brush().color() == QColor(Qt::black) && painter -> brush().isOpaque()) ? Qt::yellow : Qt::blue);
|
||||
QPointF center = rect().center();
|
||||
painter -> drawLine(QLineF(center.x() - 2.0, center.y(), center.x() + 2.0, center.y()));
|
||||
painter -> drawLine(QLineF(center.x(), center.y() - 2.0, center.x(), center.y() + 2.0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le rectangle en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant le rectangle
|
||||
*/
|
||||
const QDomElement PartRectangle::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("rect");
|
||||
QPointF top_left(sceneTopLeft());
|
||||
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
|
||||
xml_element.setAttribute("width", QString("%1").arg(rect().width()));
|
||||
xml_element.setAttribute("height", QString("%1").arg(rect().height()));
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'une rectangle depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartRectangle::fromXml(const QDomElement &qde) {
|
||||
stylesFromXml(qde);
|
||||
setRect(
|
||||
QRectF(
|
||||
mapFromScene(
|
||||
qde.attribute("x", "0").toDouble(),
|
||||
qde.attribute("y", "0").toDouble()
|
||||
),
|
||||
QSizeF(
|
||||
qde.attribute("width", "0").toDouble(),
|
||||
qde.attribute("height", "0").toDouble()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee du rectangle
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse du coin superieur gauche du rectangle
|
||||
* y : ordonnee du coin superieur gauche du rectangle
|
||||
* width : largeur du rectangle
|
||||
* height : hauteur du rectangle
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartRectangle::setProperty(const QString &property, const QVariant &value) {
|
||||
CustomElementGraphicPart::setProperty(property, value);
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
if (property == "x") {
|
||||
QRectF current_rect = rect();
|
||||
QPointF current_pos = mapToScene(current_rect.topLeft());
|
||||
setRect(current_rect.translated(value.toDouble() - current_pos.x(), 0.0));
|
||||
} else if (property == "y") {
|
||||
QRectF current_rect = rect();
|
||||
QPointF current_pos = mapToScene(current_rect.topLeft());
|
||||
setRect(current_rect.translated(0.0, value.toDouble() - current_pos.y()));
|
||||
} else if (property == "width") {
|
||||
qreal new_width = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.setWidth(new_width);
|
||||
setRect(current_rect);
|
||||
} else if (property == "height") {
|
||||
qreal new_height = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.setHeight(new_height);
|
||||
setRect(current_rect);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee du rectangle
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse du coin superieur gauche du rectangle
|
||||
* y : ordonnee du coin superieur gauche du rectangle
|
||||
* width : largeur du rectangle
|
||||
* height : hauteur du rectangle
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartRectangle::property(const QString &property) {
|
||||
// appelle la methode property de CustomElementGraphicpart pour les styles
|
||||
QVariant style_property = CustomElementGraphicPart::property(property);
|
||||
if (style_property != QVariant()) return(style_property);
|
||||
|
||||
if (property == "x") {
|
||||
return(mapToScene(rect().topLeft()).x());
|
||||
} else if (property == "y") {
|
||||
return(mapToScene(rect().topLeft()).y());
|
||||
} else if (property == "width") {
|
||||
return(rect().width());
|
||||
} else if (property == "height") {
|
||||
return(rect().height());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartRectangle::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsRectItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le coin superieur gauche du rectangle, dans les coordonnees de la
|
||||
scene.
|
||||
*/
|
||||
QPointF PartRectangle::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un rectangle est pertinent des lors que ses dimensions ne sont pas nulles.
|
||||
*/
|
||||
bool PartRectangle::isUseless() const {
|
||||
return(rect().isNull());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartRectangle::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsRectItem::boundingRect().normalized());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
61
sources/editor/partrectangle.h
Normal file
61
sources/editor/partrectangle.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef PART_RECTANGLE_H
|
||||
#define PART_RECTANGLE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class RectangleEditor;
|
||||
/**
|
||||
Cette classe represente un rectangle pouvant etre utilise pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartRectangle : public QGraphicsRectItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartRectangle(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartRectangle();
|
||||
|
||||
private:
|
||||
PartRectangle(const PartRectangle &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
RectangleEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1109 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartRectangle avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual QString name() const { return(QObject::tr("rectangle", "element part name")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
virtual QRectF boundingRect() const;
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -39,6 +39,7 @@ PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent, QGra
|
||||
|
||||
/// Destructeur
|
||||
PartTerminal::~PartTerminal() {
|
||||
if (informations -> parentWidget()) return; // le widget sera supprime par son parent
|
||||
delete informations;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -48,7 +48,7 @@ class PartTerminal : public CustomElementPart, public QGraphicsItem {
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("borne")); }
|
||||
virtual QString name() const { return(QObject::tr("borne", "element part name")); }
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual QWidget *elementInformations();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -33,14 +33,14 @@ PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent, ElementScene
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setPlainText(QObject::tr("T"));
|
||||
setPlainText(QObject::tr("T", "default text when adding a text in the element editor"));
|
||||
infos = new TextEditor(elementEditor(), this);
|
||||
infos -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
|
||||
/// Destructeur
|
||||
PartText::~PartText() {
|
||||
if (infos -> parentWidget()) return; // le widget sera supprime par son parent
|
||||
delete infos;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ void PartText::focusOutEvent(QFocusEvent *e) {
|
||||
if (previous_text != toPlainText()) {
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
TextEditor::tr("texte") + " " + name(),
|
||||
TextEditor::tr("contenu") + " " + name(),
|
||||
this,
|
||||
"text",
|
||||
previous_text,
|
||||
@@ -139,6 +139,13 @@ void PartText::focusOutEvent(QFocusEvent *e) {
|
||||
);
|
||||
previous_text = toPlainText();
|
||||
}
|
||||
|
||||
// deselectionne le texte
|
||||
QTextCursor qtc = textCursor();
|
||||
qtc.clearSelection();
|
||||
setTextCursor(qtc);
|
||||
|
||||
setTextInteractionFlags(Qt::NoTextInteraction);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
@@ -176,6 +183,7 @@ void PartText::setProperty(const QString &property, const QVariant &value) {
|
||||
} else if (property == "text") {
|
||||
setPlainText(value.toString());
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -44,7 +44,7 @@ class PartText : public QGraphicsTextItem, public CustomElementPart {
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("texte")); }
|
||||
virtual QString name() const { return(QObject::tr("texte", "element part name")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
QWidget *elementInformations();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -33,13 +33,14 @@ PartTextField::PartTextField(QETElementEditor *editor, QGraphicsItem *parent, QG
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setPlainText(QObject::tr("_"));
|
||||
setPlainText(QObject::tr("_", "default text when adding a textfield in the element editor"));
|
||||
infos = new TextFieldEditor(elementEditor(), this);
|
||||
infos -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartTextField::~PartTextField() {
|
||||
if (infos -> parentWidget()) return; // le widget sera supprime par son parent
|
||||
delete infos;
|
||||
}
|
||||
|
||||
@@ -148,7 +149,7 @@ void PartTextField::focusOutEvent(QFocusEvent *e) {
|
||||
if (previous_text != toPlainText()) {
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
TextFieldEditor::tr("texte") + " " + name(),
|
||||
TextFieldEditor::tr("contenu") + " " + name(),
|
||||
this,
|
||||
"text",
|
||||
previous_text,
|
||||
@@ -157,6 +158,13 @@ void PartTextField::focusOutEvent(QFocusEvent *e) {
|
||||
);
|
||||
previous_text = toPlainText();
|
||||
}
|
||||
|
||||
// deselectionne le texte
|
||||
QTextCursor qtc = textCursor();
|
||||
qtc.clearSelection();
|
||||
setTextCursor(qtc);
|
||||
|
||||
setTextInteractionFlags(Qt::NoTextInteraction);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
@@ -197,6 +205,7 @@ void PartTextField::setProperty(const QString &property, const QVariant &value)
|
||||
} else if (property == "rotate") {
|
||||
follow_parent_rotations = value.toBool();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -48,7 +48,7 @@ class PartTextField : public QGraphicsTextItem, public CustomElementPart {
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("champ de texte")); }
|
||||
virtual QString name() const { return(QObject::tr("champ de texte", "element part name")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
QWidget *elementInformations();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -69,8 +69,8 @@ void PolygonEditor::updatePolygonPoints() {
|
||||
if (points.count() < 2) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Erreur"),
|
||||
tr("Le polygone doit comporter au moins deux points.")
|
||||
tr("Erreur", "message box title"),
|
||||
tr("Le polygone doit comporter au moins deux points.", "message box content")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "customelementpart.h"
|
||||
#include "newelementwizard.h"
|
||||
#include "elementitemeditor.h"
|
||||
#include "elementdefinition.h"
|
||||
#include "elementdialog.h"
|
||||
#include "recentfiles.h"
|
||||
|
||||
/**
|
||||
@@ -31,8 +33,8 @@
|
||||
QETElementEditor::QETElementEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
read_only(false),
|
||||
min_title(tr("QElectroTech - \311diteur d'\351l\351ment")),
|
||||
_filename(QString())
|
||||
min_title(tr("QElectroTech - \311diteur d'\351l\351ment", "window title")),
|
||||
opened_from_file(false)
|
||||
{
|
||||
setWindowTitle(min_title);
|
||||
setWindowIcon(QIcon(":/ico/qet.png"));
|
||||
@@ -47,6 +49,7 @@ QETElementEditor::QETElementEditor(QWidget *parent) :
|
||||
|
||||
// lecture des parametres
|
||||
readSettings();
|
||||
slot_updateMenus();
|
||||
|
||||
// affichage
|
||||
show();
|
||||
@@ -62,12 +65,18 @@ QETElementEditor::~QETElementEditor() {
|
||||
void QETElementEditor::setupActions() {
|
||||
new_element = new QAction(QIcon(":/ico/new.png"), tr("&Nouveau"), this);
|
||||
open = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir"), this);
|
||||
open_file = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir depuis un fichier"), this);
|
||||
save = new QAction(QIcon(":/ico/save.png"), tr("&Enregistrer"), this);
|
||||
save_as = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer sous"), this);
|
||||
save_as_file = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer dans un fichier"), this);
|
||||
reload = new QAction(QIcon(":/ico/reload.png"), tr("Recharger"), this);
|
||||
quit = new QAction(QIcon(":/ico/exit.png"), tr("&Quitter"), this);
|
||||
selectall = new QAction( tr("Tout s\351lectionner"), this);
|
||||
deselectall = new QAction( tr("D\351s\351lectionner tout"), this);
|
||||
cut = new QAction(QIcon(":/ico/cut.png"), tr("Co&uper"), this);
|
||||
copy = new QAction(QIcon(":/ico/copy.png"), tr("Cop&ier"), this);
|
||||
paste = new QAction(QIcon(":/ico/paste.png"), tr("C&oller"), this);
|
||||
paste_in_area = new QAction(QIcon(":/ico/paste.png"), tr("C&oller dans la zone..."), this);
|
||||
inv_select = new QAction( tr("Inverser la s\351lection"), this);
|
||||
edit_delete = new QAction(QIcon(":/ico/delete.png"), tr("&Supprimer"), this);
|
||||
zoom_in = new QAction(QIcon(":/ico/viewmag+.png"), tr("Zoom avant"), this);
|
||||
@@ -83,6 +92,7 @@ void QETElementEditor::setupActions() {
|
||||
edit_forward = new QAction(QIcon(":/ico/bring_forward.png"),tr("Amener au premier plan"), this);
|
||||
move = new QAction(QIcon(":/ico/select.png"), tr("D\351placer un objet"), this);
|
||||
add_line = new QAction(QIcon(":/ico/line.png"), tr("Ajouter une ligne"), this);
|
||||
add_rectangle = new QAction(QIcon(":/ico/rectangle.png"), tr("Ajouter un rectangle"), this);
|
||||
add_ellipse = new QAction(QIcon(":/ico/ellipse.png"), tr("Ajouter une ellipse"), this);
|
||||
add_circle = new QAction(QIcon(":/ico/circle.png"), tr("Ajouter un cercle"), this);
|
||||
add_polygon = new QAction(QIcon(":/ico/polygon.png"), tr("Ajouter un polygone"), this);
|
||||
@@ -91,6 +101,17 @@ void QETElementEditor::setupActions() {
|
||||
add_terminal = new QAction(QIcon(":/ico/terminal.png"), tr("Ajouter une borne"), this);
|
||||
add_textfield = new QAction(QIcon(":/ico/textfield.png"), tr("Ajouter un champ de texte"), this);
|
||||
|
||||
QString add_status_tip = tr("Maintenez la touche Shift enfonc\351e pour effectuer plusieurs ajouts d'affil\351e");
|
||||
add_line -> setStatusTip(add_status_tip);
|
||||
add_rectangle -> setStatusTip(add_status_tip);
|
||||
add_ellipse -> setStatusTip(add_status_tip);
|
||||
add_circle -> setStatusTip(add_status_tip);
|
||||
add_text -> setStatusTip(add_status_tip);
|
||||
add_arc -> setStatusTip(add_status_tip);
|
||||
add_terminal -> setStatusTip(add_status_tip);
|
||||
add_textfield -> setStatusTip(add_status_tip);
|
||||
add_polygon -> setStatusTip(tr("Utilisez le bouton droit de la souris pour poser le dernier point du polygone"));
|
||||
|
||||
undo = ce_scene -> undoStack().createUndoAction(this, tr("Annuler"));
|
||||
redo = ce_scene -> undoStack().createRedoAction(this, tr("Refaire"));
|
||||
undo -> setIcon(QIcon(":/ico/undo.png"));
|
||||
@@ -100,12 +121,18 @@ void QETElementEditor::setupActions() {
|
||||
|
||||
new_element -> setShortcut(QKeySequence::New);
|
||||
open -> setShortcut(QKeySequence::Open);
|
||||
open_file -> setShortcut(tr("Ctrl+Shift+O"));
|
||||
save -> setShortcut(QKeySequence::Save);
|
||||
save_as_file -> setShortcut(tr("Ctrl+Shift+S"));
|
||||
reload -> setShortcut(Qt::Key_F5);
|
||||
quit -> setShortcut(QKeySequence(tr("Ctrl+Q")));
|
||||
selectall -> setShortcut(QKeySequence::SelectAll);
|
||||
deselectall -> setShortcut(QKeySequence(tr("Ctrl+Shift+A")));
|
||||
inv_select -> setShortcut(QKeySequence(tr("Ctrl+I")));
|
||||
cut -> setShortcut(QKeySequence::Cut);
|
||||
copy -> setShortcut(QKeySequence::Copy);
|
||||
paste -> setShortcut(QKeySequence::Paste);
|
||||
paste_in_area -> setShortcut(tr("Ctrl+Shift+V"));
|
||||
edit_delete -> setShortcut(QKeySequence(tr("Suppr")));
|
||||
|
||||
zoom_in -> setShortcut(QKeySequence::ZoomIn);
|
||||
@@ -124,13 +151,19 @@ void QETElementEditor::setupActions() {
|
||||
|
||||
connect(new_element, SIGNAL(triggered()), this, SLOT(slot_new()));
|
||||
connect(open, SIGNAL(triggered()), this, SLOT(slot_open()));
|
||||
connect(open_file, SIGNAL(triggered()), this, SLOT(slot_openFile()));
|
||||
connect(save, SIGNAL(triggered()), this, SLOT(slot_save()));
|
||||
connect(save_as, SIGNAL(triggered()), this, SLOT(slot_saveAs()));
|
||||
connect(save_as_file, SIGNAL(triggered()), this, SLOT(slot_saveAsFile()));
|
||||
connect(reload, SIGNAL(triggered()), this, SLOT(slot_reload()));
|
||||
connect(quit, SIGNAL(triggered()), this, SLOT(close()));
|
||||
connect(selectall, SIGNAL(triggered()), ce_scene, SLOT(slot_selectAll()));
|
||||
connect(deselectall, SIGNAL(triggered()), ce_scene, SLOT(slot_deselectAll()));
|
||||
connect(inv_select, SIGNAL(triggered()), ce_scene, SLOT(slot_invertSelection()));
|
||||
connect(cut, SIGNAL(triggered()), ce_view, SLOT(cut()));
|
||||
connect(copy, SIGNAL(triggered()), ce_view, SLOT(copy()));
|
||||
connect(paste, SIGNAL(triggered()), ce_view, SLOT(paste()));
|
||||
connect(paste_in_area, SIGNAL(triggered()), ce_view, SLOT(pasteInArea()));
|
||||
connect(zoom_in, SIGNAL(triggered()), ce_view, SLOT(zoomIn()));
|
||||
connect(zoom_out, SIGNAL(triggered()), ce_view, SLOT(zoomOut()));
|
||||
connect(zoom_fit, SIGNAL(triggered()), ce_view, SLOT(zoomFit()));
|
||||
@@ -145,6 +178,7 @@ void QETElementEditor::setupActions() {
|
||||
connect(edit_backward, SIGNAL(triggered()), ce_scene, SLOT(slot_sendBackward()));
|
||||
connect(move, SIGNAL(triggered()), ce_scene, SLOT(slot_move()));
|
||||
connect(add_line, SIGNAL(triggered()), ce_scene, SLOT(slot_addLine()));
|
||||
connect(add_rectangle, SIGNAL(triggered()), ce_scene, SLOT(slot_addRectangle()));
|
||||
connect(add_ellipse, SIGNAL(triggered()), ce_scene, SLOT(slot_addEllipse()));
|
||||
connect(add_circle, SIGNAL(triggered()), ce_scene, SLOT(slot_addCircle()));
|
||||
connect(add_polygon, SIGNAL(triggered()), ce_scene, SLOT(slot_addPolygon()));
|
||||
@@ -155,6 +189,7 @@ void QETElementEditor::setupActions() {
|
||||
|
||||
connect(move, SIGNAL(triggered()), this, SLOT(slot_setRubberBandToView()));
|
||||
connect(add_line, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_rectangle, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_ellipse, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_circle, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_polygon, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
@@ -167,6 +202,7 @@ void QETElementEditor::setupActions() {
|
||||
|
||||
move -> setCheckable(true);
|
||||
add_line -> setCheckable(true);
|
||||
add_rectangle -> setCheckable(true);
|
||||
add_ellipse -> setCheckable(true);
|
||||
add_circle -> setCheckable(true);
|
||||
add_polygon -> setCheckable(true);
|
||||
@@ -178,16 +214,17 @@ void QETElementEditor::setupActions() {
|
||||
parts = new QActionGroup(this);
|
||||
parts -> addAction(move);
|
||||
parts -> addAction(add_line);
|
||||
parts -> addAction(add_rectangle);
|
||||
parts -> addAction(add_ellipse);
|
||||
parts -> addAction(add_circle);
|
||||
parts -> addAction(add_polygon);
|
||||
parts -> addAction(add_text);
|
||||
parts -> addAction(add_arc);
|
||||
parts -> addAction(add_text);
|
||||
parts -> addAction(add_textfield);
|
||||
parts -> addAction(add_terminal);
|
||||
parts -> setExclusive(true);
|
||||
|
||||
parts_toolbar = new QToolBar(tr("Parties"), this);
|
||||
parts_toolbar = new QToolBar(tr("Parties", "toolbar title"), this);
|
||||
parts_toolbar -> setObjectName("parts");
|
||||
foreach (QAction *action, parts -> actions()) parts_toolbar -> addAction(action);
|
||||
move -> setChecked(true);
|
||||
@@ -199,13 +236,13 @@ void QETElementEditor::setupActions() {
|
||||
parts_toolbar -> addAction(xml_preview);
|
||||
*/
|
||||
|
||||
main_toolbar = new QToolBar(tr("Outils"), this);
|
||||
main_toolbar = new QToolBar(tr("Outils", "toolbar title"), this);
|
||||
main_toolbar -> setObjectName("main_toolbar");
|
||||
view_toolbar = new QToolBar(tr("Affichage"), this);
|
||||
view_toolbar = new QToolBar(tr("Affichage", "toolbar title"), this);
|
||||
view_toolbar -> setObjectName("display");
|
||||
element_toolbar = new QToolBar(tr("\311l\351ment"), this);
|
||||
element_toolbar = new QToolBar(tr("\311l\351ment", "toolbar title"), this);
|
||||
element_toolbar -> setObjectName("element_toolbar");
|
||||
depth_toolbar = new QToolBar(tr("Profondeur"), this);
|
||||
depth_toolbar = new QToolBar(tr("Profondeur", "toolbar title"), this);
|
||||
depth_toolbar -> setObjectName("depth_toolbar");
|
||||
|
||||
main_toolbar -> addAction(new_element);
|
||||
@@ -238,6 +275,7 @@ void QETElementEditor::setupActions() {
|
||||
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()));
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateMenus()));
|
||||
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slot_updateMenus()));
|
||||
connect(&(ce_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateMenus()));
|
||||
connect(&(ce_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateTitle()));
|
||||
connect(&(ce_scene -> undoStack()), SIGNAL(indexChanged(int)), this, SLOT(slot_updatePartsList()));
|
||||
@@ -261,10 +299,12 @@ void QETElementEditor::setupMenus() {
|
||||
|
||||
file_menu -> addAction(new_element);
|
||||
file_menu -> addAction(open);
|
||||
file_menu -> addAction(open_file);
|
||||
file_menu -> addMenu(QETApp::elementsRecentFiles() -> menu());
|
||||
connect(QETApp::elementsRecentFiles(), SIGNAL(fileOpeningRequested(const QString &)), this, SLOT(openRecentFile(const QString &)));
|
||||
file_menu -> addAction(save);
|
||||
file_menu -> addAction(save_as);
|
||||
file_menu -> addAction(save_as_file);
|
||||
file_menu -> addSeparator();
|
||||
file_menu -> addAction(reload);
|
||||
file_menu -> addSeparator();
|
||||
@@ -277,6 +317,11 @@ void QETElementEditor::setupMenus() {
|
||||
edit_menu -> addAction(deselectall);
|
||||
edit_menu -> addAction(inv_select);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(cut);
|
||||
edit_menu -> addAction(copy);
|
||||
edit_menu -> addAction(paste);
|
||||
edit_menu -> addAction(paste_in_area);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(edit_delete);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(edit_names);
|
||||
@@ -309,6 +354,13 @@ void QETElementEditor::setupMenus() {
|
||||
*/
|
||||
void QETElementEditor::slot_updateMenus() {
|
||||
bool selected_items = !ce_scene -> selectedItems().isEmpty();
|
||||
bool clipboard_elmt = ElementScene::clipboardMayContainElement();
|
||||
|
||||
deselectall -> setEnabled(selected_items);
|
||||
cut -> setEnabled(selected_items);
|
||||
copy -> setEnabled(selected_items);
|
||||
paste -> setEnabled(clipboard_elmt);
|
||||
paste_in_area -> setEnabled(clipboard_elmt);
|
||||
edit_delete -> setEnabled(selected_items);
|
||||
edit_forward -> setEnabled(selected_items);
|
||||
edit_raise -> setEnabled(selected_items);
|
||||
@@ -323,10 +375,10 @@ void QETElementEditor::slot_updateMenus() {
|
||||
void QETElementEditor::slot_updateTitle() {
|
||||
QString title = min_title;
|
||||
title += " - " + ce_scene -> names().name() + " ";
|
||||
if (_filename != QString()) {
|
||||
if (!ce_scene -> undoStack().isClean()) title += tr("[Modifi\351]");
|
||||
if (isReadOnly()) title += tr(" [lecture seule]");
|
||||
if (!filename_.isEmpty() || !location_.isNull()) {
|
||||
if (!ce_scene -> undoStack().isClean()) title += tr("[Modifi\351]", "window title tag");
|
||||
}
|
||||
if (isReadOnly()) title += tr(" [lecture seule]", "window title tag");
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
@@ -344,19 +396,25 @@ void QETElementEditor::setupInterface() {
|
||||
// widget par defaut dans le QDockWidget
|
||||
default_informations = new QLabel();
|
||||
|
||||
// ScrollArea pour accueillir un widget d'edition (change a la volee)
|
||||
tools_dock_scroll_area_ = new QScrollArea();
|
||||
|
||||
// Pile de widgets pour accueillir les deux widgets precedents
|
||||
tools_dock_stack_ = new QStackedWidget();
|
||||
tools_dock_stack_ -> insertWidget(0, default_informations);
|
||||
tools_dock_stack_ -> insertWidget(1, tools_dock_scroll_area_);
|
||||
|
||||
// panel sur le cote pour editer les parties
|
||||
tools_dock = new QDockWidget(tr("Informations"), this);
|
||||
tools_dock = new QDockWidget(tr("Informations", "dock title"), this);
|
||||
tools_dock -> setObjectName("informations");
|
||||
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
tools_dock -> setMinimumWidth(290);
|
||||
tools_dock -> setMinimumWidth(380);
|
||||
addDockWidget(Qt::RightDockWidgetArea, tools_dock);
|
||||
QWidget *info_widget = new QWidget();
|
||||
info_widget -> setLayout(new QVBoxLayout(info_widget));
|
||||
tools_dock -> setWidget(info_widget);
|
||||
tools_dock -> setWidget(tools_dock_stack_);
|
||||
|
||||
// panel sur le cote pour les annulations
|
||||
undo_dock = new QDockWidget(tr("Annulations"), this);
|
||||
undo_dock = new QDockWidget(tr("Annulations", "dock title"), this);
|
||||
undo_dock -> setObjectName("undo");
|
||||
undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
@@ -374,7 +432,7 @@ void QETElementEditor::setupInterface() {
|
||||
connect(ce_scene, SIGNAL(partsZValueChanged()), this, SLOT(slot_createPartsList()));
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updatePartsList()));
|
||||
connect(parts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slot_updateSelectionFromPartsList()));
|
||||
parts_dock = new QDockWidget(tr("Parties"), this);
|
||||
parts_dock = new QDockWidget(tr("Parties", "dock title"), this);
|
||||
parts_dock -> setObjectName("parts_list");
|
||||
parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
parts_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
@@ -386,7 +444,7 @@ void QETElementEditor::setupInterface() {
|
||||
slot_createPartsList();
|
||||
|
||||
// barre d'etat
|
||||
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments"));
|
||||
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments", "status bar message"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,31 +486,26 @@ void QETElementEditor::slot_updateInformations() {
|
||||
}
|
||||
}
|
||||
|
||||
// recupere le layout
|
||||
QLayout *layout = tools_dock -> widget() -> layout();
|
||||
|
||||
// enleve les widgets deja presents
|
||||
QLayoutItem *qli;
|
||||
while ((qli = layout -> takeAt(0)) != 0) {
|
||||
if (QWidget *w = qli -> widget()) {
|
||||
layout -> removeWidget(w);
|
||||
w -> setParent(0);
|
||||
w -> hide();
|
||||
}
|
||||
if (QWidget *previous_widget = tools_dock_scroll_area_ -> takeWidget()) {
|
||||
previous_widget -> setParent(0);
|
||||
previous_widget -> hide();
|
||||
}
|
||||
|
||||
if (selected_parts.size() == 1) {
|
||||
// recupere le premier CustomElementPart et en ajoute le widget d'edition
|
||||
QWidget *edit_widget = selected_parts.first() -> elementInformations();
|
||||
layout -> addWidget(edit_widget);
|
||||
edit_widget -> show();
|
||||
tools_dock_scroll_area_ -> setWidget(edit_widget);
|
||||
tools_dock_stack_ -> setCurrentIndex(1);
|
||||
} else {
|
||||
default_informations -> setText(
|
||||
selected_parts.size() ?
|
||||
QString("%1").arg(selected_parts.size()) + tr(" parties s\351lectionn\351es.") :
|
||||
tr("Aucune partie s\351lectionn\351e.")
|
||||
tr(
|
||||
"%n partie(s) s\351lectionn\351e(s).",
|
||||
"",
|
||||
selected_parts.size()
|
||||
)
|
||||
);
|
||||
layout -> addWidget(default_informations);
|
||||
default_informations -> show();
|
||||
default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop);
|
||||
tools_dock_stack_ -> setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,6 +521,33 @@ void QETElementEditor::xmlPreview() {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Verifie si l'ensemble des parties graphiques consituant l'element en cours
|
||||
d'edition est bien contenu dans le rectangle representant les limites de
|
||||
l'element. Si ce n'est pas le cas, l'utilisateur en est informe.
|
||||
@return true si la situation est ok, false sinon
|
||||
*/
|
||||
bool QETElementEditor::checkElementSize() {
|
||||
if (ce_scene -> borderContainsEveryParts()) {
|
||||
return(true);
|
||||
} else {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Dimensions de l'\351l\351ment", "messagebox title"),
|
||||
tr(
|
||||
"Attention : certaines parties graphiques (textes, cercles, "
|
||||
"lignes...) semblent d\351border du cadre de l'\351l\351ment. Cela"
|
||||
" risque de g\351n\351rer des bugs graphiques lors de leur "
|
||||
"manipulation sur un sch\351ma. Vous pouvez corriger cela soit "
|
||||
"en d\351pla\347ant ces parties, soit en vous rendant dans "
|
||||
"\311dition > \311diter la taille et le point de saisie."
|
||||
, "messagebox content"
|
||||
)
|
||||
);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Charge un fichier
|
||||
@param filepath Chemin du fichier a charger
|
||||
@@ -480,7 +560,7 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
QFileInfo infos_file(filepath);
|
||||
if (!infos_file.exists() || !infos_file.isFile()) {
|
||||
state = false;
|
||||
error_message = tr("Le fichier ") + filepath + tr(" n'existe pas.");
|
||||
error_message = QString(tr("Le fichier %1 n'existe pas.", "message box content")).arg(filepath);
|
||||
}
|
||||
|
||||
// le fichier doit etre lisible
|
||||
@@ -488,7 +568,7 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
if (state) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
state = false;
|
||||
error_message = tr("Impossible d'ouvrir le fichier ") + filepath + ".";
|
||||
error_message = QString(tr("Impossible d'ouvrir le fichier %1.", "message box content")).arg(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,13 +577,13 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
if (state) {
|
||||
if (!document_xml.setContent(&file)) {
|
||||
state = false;
|
||||
error_message = tr("Ce fichier n'est pas un document XML valide");
|
||||
error_message = tr("Ce fichier n'est pas un document XML valide", "message box content");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
QMessageBox::critical(this, tr("Erreur"), error_message);
|
||||
QMessageBox::critical(this, tr("Erreur", "toolbar title"), error_message);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -515,8 +595,8 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
if (!infos_file.isWritable()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("\311dition en lecture seule"),
|
||||
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cet \351lement. Il sera donc ouvert en lecture seule.")
|
||||
tr("\311dition en lecture seule", "message box title"),
|
||||
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cet \351lement. Il sera donc ouvert en lecture seule.", "message box content")
|
||||
);
|
||||
setReadOnly(true);
|
||||
}
|
||||
@@ -527,7 +607,6 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
slot_updateMenus();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enregistre l'element vers un fichier
|
||||
@param fn Chemin du fichier a enregistrer
|
||||
@@ -536,7 +615,7 @@ void QETElementEditor::fromFile(const QString &filepath) {
|
||||
bool QETElementEditor::toFile(const QString &fn) {
|
||||
QFile file(fn);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QMessageBox::warning(this, tr("Erreur"), tr("Impossible d'ecrire dans ce fichier"));
|
||||
QMessageBox::warning(this, tr("Erreur", "message box title"), tr("Impossible d'\351crire dans ce fichier", "message box content"));
|
||||
return(false);
|
||||
}
|
||||
QTextStream out(&file);
|
||||
@@ -546,6 +625,45 @@ bool QETElementEditor::toFile(const QString &fn) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Enregistre l'element vers un emplacement
|
||||
@param location Emplacement de l'element a enregistrer
|
||||
@return true en cas de reussite, false sinon
|
||||
*/
|
||||
bool QETElementEditor::toLocation(const ElementsLocation &location) {
|
||||
ElementsCollectionItem *item = QETApp::collectionItem(location);
|
||||
ElementDefinition *element;
|
||||
if (item) {
|
||||
// l'element existe deja
|
||||
element = qobject_cast<ElementDefinition *>(item);
|
||||
} else {
|
||||
// l'element n'existe pas encore, on demande sa creation
|
||||
element = QETApp::createElement(location);
|
||||
}
|
||||
|
||||
if (!element) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Erreur", "message box title"),
|
||||
tr("Impossible d'atteindre l'\351l\351ment", "message box content")
|
||||
);
|
||||
return(false);
|
||||
}
|
||||
|
||||
// enregistre l'element
|
||||
element -> setXml(ce_scene -> toXml().documentElement());
|
||||
if (!element -> write()) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("Erreur", "message box title"),
|
||||
tr("Impossible d'enregistrer l'\351l\351ment", "message box content")
|
||||
);
|
||||
return(false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
specifie si l'editeur d'element doit etre en mode lecture seule
|
||||
@param ro true pour activer le mode lecture seule, false pour le desactiver
|
||||
@@ -559,6 +677,9 @@ void QETElementEditor::setReadOnly(bool ro) {
|
||||
ce_view -> setInteractive(!ro);
|
||||
|
||||
// active / desactive l'edition de la taille, du hotspot, des noms et des orientations
|
||||
cut -> setEnabled(!ro);
|
||||
copy -> setEnabled(!ro);
|
||||
paste -> setEnabled(!ro);
|
||||
selectall -> setEnabled(!ro);
|
||||
deselectall -> setEnabled(!ro);
|
||||
inv_select -> setEnabled(!ro);
|
||||
@@ -587,15 +708,33 @@ void QETElementEditor::slot_new() {
|
||||
}
|
||||
|
||||
/**
|
||||
Demande un fichier a l'utilisateur et ouvre ce fichier
|
||||
Ouvre un element
|
||||
*/
|
||||
void QETElementEditor::slot_open() {
|
||||
// demande le chemin virtuel de l'element a ouvrir a l'utilisateur
|
||||
ElementsLocation location = ElementDialog::getOpenElementLocation();
|
||||
if (location.isNull()) return;
|
||||
QETElementEditor *cee = new QETElementEditor();
|
||||
cee -> fromLocation(location);
|
||||
cee -> show();
|
||||
}
|
||||
|
||||
/**
|
||||
Ouvre un fichier
|
||||
Demande un fichier a l'utilisateur et ouvre ce fichier
|
||||
*/
|
||||
void QETElementEditor::slot_openFile() {
|
||||
// demande un nom de fichier a ouvrir a l'utilisateur
|
||||
QString user_filename = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
tr("Ouvrir un fichier"),
|
||||
_filename.isEmpty() ? QETApp::customElementsDir() : QDir(_filename).absolutePath(),
|
||||
tr("\311l\351ments QElectroTech (*.elmt);;Fichiers XML (*.xml);;Tous les fichiers (*)")
|
||||
tr("Ouvrir un fichier", "dialog title"),
|
||||
filename_.isEmpty() ? QETApp::customElementsDir() : QDir(filename_).absolutePath(),
|
||||
tr(
|
||||
"\311l\351ments QElectroTech (*.elmt);;"
|
||||
"Fichiers XML (*.xml);;"
|
||||
"Tous les fichiers (*)",
|
||||
"filetypes allowed when opening an element file"
|
||||
)
|
||||
);
|
||||
openElement(user_filename);
|
||||
}
|
||||
@@ -628,16 +767,13 @@ void QETElementEditor::openElement(const QString &filepath) {
|
||||
Recharge l'element edite
|
||||
*/
|
||||
void QETElementEditor::slot_reload() {
|
||||
// impossible de recharger un element non enregistre
|
||||
if (_filename.isEmpty()) return;
|
||||
|
||||
// s'il ya des modifications, on demande a l'utilisateur s'il est certain
|
||||
// de vouloir recharger
|
||||
if (!ce_scene -> undoStack().isClean()) {
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
this,
|
||||
tr("Recharger l'\351l\351ment"),
|
||||
tr("Vous avez efffectu\351 des modifications sur cet \351l\351ment. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'\351l\351ment ?"),
|
||||
tr("Recharger l'\351l\351ment", "dialog title"),
|
||||
tr("Vous avez efffectu\351 des modifications sur cet \351l\351ment. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'\351l\351ment ?", "dialog content"),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
@@ -645,8 +781,19 @@ void QETElementEditor::slot_reload() {
|
||||
}
|
||||
|
||||
// recharge l'element
|
||||
ce_scene -> reset();
|
||||
fromFile(_filename);
|
||||
if (opened_from_file) {
|
||||
// l'element a ete ouvert a partir d'un chemin de fichier
|
||||
ce_scene -> reset();
|
||||
fromFile(filename_);
|
||||
} else {
|
||||
// l'element a ete ouvert a partir d'un emplacement (ElementsLocation)
|
||||
// il peut s'agir aussi bien d'un fichier que d'un element XML
|
||||
if (ElementsCollectionItem *item = QETApp::collectionItem(location_)) {
|
||||
item -> reload();
|
||||
ce_scene -> reset();
|
||||
fromLocation(location_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,24 +803,57 @@ void QETElementEditor::slot_reload() {
|
||||
@see slot_saveAs()
|
||||
*/
|
||||
bool QETElementEditor::slot_save() {
|
||||
// verification avant d'enregistrer le fichier
|
||||
checkElementSize();
|
||||
|
||||
// si on ne connait pas le nom du fichier en cours, enregistrer revient a enregistrer sous
|
||||
if (_filename.isEmpty()) return(slot_saveAs());
|
||||
// sinon on enregistre dans le nom de fichier connu
|
||||
bool result_save = toFile(_filename);
|
||||
if (result_save) ce_scene -> undoStack().setClean();
|
||||
if (opened_from_file) {
|
||||
if (filename_.isEmpty()) return(slot_saveAsFile());
|
||||
// sinon on enregistre dans le nom de fichier connu
|
||||
bool result_save = toFile(filename_);
|
||||
if (result_save) ce_scene -> undoStack().setClean();
|
||||
return(result_save);
|
||||
} else {
|
||||
if (location_.isNull()) return(slot_saveAs());
|
||||
// sinon on enregistre a l'emplacement connu
|
||||
bool result_save = toLocation(location_);
|
||||
if (result_save) ce_scene -> undoStack().setClean();
|
||||
return(result_save);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Demande une localisation a l'utilisateur et enregistre l'element
|
||||
*/
|
||||
bool QETElementEditor::slot_saveAs() {
|
||||
// demande une localisation a l'utilisateur
|
||||
ElementsLocation location = ElementDialog::getSaveElementLocation();
|
||||
if (location.isNull()) return(false);
|
||||
|
||||
// tente l'enregistrement
|
||||
bool result_save = toLocation(location);
|
||||
if (result_save) {
|
||||
setLocation(location);
|
||||
ce_scene -> undoStack().setClean();
|
||||
}
|
||||
|
||||
// retourne un booleen representatif de la reussite de l'enregistrement
|
||||
return(result_save);
|
||||
}
|
||||
|
||||
/**
|
||||
Demande un nom de fichier a l'utilisateur et enregistre l'element
|
||||
*/
|
||||
bool QETElementEditor::slot_saveAs() {
|
||||
bool QETElementEditor::slot_saveAsFile() {
|
||||
// demande un nom de fichier a l'utilisateur pour enregistrer l'element
|
||||
QString fn = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Enregistrer sous"),
|
||||
_filename.isEmpty() ? QETApp::customElementsDir() : QDir(_filename).absolutePath(),
|
||||
tr("\311l\351ments QElectroTech (*.elmt)")
|
||||
tr("Enregistrer sous", "dialog title"),
|
||||
filename_.isEmpty() ? QETApp::customElementsDir() : QDir(filename_).absolutePath(),
|
||||
tr(
|
||||
"\311l\351ments QElectroTech (*.elmt)",
|
||||
"filetypes allowed when saving an element file"
|
||||
)
|
||||
);
|
||||
// si aucun nom n'est entre, renvoie faux.
|
||||
if (fn.isEmpty()) return(false);
|
||||
@@ -702,9 +882,14 @@ bool QETElementEditor::canClose() {
|
||||
// demande d'abord a l'utilisateur s'il veut enregistrer l'element en cours
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
this,
|
||||
tr("Enregistrer l'\351l\351ment en cours ?"),
|
||||
tr("Voulez-vous enregistrer l'\351l\351ment ") + ce_scene -> names().name() + tr(" ?"),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
|
||||
tr("Enregistrer l'\351l\351ment en cours ?", "dialog title"),
|
||||
QString(
|
||||
tr(
|
||||
"Voulez-vous enregistrer l'\351l\351ment %1 ?",
|
||||
"dialog content - %1 is an element name"
|
||||
)
|
||||
).arg(ce_scene -> names().name()),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
bool result;
|
||||
@@ -787,6 +972,7 @@ void QETElementEditor::slot_updateSelectionFromPartsList() {
|
||||
parts_list -> blockSignals(false);
|
||||
ce_scene -> blockSignals(false);
|
||||
slot_updateInformations();
|
||||
slot_updateMenus();
|
||||
}
|
||||
|
||||
/// Lit les parametres de l'editeur d'element
|
||||
@@ -808,3 +994,70 @@ void QETElementEditor::writeSettings() {
|
||||
settings.setValue("elementeditor/geometry", saveGeometry());
|
||||
settings.setValue("elementeditor/state", saveState());
|
||||
}
|
||||
|
||||
/**
|
||||
@return les decalages horizontaux et verticaux (sous la forme d'un point) a
|
||||
utiliser lors d'un copier/coller avec decalage.
|
||||
*/
|
||||
QPointF QETElementEditor::pasteOffset() {
|
||||
QPointF paste_offset(5.0, 0.0);
|
||||
return(paste_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le type de mouvement a effectuer lors d'un copier/coller avec
|
||||
decalage.
|
||||
*/
|
||||
QET::OrientedMovement QETElementEditor::pasteMovement() {
|
||||
return(QET::ToEast);
|
||||
}
|
||||
|
||||
/**
|
||||
@param location Emplacement de l'element a editer
|
||||
*/
|
||||
void QETElementEditor::fromLocation(const ElementsLocation &location) {
|
||||
|
||||
// l'element doit exister
|
||||
ElementsCollectionItem *item = QETApp::collectionItem(location);
|
||||
ElementDefinition *element = 0;
|
||||
if (!item) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("\311l\351ment inexistant.", "message box title"),
|
||||
tr("L'\351l\351ment n'existe pas.", "message box content")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item -> isElement() || !(element = qobject_cast<ElementDefinition *>(item)) || element -> isNull()) {
|
||||
QMessageBox::critical(
|
||||
this,
|
||||
tr("\311l\351ment inexistant.", "message box title"),
|
||||
tr("Le chemin virtuel choisi ne correspond pas \340 un \351l\351ment.", "message box content")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre un document XML
|
||||
QDomDocument document_xml;
|
||||
QDomNode node = document_xml.importNode(element -> xml(), true);
|
||||
document_xml.appendChild(node);
|
||||
|
||||
// chargement de l'element
|
||||
ce_scene -> fromXml(document_xml);
|
||||
slot_createPartsList();
|
||||
|
||||
// gestion de la lecture seule
|
||||
if (!element -> isWritable()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("\311dition en lecture seule", "message box title"),
|
||||
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cet \351lement. Il sera donc ouvert en lecture seule.", "message box content")
|
||||
);
|
||||
setReadOnly(true);
|
||||
}
|
||||
|
||||
// memorise le fichier
|
||||
setLocation(location);
|
||||
slot_updateMenus();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,8 +18,10 @@
|
||||
#ifndef CUSTOM_ELEMENT_EDITOR_H
|
||||
#define CUSTOM_ELEMENT_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "qet.h"
|
||||
#include "elementscene.h"
|
||||
#include "orientationset.h"
|
||||
#include "elementslocation.h"
|
||||
class ElementView;
|
||||
/**
|
||||
Cette classe represente un editeur d'element. Elle permet a l'utilisateur
|
||||
@@ -48,6 +50,12 @@ class QETElementEditor : public QMainWindow {
|
||||
ElementScene *ce_scene;
|
||||
/// container pour les widgets d'edition des parties
|
||||
QDockWidget *tools_dock;
|
||||
/// Pile de widgets pour tools_dock
|
||||
QStackedWidget *tools_dock_stack_;
|
||||
/// label affiche lors de la selection de plusieurs elements
|
||||
QLabel *default_informations;
|
||||
/// ScrollArea pour le DockWidget affichant des infos sur la partie selectionnee
|
||||
QScrollArea *tools_dock_scroll_area_;
|
||||
/// container pour la liste des annulations
|
||||
QDockWidget *undo_dock;
|
||||
/// Container pour la liste des parties
|
||||
@@ -55,9 +63,10 @@ class QETElementEditor : public QMainWindow {
|
||||
/// Liste des parties
|
||||
QListWidget *parts_list;
|
||||
/// actions du menu fichier
|
||||
QAction *new_element, *open, *save, *save_as, *reload, *quit;
|
||||
QAction *new_element, *open, *open_file, *save, *save_as, *save_as_file, *reload, *quit;
|
||||
/// actions du menu edition
|
||||
QAction *selectall, *deselectall, *inv_select;
|
||||
QAction *cut, *copy, *paste, *paste_in_area;
|
||||
QAction *undo, *redo;
|
||||
QAction *zoom_in, *zoom_out, *zoom_fit, *zoom_reset;
|
||||
QAction *edit_delete, *edit_size_hs, *edit_names, *edit_ori;
|
||||
@@ -66,14 +75,16 @@ class QETElementEditor : public QMainWindow {
|
||||
QToolBar *parts_toolbar, *main_toolbar, *view_toolbar, *depth_toolbar, *element_toolbar;
|
||||
/// actions de la barre d'outils
|
||||
QActionGroup *parts;
|
||||
QAction *move, *add_line, *add_circle, *add_ellipse, *add_polygon, *add_text;
|
||||
QAction *move, *add_line, *add_circle, *add_rectangle, *add_ellipse, *add_polygon, *add_text;
|
||||
QAction *add_arc, *add_terminal, *add_textfield;
|
||||
/// label affiche lors de la selection de plusieurs elements
|
||||
QLabel *default_informations;
|
||||
/// titre minimal
|
||||
QString min_title;
|
||||
/// Nom de fichier
|
||||
QString _filename;
|
||||
/// Nom de fichier de l'element edite
|
||||
QString filename_;
|
||||
/// Emplacement de l'element edite
|
||||
ElementsLocation location_;
|
||||
/// booleen indiquant si l'element en cours d'edition provient d'un fichier ou d'un emplacement
|
||||
bool opened_from_file;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
@@ -84,15 +95,21 @@ class QETElementEditor : public QMainWindow {
|
||||
void setNames(const NamesList &);
|
||||
void setOrientations(const OrientationSet &orientation_set);
|
||||
OrientationSet orientations() const;
|
||||
void setLocation(const ElementsLocation &);
|
||||
ElementsLocation location() const;
|
||||
void setFileName(const QString &);
|
||||
QString fileName() const;
|
||||
void setReadOnly(bool);
|
||||
bool isReadOnly() const;
|
||||
void fromFile(const QString &);
|
||||
void fromLocation(const ElementsLocation &);
|
||||
bool toFile(const QString &);
|
||||
bool toLocation(const ElementsLocation &);
|
||||
ElementScene *elementScene() const;
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
static QPointF pasteOffset();
|
||||
static QET::OrientedMovement pasteMovement();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
@@ -106,11 +123,13 @@ class QETElementEditor : public QMainWindow {
|
||||
public slots:
|
||||
void slot_new();
|
||||
void slot_open();
|
||||
void slot_openFile();
|
||||
void openRecentFile(const QString &);
|
||||
void openElement(const QString &);
|
||||
void slot_reload();
|
||||
bool slot_save();
|
||||
bool slot_saveAs();
|
||||
bool slot_saveAsFile();
|
||||
void slot_setRubberBandToView();
|
||||
void slot_setNoDragToView();
|
||||
void slot_setNormalMode();
|
||||
@@ -121,6 +140,7 @@ class QETElementEditor : public QMainWindow {
|
||||
void slot_updatePartsList();
|
||||
void slot_updateSelectionFromPartsList();
|
||||
void xmlPreview();
|
||||
bool checkElementSize();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -179,18 +199,35 @@ inline OrientationSet QETElementEditor::orientations() const {
|
||||
}
|
||||
|
||||
/**
|
||||
@param fn Le nouveau nom de fichier de l'element edite
|
||||
@param el Le nouvel emplacement de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setFileName(const QString &fn) {
|
||||
_filename = fn;
|
||||
inline void QETElementEditor::setLocation(const ElementsLocation &el) {
|
||||
location_ = el;
|
||||
opened_from_file = false;
|
||||
slot_updateTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nomde fichier de l'element edite
|
||||
@return l'emplacement de l'element edite
|
||||
*/
|
||||
inline ElementsLocation QETElementEditor::location() const {
|
||||
return(location_);
|
||||
}
|
||||
|
||||
/**
|
||||
@param fn Le nouveau nom de fichier de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setFileName(const QString &fn) {
|
||||
filename_ = fn;
|
||||
opened_from_file = true;
|
||||
slot_updateTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom de fichier de l'element edite
|
||||
*/
|
||||
inline QString QETElementEditor::fileName() const {
|
||||
return(_filename);
|
||||
return(filename_);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
108
sources/editor/rectangleeditor.cpp
Normal file
108
sources/editor/rectangleeditor.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
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 "rectangleeditor.h"
|
||||
#include "partrectangle.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param rect Le rectangle a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
RectangleEditor::RectangleEditor(QETElementEditor *editor, PartRectangle *rect, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
|
||||
part = rect;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
w = new QLineEdit();
|
||||
h = new QLineEdit();
|
||||
|
||||
x -> setValidator(new QDoubleValidator(x));
|
||||
y -> setValidator(new QDoubleValidator(y));
|
||||
w -> setValidator(new QDoubleValidator(w));
|
||||
h -> setValidator(new QDoubleValidator(h));
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
grid -> addWidget(new QLabel(tr("Coin sup\351rieur gauche\240: ")), 0, 0);
|
||||
grid -> addWidget(new QLabel("x"), 1, 0);
|
||||
grid -> addWidget(x, 1, 1);
|
||||
grid -> addWidget(new QLabel("y"), 1, 2);
|
||||
grid -> addWidget(y, 1, 3);
|
||||
grid -> addWidget(new QLabel(tr("Dimensions\240: ")), 2, 0);
|
||||
grid -> addWidget(new QLabel(tr("Largeur\240:")), 3, 0);
|
||||
grid -> addWidget(w, 3, 1);
|
||||
grid -> addWidget(new QLabel(tr("Hauteur\240:")), 4, 0);
|
||||
grid -> addWidget(h, 4, 1);
|
||||
|
||||
activeConnections(true);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
RectangleEditor::~RectangleEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le rectangle a partir des donnees du formulaire
|
||||
*/
|
||||
void RectangleEditor::updateRectangle() {
|
||||
part -> setProperty("x", x -> text().toDouble());
|
||||
part -> setProperty("y", y -> text().toDouble());
|
||||
part -> setProperty("width", w -> text().toDouble());
|
||||
part -> setProperty("height", h -> text().toDouble());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du coin superieur gauche du rectangle et cree un objet d'annulation
|
||||
void RectangleEditor::updateRectangleX() { addChangePartCommand(tr("abscisse"), part, "x", x -> text().toDouble()); }
|
||||
/// Met a jour l'ordonnee du coin superieur gauche du rectangle et cree un objet d'annulation
|
||||
void RectangleEditor::updateRectangleY() { addChangePartCommand(tr("ordonn\351e"), part, "y", y -> text().toDouble()); }
|
||||
/// Met a jour la largeur du rectangle et cree un objet d'annulation
|
||||
void RectangleEditor::updateRectangleW() { addChangePartCommand(tr("largeur"), part, "width", w -> text().toDouble()); }
|
||||
/// Met a jour la hauteur du rectangle et cree un objet d'annulation
|
||||
void RectangleEditor::updateRectangleH() { addChangePartCommand(tr("hauteur"), part, "height", h -> text().toDouble()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void RectangleEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
x -> setText(part -> property("x").toString());
|
||||
y -> setText(part -> property("y").toString());
|
||||
w -> setText(part -> property("width").toString());
|
||||
h -> setText(part -> property("height").toString());
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive les connexionx signaux/slots entre les widgets internes.
|
||||
@param active true pour activer les connexions, false pour les desactiver
|
||||
*/
|
||||
void RectangleEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateRectangleX()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateRectangleY()));
|
||||
connect(w, SIGNAL(editingFinished()), this, SLOT(updateRectangleW()));
|
||||
connect(h, SIGNAL(editingFinished()), this, SLOT(updateRectangleH()));
|
||||
} else {
|
||||
disconnect(x, SIGNAL(editingFinished()), this, SLOT(updateRectangleX()));
|
||||
disconnect(y, SIGNAL(editingFinished()), this, SLOT(updateRectangleY()));
|
||||
disconnect(w, SIGNAL(editingFinished()), this, SLOT(updateRectangleW()));
|
||||
disconnect(h, SIGNAL(editingFinished()), this, SLOT(updateRectangleH()));
|
||||
}
|
||||
}
|
||||
53
sources/editor/rectangleeditor.h
Normal file
53
sources/editor/rectangleeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef RECTANGLE_EDITOR_H
|
||||
#define RECTANGLE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartRectangle;
|
||||
/**
|
||||
Cette classe represente le widget d'edition d'un rectangle dans l'editeur
|
||||
d'element.
|
||||
*/
|
||||
class RectangleEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
RectangleEditor(QETElementEditor *, PartRectangle *, QWidget * = 0);
|
||||
~RectangleEditor();
|
||||
private:
|
||||
RectangleEditor(const RectangleEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartRectangle *part;
|
||||
QLineEdit *x, *y, *w, *h;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateRectangle();
|
||||
void updateRectangleX();
|
||||
void updateRectangleY();
|
||||
void updateRectangleW();
|
||||
void updateRectangleH();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -27,26 +27,26 @@
|
||||
StyleEditor::StyleEditor(QETElementEditor *editor, CustomElementGraphicPart *p, QWidget *parent) : ElementItemEditor(editor, parent), part(p) {
|
||||
// couleur
|
||||
color = new QButtonGroup(this);
|
||||
color -> addButton(black_color = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackColor);
|
||||
color -> addButton(white_color = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteColor);
|
||||
color -> addButton(black_color = new QRadioButton(tr("Noir", "element part color")), CustomElementGraphicPart::BlackColor);
|
||||
color -> addButton(white_color = new QRadioButton(tr("Blanc", "element part color")), CustomElementGraphicPart::WhiteColor);
|
||||
|
||||
// style
|
||||
style = new QButtonGroup(this);
|
||||
style -> addButton(normal_style = new QRadioButton(tr("Normal")), CustomElementGraphicPart::NormalStyle);
|
||||
style -> addButton(dashed_style = new QRadioButton(tr("Pointill\351")), CustomElementGraphicPart::DashedStyle);
|
||||
style -> addButton(normal_style = new QRadioButton(tr("Normal", "element part line style")), CustomElementGraphicPart::NormalStyle);
|
||||
style -> addButton(dashed_style = new QRadioButton(tr("Pointill\351", "element part line style")), CustomElementGraphicPart::DashedStyle);
|
||||
style -> button(part -> lineStyle()) -> setChecked(true);
|
||||
|
||||
// epaisseur
|
||||
weight = new QButtonGroup(this);
|
||||
weight -> addButton(none_weight = new QRadioButton(tr("Nulle")), CustomElementGraphicPart::NoneWeight);
|
||||
weight -> addButton(thin_weight = new QRadioButton(tr("Fine")), CustomElementGraphicPart::ThinWeight);
|
||||
weight -> addButton(normal_weight = new QRadioButton(tr("Normale")), CustomElementGraphicPart::NormalWeight);
|
||||
weight -> addButton(none_weight = new QRadioButton(tr("Nulle", "element part weight")), CustomElementGraphicPart::NoneWeight);
|
||||
weight -> addButton(thin_weight = new QRadioButton(tr("Fine", "element part weight")), CustomElementGraphicPart::ThinWeight);
|
||||
weight -> addButton(normal_weight = new QRadioButton(tr("Normale", "element part weight")), CustomElementGraphicPart::NormalWeight);
|
||||
|
||||
// remplissage
|
||||
filling = new QButtonGroup(this);
|
||||
filling -> addButton(no_filling = new QRadioButton(tr("Aucun")), CustomElementGraphicPart::NoneFilling );
|
||||
filling -> addButton(black_filling = new QRadioButton(tr("Noir")), CustomElementGraphicPart::BlackFilling);
|
||||
filling -> addButton(white_filling = new QRadioButton(tr("Blanc")), CustomElementGraphicPart::WhiteFilling);
|
||||
filling -> addButton(no_filling = new QRadioButton(tr("Aucun", "element part filling")), CustomElementGraphicPart::NoneFilling );
|
||||
filling -> addButton(black_filling = new QRadioButton(tr("Noir", "element part filling")), CustomElementGraphicPart::BlackFilling);
|
||||
filling -> addButton(white_filling = new QRadioButton(tr("Blanc", "element part filling")), CustomElementGraphicPart::WhiteFilling);
|
||||
|
||||
// antialiasing
|
||||
antialiasing = new QCheckBox(tr("Antialiasing"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -81,7 +81,7 @@ void TextEditor::updateTextX() { addChangePartCommand(tr("abscisse"), part, "
|
||||
/// Met a jour l'ordonnee de la position du texte et cree un objet d'annulation
|
||||
void TextEditor::updateTextY() { addChangePartCommand(tr("ordonn\351e"), part, "y", qle_y -> text().toDouble()); updateForm(); }
|
||||
/// Met a jour le texte et cree un objet d'annulation
|
||||
void TextEditor::updateTextT() { addChangePartCommand(tr("texte"), part, "text", qle_text -> text()); }
|
||||
void TextEditor::updateTextT() { addChangePartCommand(tr("contenu"), part, "text", qle_text -> text()); }
|
||||
/// Met a jour la taille du texte et cree un objet d'annulation
|
||||
void TextEditor::updateTextS() { addChangePartCommand(tr("taille"), part, "size", font_size -> value()); }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -86,7 +86,7 @@ void TextFieldEditor::updateTextFieldX() { addChangePartCommand(tr("abscisse"),
|
||||
/// Met a jour l'ordonnee de la position du champ de texte et cree un objet d'annulation
|
||||
void TextFieldEditor::updateTextFieldY() { addChangePartCommand(tr("ordonn\351e"), part, "y", qle_y -> text().toDouble()); updateForm(); }
|
||||
/// Met a jour le texte du champ de texte et cree un objet d'annulation
|
||||
void TextFieldEditor::updateTextFieldT() { addChangePartCommand(tr("texte"), part, "text", qle_text -> text()); }
|
||||
void TextFieldEditor::updateTextFieldT() { addChangePartCommand(tr("contenu"), part, "text", qle_text -> text()); }
|
||||
/// Met a jour la taille du champ de texte et cree un objet d'annulation
|
||||
void TextFieldEditor::updateTextFieldS() { addChangePartCommand(tr("taille"), part, "size", font_size -> value()); }
|
||||
/// Met a jour la taille du champ de texte et cree un objet d'annulation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2007 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -138,8 +138,8 @@ void Element::deselect() {
|
||||
@return La pixmap de l'element
|
||||
*/
|
||||
QPixmap Element::pixmap() {
|
||||
if (apercu.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
|
||||
return(apercu);
|
||||
if (preview.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait
|
||||
return(preview);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,10 +220,10 @@ void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *)
|
||||
*/
|
||||
void Element::updatePixmap() {
|
||||
// Pixmap transparente faisant la taille de base de l'element
|
||||
apercu = QPixmap(dimensions);
|
||||
apercu.fill(QColor(255, 255, 255, 0));
|
||||
preview = QPixmap(dimensions);
|
||||
preview.fill(QColor(255, 255, 255, 0));
|
||||
// QPainter sur la pixmap, avec antialiasing
|
||||
QPainter p(&apercu);
|
||||
QPainter p(&preview);
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
// Translation de l'origine du repere de la pixmap
|
||||
@@ -416,9 +416,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table
|
||||
QDomElement element = document.createElement("element");
|
||||
|
||||
// type
|
||||
QString chemin_elmt = typeId();
|
||||
QString type_elmt = QETApp::symbolicPath(chemin_elmt);
|
||||
element.setAttribute("type", type_elmt);
|
||||
element.setAttribute("type", typeId());
|
||||
|
||||
// position, selection et orientation
|
||||
element.setAttribute("x", QString("%1").arg(pos().x()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -53,7 +53,7 @@ class Element : public QObject, public QGraphicsItem {
|
||||
private:
|
||||
QSize dimensions;
|
||||
QPoint hotspot_coord;
|
||||
QPixmap apercu;
|
||||
QPixmap preview;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
@@ -69,11 +69,11 @@ class Element : public QObject, public QGraphicsItem {
|
||||
/// @return la liste des conducteurs relies a cet element
|
||||
virtual QList<Conductor *> conductors() const = 0;
|
||||
/// @return le nombre de bornes actuel de cet element
|
||||
virtual int nbTerminals() const = 0;
|
||||
virtual int terminalsCount() const = 0;
|
||||
/// @return le nombre de bornes minimum de cet element
|
||||
virtual int nbTerminalsMin() const = 0;
|
||||
virtual int minTerminalsCount() const = 0;
|
||||
/// @return le nombre de bornes maximum de cet element
|
||||
virtual int nbTerminalsMax() const = 0;
|
||||
virtual int maxTerminalsCount() const = 0;
|
||||
/**
|
||||
Dessine l'element
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ class Element : public QObject, public QGraphicsItem {
|
||||
/// @return L'ID du type de l'element
|
||||
virtual QString typeId() const = 0;
|
||||
/// @return Le nom de l'element
|
||||
virtual QString nom() const = 0;
|
||||
virtual QString name() const = 0;
|
||||
Diagram *diagram() const;
|
||||
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
|
||||
461
sources/elementdefinition.cpp
Normal file
461
sources/elementdefinition.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
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 "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 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) {
|
||||
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);
|
||||
}
|
||||
126
sources/elementdefinition.h
Normal file
126
sources/elementdefinition.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
#ifndef ELEMENT_DEFINITION_H
|
||||
#define ELEMENT_DEFINITION_H
|
||||
#include <QtXml>
|
||||
#include "elementscategory.h"
|
||||
class ElementsCollection;
|
||||
class MoveElementsHandler;
|
||||
/**
|
||||
Cette classe abstraite represente une definition XML d'element,
|
||||
c'est-a-dire qu'elle definit l'interface a implementer pour acceder a la
|
||||
definition XML d'un element, que celle-ci proviennt d'un fichier *.elmt ou
|
||||
d'un fichier projet QET.
|
||||
*/
|
||||
class ElementDefinition : public ElementsCollectionItem {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
*/
|
||||
ElementDefinition(ElementsCategory *category = 0, ElementsCollection *collection = 0) : ElementsCollectionItem(category), parent_category_(category), parent_collection_(collection) {};
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
virtual ~ElementDefinition() {};
|
||||
|
||||
/**
|
||||
@return la definition XML de l'element
|
||||
*/
|
||||
virtual QDomElement xml() = 0;
|
||||
|
||||
/**
|
||||
Change la definition XML de l'element
|
||||
@param xml_element Nouvelle definition XML de l'element
|
||||
@return true si l'operation s'est bien passee, false sinon
|
||||
*/
|
||||
virtual bool setXml(const QDomElement &) = 0;
|
||||
|
||||
/**
|
||||
@return true si la definition n'est pas disponible
|
||||
*/
|
||||
virtual bool isNull() const = 0;
|
||||
|
||||
virtual ElementsCategory *parentCategory();
|
||||
virtual QList<ElementsCategory *> parentCategories();
|
||||
virtual bool hasParentCategory();
|
||||
|
||||
/**
|
||||
@return true si l'element est rattache a une collection d'elements
|
||||
Un element appartenant a une collection a forcement un chemin virtuel.
|
||||
*/
|
||||
virtual bool hasParentCollection();
|
||||
virtual bool isChildOf(ElementsCollectionItem *);
|
||||
|
||||
/**
|
||||
@return la collection d'element a laquelle appartient cet element
|
||||
*/
|
||||
virtual ElementsCollection *parentCollection();
|
||||
|
||||
virtual QETProject *project();
|
||||
virtual void setProject(QETProject *);
|
||||
/**
|
||||
@return le protocole utilise par la collection a laquelle appartient cet element
|
||||
*/
|
||||
virtual QString protocol();
|
||||
/**
|
||||
Ne fait rien.
|
||||
*/
|
||||
virtual void setProtocol(const QString &);
|
||||
|
||||
/**
|
||||
@return le chemin virtuel complet de cet element (protocole + chemin)
|
||||
*/
|
||||
virtual QString fullVirtualPath();
|
||||
|
||||
/**
|
||||
@return l'emplacement de cet element
|
||||
*/
|
||||
virtual ElementsLocation location();
|
||||
|
||||
virtual QList<ElementsCategory *> categories();
|
||||
virtual ElementsCategory *category(const QString &);
|
||||
virtual ElementsCategory *createCategory(const QString &);
|
||||
|
||||
virtual QList<ElementDefinition *> elements();
|
||||
virtual ElementDefinition *element(const QString &);
|
||||
virtual ElementDefinition *createElement(const QString &);
|
||||
virtual ElementsCollectionItem *copy(ElementsCategory *, MoveElementsHandler *, bool = true);
|
||||
virtual ElementsCollectionItem *move(ElementsCategory *, MoveElementsHandler *);
|
||||
|
||||
virtual bool isCollection() const { return(false); } ///< @return toujours false
|
||||
virtual bool isRootCategory() const { return(false); } ///< @return toujours false
|
||||
virtual bool isCategory() const { return(false); } ///< @return toujours false
|
||||
virtual bool isElement() const { return(true ); } ///< @return toujours true
|
||||
virtual ElementsCollection *toCollection();
|
||||
virtual ElementsCategory *toCategory();
|
||||
virtual ElementsCategory *toPureCategory();
|
||||
virtual ElementDefinition *toElement();
|
||||
virtual bool equals(ElementDefinition &);
|
||||
virtual bool removeContent();
|
||||
void copy(MoveElementsDescription *);
|
||||
void move(MoveElementsDescription *);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ElementsCategory *parent_category_;
|
||||
ElementsCollection *parent_collection_;
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -16,16 +16,25 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "elementdeleter.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param elmt_path Chemin du fichier representant l'element a supprimer
|
||||
@param elmt_path Chemin virtuel du fichier representant l'element a supprimer
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ElementDeleter::ElementDeleter(const QString &elmt_path, QWidget *parent) :
|
||||
ElementDeleter::ElementDeleter(const ElementsLocation &elmt_path, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
element_path(elmt_path)
|
||||
element(0)
|
||||
{
|
||||
// recupere l'element a supprimer
|
||||
ElementsCollectionItem *element_item = QETApp::collectionItem(elmt_path);
|
||||
if (!element_item) return;
|
||||
|
||||
// on exige un element
|
||||
if (!element_item -> isElement()) return;
|
||||
|
||||
element = element_item;
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
@@ -36,27 +45,31 @@ ElementDeleter::~ElementDeleter() {
|
||||
Supprime l'element : verifie l'existence du fichier, demande confirmation a
|
||||
l'utilisateur et avertit ce dernier si la suppression a echoue.
|
||||
*/
|
||||
void ElementDeleter::exec() {
|
||||
bool ElementDeleter::exec() {
|
||||
// verifie l'existence de l'element
|
||||
QFile elmt_file(element_path);
|
||||
if (!elmt_file.exists()) return;
|
||||
if (!element || !element -> isElement()) return(false);
|
||||
|
||||
// confirmation #1
|
||||
QMessageBox::StandardButton answer_1 = QMessageBox::question(
|
||||
this,
|
||||
tr("Supprimer l'\351l\351ment ?"),
|
||||
tr("\312tes-vous s\373r de vouloir supprimer cet \351l\351ment ?\n"),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel
|
||||
tr("Supprimer l'\351l\351ment ?", "message box title"),
|
||||
tr("\312tes-vous s\373r de vouloir supprimer cet \351l\351ment ?\n", "message box content"),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
|
||||
);
|
||||
if (answer_1 != QMessageBox::Yes) return;
|
||||
if (answer_1 != QMessageBox::Yes) return(false);
|
||||
|
||||
/**
|
||||
@todo Regression : rafficher le chemin de l'element
|
||||
*/
|
||||
|
||||
// supprime l'element
|
||||
if (!elmt_file.remove()) {
|
||||
if (!element -> remove()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Suppression de l'\351l\351ment"),
|
||||
tr("La suppression de l'\351l\351ment a \351chou\351.\n"
|
||||
"V\351rifiez vos droits sur le fichier ") + element_path + tr(".")
|
||||
tr("Suppression de l'\351l\351ment", "message box title"),
|
||||
tr("La suppression de l'\351l\351ment a \351chou\351.", "message box content")
|
||||
);
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2008 Xavier Guerrin
|
||||
Copyright 2006-2009 Xavier Guerrin
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,27 +18,28 @@
|
||||
#ifndef ELEMENT_DELETER_H
|
||||
#define ELEMENT_DELETER_H
|
||||
#include "elementscategory.h"
|
||||
#include "elementslocation.h"
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe represente une couche d'abstraction pour supprimer
|
||||
un element de la collection d'elements.
|
||||
Elle demande notamment confirmation a l'utilisateur
|
||||
Elle demande notamment confirmation a l'utilisateur.
|
||||
*/
|
||||
class ElementDeleter : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementDeleter(const QString &, QWidget * = 0);
|
||||
ElementDeleter(const ElementsLocation &, QWidget * = 0);
|
||||
virtual ~ElementDeleter();
|
||||
private:
|
||||
ElementDeleter(const ElementsCategory &);
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void exec();
|
||||
bool exec();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QString element_path;
|
||||
ElementsCollectionItem *element;
|
||||
};
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user