mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-02-13 20:59:58 +01:00
Nettoyage du trunk : deplacement des sources dans un sous-repertoire
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@364 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
139
sources/aboutqet.cpp
Normal file
139
sources/aboutqet.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 <QtGui>
|
||||
#include "aboutqet.h"
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent de la boite de dialogue
|
||||
*/
|
||||
AboutQET::AboutQET(QWidget *parent) : QDialog(parent) {
|
||||
// Titre, taille, comportement...
|
||||
setWindowTitle(tr("\300 propos de QElectrotech"));
|
||||
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"));
|
||||
|
||||
// Un bouton pour fermer la boite de dialogue
|
||||
QDialogButtonBox *boutons = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
connect(boutons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(boutons, SIGNAL(rejected()), this, SLOT(accept()));
|
||||
|
||||
// Le tout dans une disposition verticale
|
||||
QVBoxLayout *disposition = new QVBoxLayout();
|
||||
disposition -> addWidget(titre());
|
||||
disposition -> addWidget(onglets);
|
||||
disposition -> addWidget(boutons);
|
||||
setLayout(disposition);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
AboutQET::~AboutQET() {
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le titre QElectroTech avec son icone
|
||||
*/
|
||||
QWidget *AboutQET::titre() const {
|
||||
QWidget *icone_et_titre = new QWidget();
|
||||
// icone
|
||||
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>");
|
||||
titre -> setTextFormat(Qt::RichText);
|
||||
// le tout dans une grille
|
||||
QGridLayout *dispo_horiz = new QGridLayout();
|
||||
dispo_horiz -> addWidget(icone, 0, 0);
|
||||
dispo_horiz -> addWidget(titre, 0, 1);
|
||||
dispo_horiz -> setColumnStretch(0, 1);
|
||||
dispo_horiz -> setColumnStretch(1, 100);
|
||||
icone_et_titre -> setLayout(dispo_horiz);
|
||||
return(icone_et_titre);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « A propos »
|
||||
*/
|
||||
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") +
|
||||
"<br><br>"
|
||||
"<a href=\"http://qelectrotech.tuxfamily.org/\">"
|
||||
"http://qelectrotech.tuxfamily.org/</a>"
|
||||
);
|
||||
apropos -> setAlignment(Qt::AlignCenter);
|
||||
apropos -> setOpenExternalLinks(true);
|
||||
apropos -> setTextFormat(Qt::RichText);
|
||||
return(apropos);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « Auteurs »
|
||||
*/
|
||||
QWidget *AboutQET::ongletAuteurs() const {
|
||||
QLabel *auteurs = new QLabel(
|
||||
"<span style=\"text-decoration: underline;\">" +
|
||||
tr("Id\351e originale") +
|
||||
"</span> : Beno\356t Ansieau "
|
||||
"<<a href=\"mailto:benoit.ansieau@gmail.com\">"
|
||||
"benoit.ansieau@gmail.com</a>>"
|
||||
"<br><br>"
|
||||
"<span style=\"text-decoration: underline;\">" +
|
||||
tr("Programmation") +
|
||||
"</span> : Xavier Guerrin "
|
||||
"<<a href=\"mailto:xavier.guerrin@gmail.com\">"
|
||||
"xavier.guerrin@gmail.com</a>>"
|
||||
);
|
||||
auteurs -> setAlignment(Qt::AlignCenter);
|
||||
auteurs -> setOpenExternalLinks(true);
|
||||
auteurs -> setTextFormat(Qt::RichText);
|
||||
return(auteurs);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget contenu par l'onglet « Accord de Licence »
|
||||
*/
|
||||
QWidget *AboutQET::ongletLicence() const {
|
||||
QWidget *licence = new QWidget();
|
||||
// label
|
||||
QLabel *titre_licence = new QLabel(tr("Ce programme est sous licence GNU/GPL."));
|
||||
|
||||
// texte de la GNU/GPL dans une zone de texte scrollable non editable
|
||||
QTextEdit *texte_licence = new QTextEdit();
|
||||
texte_licence -> setPlainText(QET::license());
|
||||
texte_licence -> setReadOnly(true);
|
||||
|
||||
// le tout dans une disposition verticale
|
||||
QVBoxLayout *dispo_licence = new QVBoxLayout();
|
||||
dispo_licence -> addWidget(titre_licence);
|
||||
dispo_licence -> addWidget(texte_licence);
|
||||
licence -> setLayout(dispo_licence);
|
||||
return(licence);
|
||||
}
|
||||
43
sources/aboutqet.h
Normal file
43
sources/aboutqet.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ABOUTQET_H
|
||||
#define ABOUTQET_H
|
||||
#include <QDialog>
|
||||
/**
|
||||
Cette classe represente la boite de dialogue
|
||||
« A propos de QElectroTech »
|
||||
*/
|
||||
class AboutQET : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AboutQET(QWidget * = 0);
|
||||
virtual ~AboutQET();
|
||||
|
||||
private:
|
||||
AboutQET(AboutQET &);
|
||||
|
||||
// methodes
|
||||
private:
|
||||
QWidget *titre() const;
|
||||
QWidget *ongletAPropos() const;
|
||||
QWidget *ongletAuteurs() const;
|
||||
QWidget *ongletLicence() const;
|
||||
};
|
||||
#endif
|
||||
234
sources/borderinset.cpp
Normal file
234
sources/borderinset.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 <QPainter>
|
||||
#include "borderinset.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur simple : construit une bordure de 15 colonnes de 50x500 avec
|
||||
un cartouche de 400x50.
|
||||
@param parent QObject parent de ce BorderInset
|
||||
*/
|
||||
BorderInset::BorderInset(QObject *parent) : QObject(parent) {
|
||||
nb_columns = qMax(3, QETApp::settings().value("diagrameditor/defaultcols", 15).toInt());
|
||||
min_nb_columns = 3;
|
||||
columns_width = QETApp::settings().value("diagrameditor/defaultcolsize", 50.0).toDouble();
|
||||
columns_height = QETApp::settings().value("diagrameditor/defaultheight", 500.0).toDouble();
|
||||
min_columns_height = 80.0;
|
||||
inset_width = nb_columns * columns_width;
|
||||
inset_height = 50.0;
|
||||
columns_header_height = 20.0;
|
||||
display_inset = true;
|
||||
display_columns = true;
|
||||
display_border = true;
|
||||
updateRectangles();
|
||||
|
||||
bi_author = QETApp::settings().value("diagrameditor/defaultauthor").toString();
|
||||
bi_title = QETApp::settings().value("diagrameditor/defaulttitle").toString();
|
||||
bi_folio = QETApp::settings().value("diagrameditor/defaultfolio").toString();
|
||||
bi_filename = QETApp::settings().value("diagrameditor/defaultfilename").toString();
|
||||
QString settings_date = QETApp::settings().value("diagrameditor/defaultdate").toString();
|
||||
if (settings_date == "now") bi_date = QDate::currentDate();
|
||||
else if (settings_date.isEmpty() || settings_date == "null") bi_date = QDate();
|
||||
else bi_date = QDate::fromString(settings_date, "yyyyMMdd");
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur - ne fait rien
|
||||
*/
|
||||
BorderInset::~BorderInset() {
|
||||
}
|
||||
|
||||
/**
|
||||
Methode recalculant les rectangles composant le cadre et le cartouche en
|
||||
fonction des attributs de taille
|
||||
*/
|
||||
void BorderInset::updateRectangles() {
|
||||
// rectangle delimitant le schema
|
||||
QRectF previous_border = border;
|
||||
border = QRectF(0, 0, nb_columns * columns_width, columns_height);
|
||||
if (border != previous_border) emit(borderChanged(previous_border, border));
|
||||
|
||||
// rectangles relatifs au cartouche
|
||||
inset = QRectF(border.bottomLeft().x(), border.bottomLeft().y(), inset_width, inset_height);
|
||||
inset_author = QRectF(inset.topLeft(), QSizeF(2.0 * inset_width / 9.0, 0.5 * inset_height));
|
||||
inset_date = QRectF(inset_author.bottomLeft(), inset_author.size());
|
||||
inset_title = QRectF(inset_author.topRight(), QSizeF(5.0 * inset_width / 9.0, inset_height));
|
||||
inset_file = QRectF(inset_title.topRight(), inset_author.size());
|
||||
inset_folio = QRectF(inset_file.bottomLeft(), inset_author.size());
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le cadre et le cartouche
|
||||
@param qp QPainter a utiliser pour dessiner le cadre et le cartouche
|
||||
@param x Abscisse du cadre
|
||||
@param y Ordonnee du cadre
|
||||
*/
|
||||
void BorderInset::draw(QPainter *qp, qreal x, qreal y) {
|
||||
// translate tous les rectangles
|
||||
border .translate(x, y);
|
||||
inset .translate(x, y);
|
||||
inset_author.translate(x, y);
|
||||
inset_date .translate(x, y);
|
||||
inset_title .translate(x, y);
|
||||
inset_file .translate(x, y);
|
||||
inset_folio .translate(x, y);
|
||||
|
||||
// prepare le QPainter
|
||||
qp -> save();
|
||||
qp -> setPen(Qt::black);
|
||||
qp -> setBrush(Qt::NoBrush);
|
||||
|
||||
// dessine le cadre
|
||||
if (display_border) qp -> drawRect(border);
|
||||
|
||||
qp -> setFont(QFont(QETApp::diagramTextsFont(), qp -> font().pointSize()));
|
||||
|
||||
// dessine la numerotation des colonnes
|
||||
if (display_columns) {
|
||||
qp -> setBrush(Qt::white);
|
||||
for (int i = 1 ; i <= nb_columns ; ++ i) {
|
||||
QRectF numbered_rectangle = QRectF(
|
||||
border.topLeft().x() + ((i - 1) * columns_width),
|
||||
border.topLeft().y(),
|
||||
columns_width,
|
||||
columns_header_height
|
||||
);
|
||||
qp -> drawRect(numbered_rectangle);
|
||||
qp -> drawText(numbered_rectangle, Qt::AlignVCenter | Qt::AlignCenter, QString("%1").arg(i));
|
||||
}
|
||||
}
|
||||
|
||||
// dessine le cartouche
|
||||
if (display_inset) {
|
||||
qp -> setBrush(Qt::white);
|
||||
qp -> drawRect(inset);
|
||||
|
||||
qp -> drawRect(inset_author);
|
||||
qp -> drawText(inset_author, Qt::AlignVCenter | Qt::AlignLeft, tr(" Auteur : ") + bi_author);
|
||||
|
||||
qp -> drawRect(inset_date);
|
||||
qp -> drawText(inset_date, Qt::AlignVCenter | Qt::AlignLeft, tr(" Date : ") + 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 -> drawRect(inset_file);
|
||||
qp -> drawText(inset_file, Qt::AlignVCenter | Qt::AlignLeft, tr(" Fichier : ") + bi_filename);
|
||||
|
||||
qp -> drawRect(inset_folio);
|
||||
qp -> drawText(inset_folio, Qt::AlignVCenter | Qt::AlignLeft, tr(" Folio : ") + bi_folio);
|
||||
}
|
||||
|
||||
qp -> restore();
|
||||
|
||||
// annule la translation des rectangles
|
||||
border .translate(-x, -y);
|
||||
inset .translate(-x, -y);
|
||||
inset_author.translate(-x, -y);
|
||||
inset_date .translate(-x, -y);
|
||||
inset_title .translate(-x, -y);
|
||||
inset_file .translate(-x, -y);
|
||||
inset_folio .translate(-x, -y);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute une colonne.
|
||||
*/
|
||||
void BorderInset::addColumn() {
|
||||
++ nb_columns;
|
||||
setInsetWidth(nb_columns * columns_width);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Enleve une colonne. Il doit rester au moins 3 colonnes.
|
||||
*/
|
||||
void BorderInset::removeColumn() {
|
||||
if (nb_columns == min_nb_columns) return;
|
||||
-- nb_columns;
|
||||
setInsetWidth(nb_columns * columns_width);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de changer le nombre de colonnes.
|
||||
Si ce nombre de colonnes est inferieur au minimum requis, cette fonction ne
|
||||
fait rien
|
||||
@param nb_c nouveau nombre de colonnes
|
||||
@see minNbColumns()
|
||||
*/
|
||||
void BorderInset::setNbColumns(int nb_c) {
|
||||
if (nb_c < min_nb_columns) return;
|
||||
nb_columns = nb_c;
|
||||
setInsetWidth(nb_columns * columns_width);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Change la largeur des colonnes ; celle-ci doit rester comprise entre 10 et
|
||||
200px.
|
||||
*/
|
||||
void BorderInset::setColumnsWidth(const qreal &new_cw) {
|
||||
columns_width = qBound(10.0, new_cw, 200.0);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Change la hauteur des en-tetes contenant les numeros de colonnes. Celle-ci
|
||||
doit rester comprise entre 5 et 50 px.
|
||||
*/
|
||||
void BorderInset::setColumnsHeaderHeight(const qreal &new_chh) {
|
||||
columns_header_height = qBound(5.0, new_chh, 50.0);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Change la hauteur des colonnes (et donc du cadre). Cette hauteur doit
|
||||
rester superieure a la hauteur des en-tetes de colonnes + 20px.
|
||||
*/
|
||||
void BorderInset::setColumnsHeight(const qreal &new_ch) {
|
||||
columns_height = qMax(columns_header_height + min_columns_height, new_ch);
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Change la largeur du cartouche. Cette largeur doit rester comprise entre
|
||||
100px et la largeur du cartouche
|
||||
*/
|
||||
void BorderInset::setInsetWidth(const qreal &new_iw) {
|
||||
inset_width = qMax(100.0, qMin(nb_columns * columns_width, new_iw));
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Change la hauteur du cartouche. Cette largeur doit rester comprise entre
|
||||
20px et la hauteur du cartouche.
|
||||
*/
|
||||
void BorderInset::setInsetHeight(const qreal &new_ih) {
|
||||
inset_height = qMax(20.0, qMin(columns_height, new_ih));
|
||||
updateRectangles();
|
||||
}
|
||||
|
||||
/**
|
||||
Ajuste la largeur du cartouche de facon a ce que celui-ci soit aussi large
|
||||
que le schema
|
||||
*/
|
||||
void BorderInset::adjustInsetToColumns() {
|
||||
setInsetWidth(nbColumn() * columnsWidth());
|
||||
}
|
||||
182
sources/borderinset.h
Normal file
182
sources/borderinset.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 BORDERINSET_H
|
||||
#define BORDERINSET_H
|
||||
#include "insetproperties.h"
|
||||
#include <QObject>
|
||||
#include <QRectF>
|
||||
#include <QDate>
|
||||
class QPainter;
|
||||
/**
|
||||
Cette classe represente l'ensemble bordure + cartouche qui encadre le
|
||||
schema electrique.
|
||||
*/
|
||||
class BorderInset : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
BorderInset(QObject * = 0);
|
||||
virtual ~BorderInset();
|
||||
|
||||
private:
|
||||
BorderInset(const BorderInset &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void draw(QPainter *, qreal = 0.0, qreal = 0.0);
|
||||
|
||||
// methodes d'acces en lecture aux dimensions
|
||||
/// @return le nombre de colonnes du schema
|
||||
int nbColumn() const { return(nb_columns); }
|
||||
/// @return la taille des colonnes en pixels
|
||||
qreal columnsWidth() const { return(columns_width); }
|
||||
/// @return la hauteur, en pixels, des en-tetes des colonnes
|
||||
qreal columnsHeaderHeight() const { return(columns_header_height); }
|
||||
/// @return la hauteur des colonnes, en-tetes inclus
|
||||
qreal columnsHeight() const { return(columns_height); }
|
||||
/// @return la largeur de la bordure
|
||||
qreal borderWidth() const { return(nb_columns * columns_width); }
|
||||
/// @return la hauteur de la bordure
|
||||
qreal borderHeight() const { return(columns_height + inset_height); }
|
||||
/// @return la largeur du cartouche
|
||||
qreal insetWidth() const { return(inset_width); }
|
||||
/// @return la hauteur du cartouche
|
||||
qreal insetHeight() const { return(inset_height); }
|
||||
/// @return la hauteur minimale acceptee des colonnes
|
||||
qreal minColumnsHeight() const { return(min_columns_height); }
|
||||
/// @return le nombre minimum accepte de colonnes
|
||||
int minNbColumns() const { return(min_nb_columns); }
|
||||
|
||||
// methodes d'acces en lecture aux informations du cartouche
|
||||
/// @return le champ "Auteur" du cartouche
|
||||
QString author() const { return(bi_author); }
|
||||
/// @return le champ "Date" du cartouche
|
||||
QDate date() const { return(bi_date); }
|
||||
/// @return le champ "Titre" du cartouche
|
||||
QString title() const { return(bi_title); }
|
||||
/// @return le champ "Folio" du cartouche
|
||||
QString folio() const { return(bi_folio); }
|
||||
/// @return le champ "Fichier" du cartouche
|
||||
QString fileName() const { return(bi_filename); }
|
||||
|
||||
// methodes d'acces en lecture aux options
|
||||
/// @return true si le cartouche est affiche, false sinon
|
||||
bool insetIsDisplayed() const { return(display_inset); }
|
||||
/// @return true si les entetes des colonnes sont affiches, false sinon
|
||||
bool columnsAreDisplayed() const { return(display_columns); }
|
||||
/// @return true si la bordure est affichee, false sinon
|
||||
bool borderIsDisplayed() const { return(display_border); }
|
||||
|
||||
// methodes d'acces en ecriture aux dimensions
|
||||
void addColumn ();
|
||||
void removeColumn ();
|
||||
void setNbColumns (int);
|
||||
void setColumnsWidth (const qreal &);
|
||||
void setColumnsHeaderHeight(const qreal &);
|
||||
void setColumnsHeight (const qreal &);
|
||||
void setInsetWidth (const qreal &);
|
||||
void setInsetHeight (const qreal &);
|
||||
void adjustInsetToColumns ();
|
||||
|
||||
// methodes d'acces en ecriture aux informations du cartouche
|
||||
/// @param author le nouveau contenu du champ "Auteur"
|
||||
void setAuthor (const QString &author) { bi_author = author; }
|
||||
/// @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; }
|
||||
/// @param folio le nouveau contenu du champ "Folio"
|
||||
void setFolio (const QString &folio) { bi_folio = folio; }
|
||||
/// @param filename le nouveau contenu du champ "Fichier"
|
||||
void setFileName (const QString &filename) { bi_filename = filename; }
|
||||
|
||||
/// @return les proprietes du cartouches
|
||||
InsetProperties exportInset() {
|
||||
InsetProperties ip;
|
||||
ip.author = bi_author;
|
||||
ip.date = bi_date;
|
||||
ip.title = bi_title;
|
||||
ip.folio = bi_folio;
|
||||
ip.filename = bi_filename;
|
||||
return(ip);
|
||||
}
|
||||
|
||||
/// @param ip les nouvelles proprietes du cartouche
|
||||
void importInset(const InsetProperties &ip) {
|
||||
bi_author = ip.author;
|
||||
bi_date = ip.date;
|
||||
bi_title = ip.title;
|
||||
bi_folio = ip.folio;
|
||||
bi_filename = ip.filename;
|
||||
}
|
||||
|
||||
// methodes d'acces en ecriture aux options
|
||||
/// @param di true pour afficher le cartouche, false sinon
|
||||
void displayInset (bool di) { display_inset = di; }
|
||||
/// @param dc true pour afficher les entetes des colonnes, false sinon
|
||||
void displayColumns (bool dc) { display_columns = dc; }
|
||||
/// @param db true pour afficher la bordure du schema, false sinon
|
||||
void displayBorder (bool db) { display_border = db; }
|
||||
|
||||
private:
|
||||
void updateRectangles();
|
||||
|
||||
// signaux
|
||||
signals:
|
||||
/**
|
||||
Signal emis lorsque la bordure change
|
||||
@param old_border Ancienne bordure
|
||||
@param new_border Nouvelle bordure
|
||||
*/
|
||||
void borderChanged(QRectF old_border, QRectF new_border);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
// informations du cartouche
|
||||
QString bi_author;
|
||||
QDate bi_date;
|
||||
QString bi_title;
|
||||
QString bi_folio;
|
||||
QString bi_filename;
|
||||
|
||||
// dimensions du cadre et du cartouche
|
||||
int nb_columns;
|
||||
int min_nb_columns;
|
||||
qreal columns_width;
|
||||
qreal columns_header_height;
|
||||
qreal columns_height;
|
||||
qreal min_columns_height;
|
||||
qreal inset_width;
|
||||
qreal inset_height;
|
||||
|
||||
// rectangles utilises pour le dessin
|
||||
QRectF border;
|
||||
QRectF inset;
|
||||
QRectF inset_author;
|
||||
QRectF inset_date;
|
||||
QRectF inset_title;
|
||||
QRectF inset_file;
|
||||
QRectF inset_folio;
|
||||
|
||||
// booleens pour les options de dessin
|
||||
bool display_inset;
|
||||
bool display_columns;
|
||||
bool display_border;
|
||||
};
|
||||
#endif
|
||||
1307
sources/conductor.cpp
Normal file
1307
sources/conductor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
146
sources/conductor.h
Normal file
146
sources/conductor.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_H
|
||||
#define CONDUCTOR_H
|
||||
#include <QtGui>
|
||||
#include "terminal.h"
|
||||
#include "conductorprofile.h"
|
||||
#include "conductorproperties.h"
|
||||
class ConductorSegment;
|
||||
class DiagramTextItem;
|
||||
class Element;
|
||||
typedef QPair<QPointF, Qt::Corner> ConductorBend;
|
||||
typedef QHash<Qt::Corner, ConductorProfile> ConductorProfilesGroup;
|
||||
/**
|
||||
Cette classe represente un conducteur. Un conducteur relie deux bornes d'element.
|
||||
*/
|
||||
class Conductor : public QObject, public QGraphicsPathItem {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
Conductor(Terminal *, Terminal *, Element * = 0, QGraphicsScene * = 0);
|
||||
virtual ~Conductor();
|
||||
|
||||
private:
|
||||
Conductor(const Conductor &);
|
||||
|
||||
// attributs
|
||||
public:
|
||||
enum { Type = UserType + 1001 };
|
||||
|
||||
/// premiere borne a laquelle le fil est rattache
|
||||
Terminal *terminal1;
|
||||
/// deuxieme borne a laquelle le fil est rattache
|
||||
Terminal *terminal2;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
/**
|
||||
permet de caster un QGraphicsItem en Conductor avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
void destroy();
|
||||
/// @return true si ce conducteur est detruit
|
||||
bool isDestroyed() const { return(destroyed); }
|
||||
Diagram *diagram() const;
|
||||
void updateWithNewPos(const QRectF &, const Terminal *, const QPointF &);
|
||||
void update(const QRectF & = QRectF());
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
QRectF boundingRect() const;
|
||||
virtual QPainterPath shape() const;
|
||||
qreal length();
|
||||
ConductorSegment *middleSegment();
|
||||
bool containsPoint(const QPointF &) const;
|
||||
QString text() const;
|
||||
void setText(const QString &);
|
||||
static bool valideXml(QDomElement &);
|
||||
bool fromXml(QDomElement &);
|
||||
QDomElement toXml(QDomDocument &, QHash<Terminal *, int> &) const;
|
||||
const QList<ConductorSegment *> segmentsList() const;
|
||||
void setProperties(const ConductorProperties &);
|
||||
ConductorProperties properties() const;
|
||||
void setProfile(const ConductorProfile &, Qt::Corner);
|
||||
ConductorProfile profile(Qt::Corner) const;
|
||||
void setProfiles(const ConductorProfilesGroup &);
|
||||
ConductorProfilesGroup profiles() const;
|
||||
void readProperties();
|
||||
|
||||
public slots:
|
||||
void displayedTextChanged();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *);
|
||||
|
||||
private:
|
||||
/// caracteristiques du conducteur
|
||||
ConductorProperties properties_;
|
||||
/// booleen indiquant si le fil est encore valide
|
||||
bool destroyed;
|
||||
/// champ de texte editable pour les conducteurs non unifilaires
|
||||
DiagramTextItem *text_item;
|
||||
/// segments composant le conducteur
|
||||
ConductorSegment *segments;
|
||||
/// attributs lies aux manipulations a la souris
|
||||
QPointF press_point;
|
||||
bool moving_point;
|
||||
bool moving_segment;
|
||||
int moved_point;
|
||||
qreal previous_z_value;
|
||||
ConductorSegment *moved_segment;
|
||||
/// booleen indiquant si le conducteur a ete modifie manuellement par l'utilisateur
|
||||
bool modified_path;
|
||||
/// booleen indiquant s'il faut sauver le profil courant au plus tot
|
||||
bool has_to_save_profile;
|
||||
/// profil du conducteur : "photo" de ce a quoi le conducteur doit ressembler - il y a un profil par type de trajet
|
||||
ConductorProfilesGroup conductor_profiles;
|
||||
/// QPen et QBrush utilises pour dessiner les conducteurs
|
||||
static QPen conductor_pen;
|
||||
static QBrush conductor_brush;
|
||||
static QBrush square_brush;
|
||||
static bool pen_and_brush_initialized;
|
||||
|
||||
private:
|
||||
void segmentsToPath();
|
||||
void saveProfile(bool = true);
|
||||
void priv_calculeConductor(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
|
||||
void priv_modifieConductor(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
|
||||
uint nbSegments(QET::ConductorSegmentType = QET::Both) const;
|
||||
QList<QPointF> segmentsToPoints() const;
|
||||
QSet<Conductor *> relatedConductors() const;
|
||||
QList<ConductorBend> bends() const;
|
||||
QList<QPointF> junctions() const;
|
||||
void pointsToSegments(QList<QPointF>);
|
||||
bool hasClickedOn(QPointF, QPointF) const;
|
||||
void calculateTextItemPosition();
|
||||
Qt::Corner currentPathType() const;
|
||||
void deleteSegments();
|
||||
static int getCoeff(const qreal &, const qreal &);
|
||||
static int getSign(const qreal &);
|
||||
QHash<ConductorSegmentProfile *, qreal> shareOffsetBetweenSegments(const qreal &offset, const QList<ConductorSegmentProfile *> &, const qreal & = 0.01) const;
|
||||
static QPointF extendTerminal(const QPointF &, QET::Orientation, qreal = 9.0);
|
||||
static qreal conductor_bound(qreal, qreal, qreal, qreal = 0.0);
|
||||
static qreal conductor_bound(qreal, qreal, bool);
|
||||
static Qt::Corner movementType(const QPointF &, const QPointF &);
|
||||
};
|
||||
#endif
|
||||
157
sources/conductorprofile.cpp
Normal file
157
sources/conductorprofile.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "conductorprofile.h"
|
||||
#include "conductor.h"
|
||||
#include "conductorsegmentprofile.h"
|
||||
|
||||
/// Constructeur
|
||||
ConductorProfile::ConductorProfile() {
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param conductor conducteur dont il faut extraire le profil
|
||||
*/
|
||||
ConductorProfile::ConductorProfile(Conductor *conductor) {
|
||||
fromConductor(conductor);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur de copie
|
||||
@param c autre conducteur
|
||||
*/
|
||||
ConductorProfile::ConductorProfile(const ConductorProfile &c) {
|
||||
beginOrientation = c.beginOrientation;
|
||||
endOrientation = c.endOrientation;
|
||||
foreach(ConductorSegmentProfile *csp, c.segments) {
|
||||
segments << new ConductorSegmentProfile(*csp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Operateur =
|
||||
@param c autre conducteur
|
||||
*/
|
||||
ConductorProfile &ConductorProfile::operator=(const ConductorProfile &c) {
|
||||
if (&c == this) return(*this);
|
||||
|
||||
// supprime ses informations
|
||||
setNull();
|
||||
|
||||
// copie les informations de l'autre profil de conducteur
|
||||
beginOrientation = c.beginOrientation;
|
||||
endOrientation = c.endOrientation;
|
||||
foreach(ConductorSegmentProfile *csp, c.segments) {
|
||||
segments << new ConductorSegmentProfile(*csp);
|
||||
}
|
||||
return(*this);
|
||||
}
|
||||
|
||||
/// destructeur
|
||||
ConductorProfile::~ConductorProfile() {
|
||||
setNull();
|
||||
}
|
||||
|
||||
/// @return true si le profil est nul
|
||||
bool ConductorProfile::isNull() const {
|
||||
return(segments.isEmpty());
|
||||
}
|
||||
|
||||
/// supprime les segments du profil de conducteur
|
||||
void ConductorProfile::setNull() {
|
||||
foreach(ConductorSegmentProfile *csp, segments) delete csp;
|
||||
segments.clear();
|
||||
}
|
||||
|
||||
/// @return la largeur occupee par le conducteur
|
||||
qreal ConductorProfile::width() const {
|
||||
qreal width = 0.0;
|
||||
foreach(ConductorSegmentProfile *csp, segments) {
|
||||
if (csp -> isHorizontal) width += csp -> length;
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
/// @return la hauteur occupee par le conducteur
|
||||
qreal ConductorProfile::height() const{
|
||||
qreal height = 0.0;
|
||||
foreach(ConductorSegmentProfile *csp, segments) {
|
||||
if (!csp -> isHorizontal) height += csp -> length;
|
||||
}
|
||||
return(height);
|
||||
}
|
||||
|
||||
/**
|
||||
@param type Type de Segments
|
||||
@return Le nombre de segments composant le conducteur.
|
||||
*/
|
||||
uint ConductorProfile::nbSegments(QET::ConductorSegmentType type) const {
|
||||
if (type == QET::Both) return(segments.count());
|
||||
uint nb_seg = 0;
|
||||
foreach(ConductorSegmentProfile *csp, segments) {
|
||||
if (type == QET::Horizontal && csp -> isHorizontal) ++ nb_seg;
|
||||
else if (type == QET::Vertical && !csp -> isHorizontal) ++ nb_seg;
|
||||
}
|
||||
return(nb_seg);
|
||||
}
|
||||
|
||||
/// @return les segments horizontaux de ce profil
|
||||
QList<ConductorSegmentProfile *> ConductorProfile::horizontalSegments() {
|
||||
QList<ConductorSegmentProfile *> segments_list;
|
||||
foreach(ConductorSegmentProfile *csp, segments) {
|
||||
if (csp -> isHorizontal) segments_list << csp;
|
||||
}
|
||||
return(segments_list);
|
||||
}
|
||||
|
||||
/// @return les segments verticaux de ce profil
|
||||
QList<ConductorSegmentProfile *> ConductorProfile::verticalSegments() {
|
||||
QList<ConductorSegmentProfile *> segments_list;
|
||||
foreach(ConductorSegmentProfile *csp, segments) {
|
||||
if (!csp -> isHorizontal) segments_list << csp;
|
||||
}
|
||||
return(segments_list);
|
||||
}
|
||||
|
||||
/**
|
||||
Reconstruit le profil a partir d'un conducteur existant
|
||||
*/
|
||||
void ConductorProfile::fromConductor(Conductor *conductor) {
|
||||
// supprime les segments precedents
|
||||
setNull();
|
||||
|
||||
foreach(ConductorSegment *conductor_segment, conductor -> segmentsList()) {
|
||||
segments << new ConductorSegmentProfile(conductor_segment);
|
||||
}
|
||||
beginOrientation = conductor -> terminal1 -> orientation();
|
||||
endOrientation = conductor -> terminal2 -> orientation();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de debugger un profil de conducteur
|
||||
@param d Object QDebug a utiliser pour l'affichage des informations de debug
|
||||
@param t Profil de conducteur a debugger
|
||||
*/
|
||||
QDebug &operator<<(QDebug d, ConductorProfile &t) {
|
||||
d << "ConductorProfile {";
|
||||
foreach(ConductorSegmentProfile *csp, t.segments) {
|
||||
d << "CSP" << (csp -> isHorizontal ? "horizontal" : "vertical") << ":" << csp -> length << ",";
|
||||
}
|
||||
d << "}";
|
||||
return(d.space());
|
||||
}
|
||||
58
sources/conductorprofile.h
Normal file
58
sources/conductorprofile.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_PROFILE_H
|
||||
#define CONDUCTOR_PROFILE_H
|
||||
#include <QList>
|
||||
#include "qet.h"
|
||||
class Conductor;
|
||||
class ConductorSegmentProfile;
|
||||
/**
|
||||
Cette classe contient le profil (= les caracteristiques essentielles) d'un
|
||||
conducteur.
|
||||
*/
|
||||
class ConductorProfile {
|
||||
public:
|
||||
// constructeurs, destructeur
|
||||
ConductorProfile();
|
||||
ConductorProfile(Conductor *conductor);
|
||||
ConductorProfile(const ConductorProfile &);
|
||||
ConductorProfile &operator=(const ConductorProfile &);
|
||||
virtual ~ConductorProfile();
|
||||
|
||||
// attributs
|
||||
public:
|
||||
/// Segment composant le profil du conducteur
|
||||
QList<ConductorSegmentProfile *> segments;
|
||||
/// Orientation de la borne de depart du profil
|
||||
QET::Orientation beginOrientation;
|
||||
/// Orientation de la borne d'arrivee du profil
|
||||
QET::Orientation endOrientation;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool isNull() const;
|
||||
void setNull();
|
||||
qreal width() const;
|
||||
qreal height() const;
|
||||
uint nbSegments(QET::ConductorSegmentType) const;
|
||||
QList<ConductorSegmentProfile *> horizontalSegments();
|
||||
QList<ConductorSegmentProfile *> verticalSegments();
|
||||
void fromConductor(Conductor *);
|
||||
};
|
||||
QDebug &operator<<(QDebug d, ConductorProfile &);
|
||||
#endif
|
||||
319
sources/conductorproperties.cpp
Normal file
319
sources/conductorproperties.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "conductorproperties.h"
|
||||
|
||||
/**
|
||||
Constructeur par defaut
|
||||
*/
|
||||
SingleLineProperties::SingleLineProperties() :
|
||||
hasGround(true),
|
||||
hasNeutral(true),
|
||||
phases(1)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
SingleLineProperties::~SingleLineProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le nombre de phases (0, 1, 2, ou 3)
|
||||
@param n Nombre de phases
|
||||
*/
|
||||
void SingleLineProperties::setPhasesCount(int n) {
|
||||
phases = qBound(0, n, 3);
|
||||
}
|
||||
|
||||
/// @return le nombre de phases (0, 1, 2, ou 3)
|
||||
unsigned short int SingleLineProperties::phasesCount() {
|
||||
return(phases);
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine les symboles propres a un conducteur unifilaire
|
||||
@param painter QPainter a utiliser pour dessiner les symboles
|
||||
@param direction direction du segment sur lequel les symboles apparaitront
|
||||
@param rect rectangle englobant le dessin ; utilise pour specifier a la fois la position et la taille du dessin
|
||||
*/
|
||||
void SingleLineProperties::draw(QPainter *painter, QET::ConductorSegmentType direction, const QRectF &rect) {
|
||||
// s'il n'y a rien a dessiner, on retourne immediatement
|
||||
if (!hasNeutral && !hasGround && !phases) return;
|
||||
|
||||
// prepare le QPainter
|
||||
painter -> save();
|
||||
QPen pen(painter -> pen());
|
||||
pen.setCapStyle(Qt::FlatCap);
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
painter -> setPen(pen);
|
||||
painter -> setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
uint symbols_count = (hasNeutral ? 1 : 0) + (hasGround ? 1 : 0) + phases;
|
||||
qreal interleave;
|
||||
qreal symbol_width;
|
||||
if (direction == QET::Horizontal) {
|
||||
interleave = rect.width() / (symbols_count + 1);
|
||||
symbol_width = rect.width() / 12;
|
||||
for (uint i = 1 ; i <= symbols_count ; ++ i) {
|
||||
// dessine le tronc du symbole
|
||||
QPointF symbol_p1(rect.x() + (i * interleave) + symbol_width, rect.y() + rect.height() * 0.75);
|
||||
QPointF symbol_p2(rect.x() + (i * interleave) - symbol_width, rect.y() + rect.height() * 0.25);
|
||||
painter -> drawLine(QLineF(symbol_p1, symbol_p2));
|
||||
|
||||
// dessine le reste des symboles terre et neutre
|
||||
if (hasGround && i == 1) {
|
||||
drawGround(painter, direction, symbol_p2, symbol_width * 2.0);
|
||||
} else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) {
|
||||
drawNeutral(painter, direction, symbol_p2, symbol_width * 1.35);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
interleave = rect.height() / (symbols_count + 1);
|
||||
symbol_width = rect.height() / 12;
|
||||
for (uint i = 1 ; i <= symbols_count ; ++ i) {
|
||||
// dessine le tronc du symbole
|
||||
QPointF symbol_p2(rect.x() + rect.width() * 0.75, rect.y() + (i * interleave) - symbol_width);
|
||||
QPointF symbol_p1(rect.x() + rect.width() * 0.25, rect.y() + (i * interleave) + symbol_width);
|
||||
painter -> drawLine(QLineF(symbol_p1, symbol_p2));
|
||||
|
||||
// dessine le reste des symboles terre et neutre
|
||||
if (hasGround && i == 1) {
|
||||
drawGround(painter, direction, symbol_p2, symbol_width * 2.0);
|
||||
} else if (hasNeutral && ((i == 1 && !hasGround) || (i == 2 && hasGround))) {
|
||||
drawNeutral(painter, direction, symbol_p2, symbol_width * 1.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le segment correspondant au symbole de la terre sur un conducteur unifilaire
|
||||
@param painter QPainter a utiliser pour dessiner le segment
|
||||
@param direction direction du segment sur lequel le symbole apparaitra
|
||||
@param center centre du segment
|
||||
@param size taille du segment
|
||||
*/
|
||||
void SingleLineProperties::drawGround(QPainter *painter, QET::ConductorSegmentType direction, QPointF center, qreal size) {
|
||||
painter -> save();
|
||||
|
||||
// prepare le QPainter
|
||||
painter -> setRenderHint(QPainter::Antialiasing, false);
|
||||
QPen pen2(painter -> pen());
|
||||
pen2.setCapStyle(Qt::SquareCap);
|
||||
painter -> setPen(pen2);
|
||||
|
||||
// dessine le segment representant la terre
|
||||
qreal half_size = size / 2.0;
|
||||
QPointF offset_point(
|
||||
(direction == QET::Horizontal) ? half_size : 0.0,
|
||||
(direction == QET::Horizontal) ? 0.0 : half_size
|
||||
);
|
||||
painter -> drawLine(
|
||||
QLineF(
|
||||
center + offset_point,
|
||||
center - offset_point
|
||||
)
|
||||
);
|
||||
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le cercle correspondant au symbole du neutre sur un conducteur unifilaire
|
||||
@param painter QPainter a utiliser pour dessiner le segment
|
||||
@param direction direction du segment sur lequel le symbole apparaitra
|
||||
@param center centre du cercle
|
||||
@param size diametre du cercle
|
||||
*/
|
||||
void SingleLineProperties::drawNeutral(QPainter *painter, QET::ConductorSegmentType, QPointF center, qreal size) {
|
||||
painter -> save();
|
||||
|
||||
// prepare le QPainter
|
||||
if (painter -> brush() == Qt::NoBrush) painter -> setBrush(Qt::black);
|
||||
painter -> setPen(Qt::NoPen);
|
||||
|
||||
// desine le cercle representant le neutre
|
||||
painter -> drawEllipse(
|
||||
QRectF(
|
||||
center - QPointF(size / 2.0, size / 2.0),
|
||||
QSizeF(size, size)
|
||||
)
|
||||
);
|
||||
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
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 {
|
||||
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
|
||||
de l'element e
|
||||
@param e Element XML dont les attributs seront lus
|
||||
*/
|
||||
void SingleLineProperties::fromXml(QDomElement &e) {
|
||||
hasGround = e.attribute("ground") == "true";
|
||||
hasNeutral = e.attribute("neutral") == "true";
|
||||
setPhasesCount(e.attribute("phase").toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
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 {
|
||||
e.setAttribute("type", typeToString(type));
|
||||
if (type == Single) {
|
||||
singleLineProperties.toXml(d, e);
|
||||
} else if (type == Multi) {
|
||||
e.setAttribute("num", text);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
importe les parametres du conducteur unifilaire a partir des attributs XML
|
||||
de l'element e
|
||||
@param e Element XML dont les attributs seront lus
|
||||
*/
|
||||
void ConductorProperties::fromXml(QDomElement &e) {
|
||||
if (e.attribute("type") == typeToString(Single)) {
|
||||
// recupere les parametres specifiques a un conducteur unifilaire
|
||||
singleLineProperties.fromXml(e);
|
||||
type = Single;
|
||||
} else if (e.attribute("type") == typeToString(Simple)) {
|
||||
type = Simple;
|
||||
} else {
|
||||
// recupere le champ de texte
|
||||
text = e.attribute("num");
|
||||
type = Multi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param settings Parametres a ecrire
|
||||
@param prefix prefix a ajouter devant les noms des parametres
|
||||
*/
|
||||
void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) const {
|
||||
settings.setValue(prefix + "type", typeToString(type));
|
||||
settings.setValue(prefix + "text", text);
|
||||
singleLineProperties.toSettings(settings, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
@param settings Parametres a lire
|
||||
@param prefix prefix 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();
|
||||
if (setting_type == typeToString(Single)) {
|
||||
type = Single;
|
||||
} else if (setting_type == typeToString(Simple)) {
|
||||
type = Simple;
|
||||
} else {
|
||||
type = Multi;
|
||||
}
|
||||
singleLineProperties.fromSettings(settings, prefix);
|
||||
text = settings.value(prefix + "text", "_").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@param t type du conducteur
|
||||
*/
|
||||
QString ConductorProperties::typeToString(ConductorType t) {
|
||||
switch(t) {
|
||||
case Simple: return("simple");
|
||||
case Single: return("single");
|
||||
case Multi: return("multi");
|
||||
default: return(QString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param other l'autre ensemble de proprietes avec lequel il faut effectuer la comparaison
|
||||
@return true si les deux ensembles de proprietes sont identiques, false sinon
|
||||
*/
|
||||
int ConductorProperties::operator==(const ConductorProperties &other) {
|
||||
return(
|
||||
other.type == type &&\
|
||||
other.text == text &&\
|
||||
other.singleLineProperties == singleLineProperties
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@param other l'autre ensemble de proprietes avec lequel il faut effectuer la comparaison
|
||||
@return true si les deux ensembles de proprietes sont differents, false sinon
|
||||
*/
|
||||
int ConductorProperties::operator!=(const ConductorProperties &other) {
|
||||
return(
|
||||
other.type != type ||\
|
||||
other.text != text ||\
|
||||
other.singleLineProperties != singleLineProperties
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@param other l'autre ensemble de proprietes avec lequel il faut effectuer la comparaison
|
||||
@return true si les deux ensembles de proprietes sont identiques, false sinon
|
||||
*/
|
||||
int SingleLineProperties::operator==(const SingleLineProperties &other) const {
|
||||
return(
|
||||
other.hasGround == hasGround &&\
|
||||
other.hasNeutral == hasNeutral &&\
|
||||
other.phases == phases
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@param other l'autre ensemble de proprietes avec lequel il faut effectuer la comparaison
|
||||
@return true si les deux ensembles de proprietes sont differents, false sinon
|
||||
*/
|
||||
int SingleLineProperties::operator!=(const SingleLineProperties &other) const {
|
||||
return(!(other == (*this)));
|
||||
}
|
||||
|
||||
/**
|
||||
@param settings Parametres a ecrire
|
||||
@param prefix prefix a ajouter devant les noms des parametres
|
||||
*/
|
||||
void SingleLineProperties::toSettings(QSettings &settings, const QString &prefix) const {
|
||||
settings.setValue(prefix + "hasGround", hasGround);
|
||||
settings.setValue(prefix + "hasNeutral", hasNeutral);
|
||||
settings.setValue(prefix + "phases", phases);
|
||||
}
|
||||
|
||||
/**
|
||||
@param settings Parametres a lire
|
||||
@param prefix prefix a ajouter devant les noms des parametres
|
||||
*/
|
||||
void SingleLineProperties::fromSettings(QSettings &settings, const QString &prefix) {
|
||||
hasGround = settings.value(prefix + "hasGround", true).toBool();
|
||||
hasNeutral = settings.value(prefix + "hasNeutral", true).toBool();
|
||||
phases = settings.value(prefix + "phases", 1).toInt();
|
||||
}
|
||||
100
sources/conductorproperties.h
Normal file
100
sources/conductorproperties.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_PROPERTIES_H
|
||||
#define CONDUCTOR_PROPERTIES_H
|
||||
#include "qet.h"
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
/**
|
||||
Cette classe represente les proprietes specifiques a un conducteur unifilaire
|
||||
*/
|
||||
class SingleLineProperties {
|
||||
public:
|
||||
SingleLineProperties();
|
||||
virtual ~SingleLineProperties();
|
||||
|
||||
void setPhasesCount(int);
|
||||
unsigned short int phasesCount();
|
||||
void draw(QPainter *, QET::ConductorSegmentType, const QRectF &);
|
||||
void toXml(QDomDocument &, QDomElement &) const;
|
||||
void fromXml(QDomElement &);
|
||||
void toSettings(QSettings &, const QString & = QString()) const;
|
||||
void fromSettings(QSettings &, const QString & = QString());
|
||||
|
||||
/// indique si le conducteur unifilaire doit afficher le symbole terre
|
||||
bool hasGround;
|
||||
/// indique si le conducteur unifilaire doit afficher le symbole neutre
|
||||
bool hasNeutral;
|
||||
|
||||
int operator==(const SingleLineProperties &) const;
|
||||
int operator!=(const SingleLineProperties &) const;
|
||||
|
||||
private:
|
||||
unsigned short int phases;
|
||||
void drawGround (QPainter *, QET::ConductorSegmentType, QPointF, qreal);
|
||||
void drawNeutral(QPainter *, QET::ConductorSegmentType, QPointF, qreal);
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente les proprietes specifiques a un conducteur,
|
||||
en dehors de ses bornes et de son trajet.
|
||||
*/
|
||||
class ConductorProperties {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/**
|
||||
Constructeur : par defaut, les proprietes font un conducteur
|
||||
multifilaire dont le texte est "_"
|
||||
*/
|
||||
ConductorProperties() : type(Multi), text("_") {
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
virtual ~ConductorProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
Represente le type d'un conducteur :
|
||||
* Simple : ni symbole ni champ de texte
|
||||
* Single : symboles unifilaires, pas de champ de texte
|
||||
* Multi : champ de texte, pas de symbole
|
||||
*/
|
||||
enum ConductorType { Simple, Single, Multi };
|
||||
|
||||
// attributs
|
||||
/// type du conducteur
|
||||
ConductorType type;
|
||||
|
||||
/// texte affiche si le conducteur est multifilaire
|
||||
QString text;
|
||||
|
||||
/// proprietes si le conducteur est unifilaire
|
||||
SingleLineProperties singleLineProperties;
|
||||
|
||||
// methodes
|
||||
void toXml(QDomDocument &, QDomElement &) const;
|
||||
void fromXml(QDomElement &);
|
||||
void toSettings(QSettings &, const QString & = QString()) const;
|
||||
void fromSettings(QSettings &, const QString & = QString());
|
||||
static QString typeToString(ConductorType);
|
||||
|
||||
// operateurs
|
||||
int operator==(const ConductorProperties &);
|
||||
int operator!=(const ConductorProperties &);
|
||||
};
|
||||
#endif
|
||||
211
sources/conductorpropertieswidget.cpp
Normal file
211
sources/conductorpropertieswidget.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "conductorpropertieswidget.h"
|
||||
#include <QtGui>
|
||||
#include "conductor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ConductorPropertiesWidget::ConductorPropertiesWidget(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
buildInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
@param cp Proprietes a editer
|
||||
*/
|
||||
ConductorPropertiesWidget::ConductorPropertiesWidget(const ConductorProperties &cp, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
buildInterface();
|
||||
setConductorProperties(cp);
|
||||
}
|
||||
|
||||
/// construit l'interface du widget
|
||||
void ConductorPropertiesWidget::buildInterface() {
|
||||
|
||||
setMinimumSize(380, 280);
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
|
||||
QGroupBox *groupbox = new QGroupBox(tr("Type de conducteur"));
|
||||
main_layout -> addWidget(groupbox);
|
||||
|
||||
QVBoxLayout *groupbox_layout = new QVBoxLayout();
|
||||
groupbox -> setLayout(groupbox_layout);
|
||||
|
||||
simple = new QRadioButton(tr("Simple"));
|
||||
multiline = new QRadioButton(tr("Multifilaire"));
|
||||
|
||||
QHBoxLayout *multiline_layout = new QHBoxLayout();
|
||||
QLabel *text = new QLabel(tr("Texte :"));
|
||||
text_field = new QLineEdit();
|
||||
multiline_layout -> addWidget(text);
|
||||
multiline_layout -> addWidget(text_field);
|
||||
|
||||
singleline = new QRadioButton(tr("Unifilaire"));
|
||||
|
||||
QHBoxLayout *singleline_layout3 = new QHBoxLayout();
|
||||
phase_checkbox = new QCheckBox(tr("phase"));
|
||||
phase_checkbox -> setIcon(QIcon(":/ico/phase.png"));
|
||||
phase_slider = new QSlider(Qt::Horizontal);
|
||||
phase_slider -> setRange(1, 3);
|
||||
phase_spinbox = new QSpinBox();
|
||||
phase_spinbox -> setRange(1, 3);
|
||||
singleline_layout3 -> addWidget(phase_checkbox);
|
||||
singleline_layout3 -> addWidget(phase_slider);
|
||||
singleline_layout3 -> addWidget(phase_spinbox);
|
||||
|
||||
QVBoxLayout *singleline_layout2 = new QVBoxLayout();
|
||||
ground_checkbox = new QCheckBox(tr("terre"));
|
||||
ground_checkbox -> setIcon(QIcon(":/ico/ground.png"));
|
||||
neutral_checkbox = new QCheckBox(tr("neutre"));
|
||||
neutral_checkbox -> setIcon(QIcon(":/ico/neutral.png"));
|
||||
singleline_layout2 -> addWidget(ground_checkbox);
|
||||
singleline_layout2 -> addWidget(neutral_checkbox);
|
||||
singleline_layout2 -> addLayout(singleline_layout3);
|
||||
|
||||
QHBoxLayout *singleline_layout1 = new QHBoxLayout();
|
||||
preview = new QLabel();
|
||||
preview -> setFixedSize(96, 96);
|
||||
singleline_layout1 -> addWidget(preview);
|
||||
singleline_layout1 -> addLayout(singleline_layout2);
|
||||
|
||||
groupbox_layout -> addWidget(simple);
|
||||
groupbox_layout -> addWidget(multiline);
|
||||
groupbox_layout -> addLayout(multiline_layout);
|
||||
groupbox_layout -> addWidget(singleline);
|
||||
groupbox_layout -> addLayout(singleline_layout1);
|
||||
|
||||
radio_buttons = new QButtonGroup(this);
|
||||
radio_buttons -> addButton(simple, ConductorProperties::Simple);
|
||||
radio_buttons -> addButton(multiline, ConductorProperties::Multi);
|
||||
radio_buttons -> addButton(singleline, ConductorProperties::Single);
|
||||
|
||||
buildConnections();
|
||||
setConductorType(ConductorProperties::Multi);
|
||||
}
|
||||
|
||||
/// Met en place les connexions signaux/slots
|
||||
void ConductorPropertiesWidget::buildConnections() {
|
||||
connect(phase_slider, SIGNAL(valueChanged(int)), phase_spinbox, SLOT(setValue(int)));
|
||||
connect(phase_spinbox, SIGNAL(valueChanged(int)), phase_slider, SLOT(setValue(int)));
|
||||
connect(ground_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
connect(neutral_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
connect(phase_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
connect(phase_slider, SIGNAL(valueChanged(int)), this, SLOT(updateConfig()));
|
||||
connect(radio_buttons, SIGNAL(buttonClicked(int)), this, SLOT(updateConfig()));
|
||||
connect(text_field, SIGNAL(textChanged(const QString &)), this, SLOT(updateConfig()));
|
||||
}
|
||||
|
||||
/// Enleve les connexions signaux/slots
|
||||
void ConductorPropertiesWidget::destroyConnections() {
|
||||
disconnect(phase_slider, SIGNAL(valueChanged(int)), phase_spinbox, SLOT(setValue(int)));
|
||||
disconnect(phase_spinbox, SIGNAL(valueChanged(int)), phase_slider, SLOT(setValue(int)));
|
||||
disconnect(ground_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
disconnect(neutral_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
disconnect(phase_checkbox, SIGNAL(toggled(bool)), this, SLOT(updateConfig()));
|
||||
disconnect(phase_slider, SIGNAL(valueChanged(int)), this, SLOT(updateConfig()));
|
||||
disconnect(radio_buttons, SIGNAL(buttonClicked(int)), this, SLOT(updateConfig()));
|
||||
disconnect(text_field, SIGNAL(textChanged(const QString &)), this, SLOT(updateConfig()));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ConductorPropertiesWidget::~ConductorPropertiesWidget() {
|
||||
}
|
||||
|
||||
/// Met a jour les proprietes
|
||||
void ConductorPropertiesWidget::updateConfig() {
|
||||
properties_.type = static_cast<ConductorProperties::ConductorType>(radio_buttons -> checkedId());
|
||||
properties_.text = text_field -> text();
|
||||
properties_.singleLineProperties.hasGround = ground_checkbox -> isChecked();
|
||||
properties_.singleLineProperties.hasNeutral = neutral_checkbox -> isChecked();
|
||||
properties_.singleLineProperties.setPhasesCount(phase_checkbox -> isChecked() ? phase_spinbox -> value() : 0);
|
||||
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/// Met a jour l'affichage des proprietes
|
||||
void ConductorPropertiesWidget::updateDisplay() {
|
||||
destroyConnections();
|
||||
|
||||
setConductorType(properties_.type);
|
||||
text_field -> setText(properties_.text);
|
||||
ground_checkbox -> setChecked(properties_.singleLineProperties.hasGround);
|
||||
neutral_checkbox -> setChecked(properties_.singleLineProperties.hasNeutral);
|
||||
phase_spinbox -> setValue(properties_.singleLineProperties.phasesCount());
|
||||
phase_slider -> setValue(properties_.singleLineProperties.phasesCount());
|
||||
phase_checkbox -> setChecked(properties_.singleLineProperties.phasesCount());
|
||||
|
||||
buildConnections();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
/// Met a jour la previsualisation des attributs unifilaires
|
||||
void ConductorPropertiesWidget::updatePreview() {
|
||||
const QRect pixmap_rect(0, 0, 96, 96);
|
||||
QPixmap pixmap(pixmap_rect.width(), pixmap_rect.height());
|
||||
QPainter painter;
|
||||
painter.begin(&pixmap);
|
||||
painter.eraseRect(pixmap_rect);
|
||||
painter.drawRect(pixmap_rect.adjusted(0,0,-1,-1));
|
||||
painter.drawLine(QLineF(0, pixmap_rect.height() / 2, pixmap_rect.width(), pixmap_rect.height() / 2));
|
||||
properties_.singleLineProperties.draw(&painter, QET::Horizontal, pixmap_rect);
|
||||
painter.end();
|
||||
preview -> setPixmap(pixmap);
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le widget en mode simple, unifilaire ou multifilaire
|
||||
@param t le type de conducteur
|
||||
*/
|
||||
void ConductorPropertiesWidget::setConductorType(ConductorProperties::ConductorType t) {
|
||||
|
||||
// widgets lies au simple
|
||||
simple -> setChecked(t == ConductorProperties::Simple);
|
||||
|
||||
// widgets lies au mode multifilaire
|
||||
multiline -> setChecked(t == ConductorProperties::Multi);
|
||||
text_field -> setEnabled(t == ConductorProperties::Multi);
|
||||
|
||||
// widgets lies au mode unifilaire
|
||||
bool sl = (t == ConductorProperties::Single);
|
||||
singleline -> setChecked(sl);
|
||||
preview -> setEnabled(sl);
|
||||
phase_checkbox -> setEnabled(sl);
|
||||
phase_slider -> setEnabled(sl);
|
||||
phase_spinbox -> setEnabled(sl);
|
||||
ground_checkbox -> setEnabled(sl);
|
||||
neutral_checkbox -> setEnabled(sl);
|
||||
}
|
||||
|
||||
/// @param p les nouvelles proprietes
|
||||
void ConductorPropertiesWidget::setConductorProperties(const ConductorProperties &p) {
|
||||
properties_ = p;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/// @return les proprietes editees
|
||||
ConductorProperties ConductorPropertiesWidget::conductorProperties() const {
|
||||
return(properties_);
|
||||
}
|
||||
74
sources/conductorpropertieswidget.h
Normal file
74
sources/conductorpropertieswidget.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_PROPERTIES_WIDGET_H
|
||||
#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
|
||||
les options supplementaires : symboles unifilaires, presence ou non d'un
|
||||
champ de texte, contenu de ce champ de texte, etc.
|
||||
*/
|
||||
class ConductorPropertiesWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ConductorPropertiesWidget(QWidget * = 0);
|
||||
ConductorPropertiesWidget(const ConductorProperties &, QWidget * = 0);
|
||||
virtual ~ConductorPropertiesWidget();
|
||||
|
||||
private:
|
||||
ConductorPropertiesWidget(const ConductorPropertiesWidget &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setConductorProperties(const ConductorProperties &);
|
||||
ConductorProperties conductorProperties() const;
|
||||
|
||||
private:
|
||||
void setConductorType(ConductorProperties::ConductorType);
|
||||
|
||||
public slots:
|
||||
void updatePreview();
|
||||
void updateConfig();
|
||||
void updateDisplay();
|
||||
|
||||
// attributs prives
|
||||
private:
|
||||
QButtonGroup *radio_buttons;
|
||||
QRadioButton *simple;
|
||||
QRadioButton *multiline;
|
||||
QLineEdit *text_field;
|
||||
QRadioButton *singleline;
|
||||
QCheckBox *phase_checkbox;
|
||||
QSlider *phase_slider;
|
||||
QSpinBox *phase_spinbox;
|
||||
QCheckBox *ground_checkbox;
|
||||
QCheckBox *neutral_checkbox;
|
||||
QLabel *preview;
|
||||
|
||||
ConductorProperties properties_;
|
||||
|
||||
// methodes privees
|
||||
void buildInterface();
|
||||
void buildConnections();
|
||||
void destroyConnections();
|
||||
};
|
||||
#endif
|
||||
521
sources/conductorsegment.cpp
Normal file
521
sources/conductorsegment.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "conductorsegment.h"
|
||||
#include <QDebug>
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param p1 Le point
|
||||
@param p2
|
||||
@param cs1 Le segment precedent
|
||||
@param cs2 Le segment suivant
|
||||
*/
|
||||
ConductorSegment::ConductorSegment(
|
||||
const QPointF &p1,
|
||||
const QPointF &p2,
|
||||
ConductorSegment *cs1,
|
||||
ConductorSegment *cs2
|
||||
) :
|
||||
point1(p1),
|
||||
point2(p2)
|
||||
{
|
||||
setPreviousSegment(cs1);
|
||||
setNextSegment(cs2);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur - Relie le segment precedent au suivant
|
||||
*/
|
||||
ConductorSegment::~ConductorSegment() {
|
||||
if (hasPreviousSegment()) previousSegment() -> setNextSegment(nextSegment());
|
||||
if (hasNextSegment()) nextSegment() -> setPreviousSegment(previousSegment());
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir s'il est possible de deplacer le premier point du segment
|
||||
sans creer d'incoherence. La valeur du mouvement maximum qu'il est possible de faire
|
||||
sans incoherence est stockee dans le second parametre.
|
||||
@param asked_dx La valeur du mouvement demande
|
||||
@param possible_dx La valeur du mouvement possible (au maximum)
|
||||
@return true si le mouvement est possible ; false s'il doit etre limite
|
||||
*/
|
||||
bool ConductorSegment::canMove1stPointX(const qreal &asked_dx, qreal &possible_dx) const {
|
||||
|
||||
Q_ASSERT_X(isVertical(), "ConductorSegment::canMove1stPointX", "segment non vertical");
|
||||
|
||||
/// On ne bouge jamais le premier point d'un segment statique.
|
||||
if (isStatic()) {
|
||||
possible_dx = 0.0;
|
||||
return(false);
|
||||
}
|
||||
// a ce stade, on a forcement un segment precedent
|
||||
|
||||
/// Si le segment precedent n'est pas statique, le mouvement est possible.
|
||||
if (previous_segment -> hasPreviousSegment()) {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment precedent est forcement statique
|
||||
|
||||
/// Si le segment precedent est vertical, le mouvement est possible :
|
||||
/// il induira la creation d'un segment horizontal supplementaire.
|
||||
if (previous_segment -> isVertical()) {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment precedent est forcement horizontal
|
||||
|
||||
// recupere quelques donnees
|
||||
qreal prev_segment_first_x = previous_segment -> point1.x();
|
||||
qreal first_x = point1.x();
|
||||
|
||||
/// Il se peut que le mouvement doive etre limite de facon a ce
|
||||
/// que le segment statique conserve une taille minimale.
|
||||
if (previous_segment -> length() > 0.0) {
|
||||
if (first_x + asked_dx < prev_segment_first_x + 12.0) {
|
||||
possible_dx = -first_x + prev_segment_first_x + 12.0;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
} else {
|
||||
if (first_x + asked_dx >= prev_segment_first_x - 12.0) {
|
||||
possible_dx = prev_segment_first_x - 12.0 - first_x;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir s'il est possible de deplacer le second point du segment
|
||||
sans creer d'incoherence. La valeur du mouvement maximum qu'il est possible de faire
|
||||
sans incoherence est stockee dans le second parametre.
|
||||
@param asked_dx La valeur du mouvement demande
|
||||
@param possible_dx La valeur du mouvement possible (au maximum)
|
||||
@return true si le mouvement est possible ; false s'il doit etre limite
|
||||
*/
|
||||
bool ConductorSegment::canMove2ndPointX(const qreal &asked_dx, qreal &possible_dx) const {
|
||||
|
||||
Q_ASSERT_X(isVertical(), "ConductorSegment::canMove2ndPointX", "segment non vertical");
|
||||
|
||||
/// On ne modifie jamais l'abscisse du second point d'un segment statique.
|
||||
if (isStatic()) {
|
||||
possible_dx = 0.0;
|
||||
return(false);
|
||||
}
|
||||
// a ce stade, on a forcement un segment suivant
|
||||
|
||||
/// Si le segment suivant n'est pas statique, le mouvement est possible.
|
||||
if (next_segment -> hasNextSegment()) {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment suivant est forcement statique
|
||||
|
||||
/// Si le segment suivant est vertical, le mouvement est possible :
|
||||
/// il induira la creation d'un segment horizontal supplementaire.
|
||||
if (next_segment -> isVertical()) {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment suivant est forcement horizontal
|
||||
|
||||
// recupere quelques donnees
|
||||
qreal next_segment_second_x = next_segment -> point2.x();
|
||||
qreal second_x = point2.x();
|
||||
|
||||
/// Il se peut que le mouvement doive etre limite de facon a ce
|
||||
/// que le segment statique conserve une taille minimale.
|
||||
if (next_segment -> length() < 0.0) {
|
||||
if (second_x + asked_dx < next_segment_second_x + 12.0) {
|
||||
possible_dx = -second_x + next_segment_second_x + 12.0;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
} else {
|
||||
if (second_x + asked_dx >= next_segment_second_x - 12.0) {
|
||||
possible_dx = next_segment_second_x - 12.0 - second_x;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dx = asked_dx;
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir s'il est possible de deplacer le premier point du segment
|
||||
sans creer d'incoherence. La valeur du mouvement maximum qu'il est possible de faire
|
||||
sans incoherence est stockee dans le second parametre.
|
||||
@param asked_dy La valeur du mouvement demande
|
||||
@param possible_dy La valeur du mouvement possible (au maximum)
|
||||
@return true si le mouvement est possible ; false s'il doit etre limite
|
||||
*/
|
||||
bool ConductorSegment::canMove1stPointY(const qreal &asked_dy, qreal &possible_dy) const {
|
||||
|
||||
Q_ASSERT_X(isHorizontal(), "ConductorSegment::canMove1stPointY", "segment non horizontal");
|
||||
|
||||
/// On ne bouge jamais le premier point d'un segment statique.
|
||||
if (isStatic()) {
|
||||
possible_dy = 0.0;
|
||||
return(false);
|
||||
}
|
||||
// a ce stade, on a forcement un segment precedent
|
||||
|
||||
/// Si le segment precedent n'est pas statique, le mouvement est possible.
|
||||
if (previous_segment -> hasPreviousSegment()) {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment precedent est forcement statique
|
||||
|
||||
/// Si le segment precedent est horizontal, le mouvement est possible :
|
||||
/// il induira la creation d'un segment vertical supplementaire.
|
||||
if (previous_segment -> isHorizontal()) {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment precedent est forcement vertical
|
||||
|
||||
// recupere quelques donnees
|
||||
qreal prev_segment_first_y = previous_segment -> point1.y();
|
||||
qreal first_y = point1.y();
|
||||
|
||||
/// Il se peut que le mouvement doive etre limite de facon a ce
|
||||
/// que le segment statique conserve une taille minimale.
|
||||
if (previous_segment -> length() > 0.0) {
|
||||
if (first_y + asked_dy < prev_segment_first_y + 12.0) {
|
||||
possible_dy = -first_y + prev_segment_first_y + 12.0;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
} else {
|
||||
if (first_y + asked_dy >= prev_segment_first_y - 12.0) {
|
||||
possible_dy = prev_segment_first_y - 12.0 - first_y;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir s'il est possible de deplacer le second point du segment
|
||||
sans creer d'incoherence. La valeur du mouvement maximum qu'il est possible de faire
|
||||
sans incoherence est stockee dans le second parametre.
|
||||
@param asked_dy La valeur du mouvement demande
|
||||
@param possible_dy La valeur du mouvement possible (au maximum)
|
||||
@return true si le mouvement est possible ; false s'il doit etre limite
|
||||
*/
|
||||
bool ConductorSegment::canMove2ndPointY(const qreal &asked_dy, qreal &possible_dy) const {
|
||||
|
||||
Q_ASSERT_X(isHorizontal(), "ConductorSegment::canMove2ndPointY", "segment non horizontal");
|
||||
|
||||
/// On ne modifie jamais l'abscisse du second point d'un segment statique.
|
||||
if (isStatic()) {
|
||||
possible_dy = 0.0;
|
||||
return(false);
|
||||
}
|
||||
// a ce stade, on a forcement un segment suivant
|
||||
|
||||
/// Si le segment suivant n'est pas statique, le mouvement est possible.
|
||||
if (next_segment -> hasNextSegment()) {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment suivant est forcement statique
|
||||
|
||||
/// Si le segment suivant est horizontal, le mouvement est possible :
|
||||
/// il induira la creation d'un segment vertical supplementaire.
|
||||
if (next_segment -> isHorizontal()) {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
// a ce stade, le segment suivant est forcement vertical
|
||||
|
||||
// recupere quelques donnees
|
||||
qreal next_segment_second_y = next_segment -> point2.y();
|
||||
qreal second_y = point2.y();
|
||||
|
||||
/// Il se peut que le mouvement doive etre limite de facon a ce
|
||||
/// que le segment statique conserve une taille minimale.
|
||||
if (next_segment -> length() < 0.0) {
|
||||
if (second_y + asked_dy < next_segment_second_y + 12.0) {
|
||||
possible_dy = -second_y + next_segment_second_y + 12.0;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
} else {
|
||||
if (second_y + asked_dy >= next_segment_second_y - 12.0) {
|
||||
possible_dy = next_segment_second_y - 12.0 - second_y;
|
||||
return(false);
|
||||
} else {
|
||||
possible_dy = asked_dy;
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements sur l'axe horizontal
|
||||
@param dx taille du deplacement en pixels
|
||||
*/
|
||||
void ConductorSegment::moveX(const qreal &dx) {
|
||||
if (isHorizontal()) return;
|
||||
Q_ASSERT_X(isVertical(), "ConductorSegment::moveX", "segment non vertical");
|
||||
|
||||
bool has_prev_segment = hasPreviousSegment();
|
||||
bool has_next_segment = hasNextSegment();
|
||||
|
||||
if (isStatic()) return;
|
||||
|
||||
// determine si le mouvement demande doit etre limite et, le cas echeant, a quelle valeur il faut le limiter
|
||||
qreal real_dx_for_1st_point = 0.0;
|
||||
qreal real_dx_for_2nd_point = 0.0;
|
||||
canMove1stPointX(dx, real_dx_for_1st_point);
|
||||
canMove2ndPointX(dx, real_dx_for_2nd_point);
|
||||
|
||||
qreal final_movement = (dx <= 0.0) ? qMax(real_dx_for_1st_point, real_dx_for_2nd_point) : qMin(real_dx_for_1st_point, real_dx_for_2nd_point);
|
||||
|
||||
// applique le mouvement au premier point
|
||||
if (has_prev_segment) {
|
||||
point1.rx() += final_movement;
|
||||
if (previous_segment -> isFirstSegment()) {
|
||||
new ConductorSegment(
|
||||
previous_segment -> point2,
|
||||
point1,
|
||||
previous_segment,
|
||||
this
|
||||
);
|
||||
} else previous_segment -> setSecondPoint(point1);
|
||||
}
|
||||
|
||||
// applique le mouvement au second point
|
||||
if (has_next_segment) {
|
||||
point2.rx() += final_movement;
|
||||
if (next_segment -> isLastSegment()) {
|
||||
new ConductorSegment(
|
||||
point2,
|
||||
next_segment -> point1,
|
||||
this,
|
||||
next_segment
|
||||
);
|
||||
} else next_segment -> setFirstPoint(point2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements sur l'axe vertical
|
||||
@param dy taille du deplacement en pixels
|
||||
*/
|
||||
void ConductorSegment::moveY(const qreal &dy) {
|
||||
if (isVertical()) return;
|
||||
Q_ASSERT_X(isHorizontal(), "ConductorSegment::moveY", "segment non horizontal");
|
||||
|
||||
bool has_prev_segment = hasPreviousSegment();
|
||||
bool has_next_segment = hasNextSegment();
|
||||
|
||||
if (isStatic()) return;
|
||||
|
||||
// determine si le mouvement demande doit etre limite et, le cas echeant, a quelle valeur il faut le limiter
|
||||
qreal real_dy_for_1st_point = 0.0;
|
||||
qreal real_dy_for_2nd_point = 0.0;
|
||||
canMove1stPointY(dy, real_dy_for_1st_point);
|
||||
canMove2ndPointY(dy, real_dy_for_2nd_point);
|
||||
|
||||
qreal final_movement = (dy <= 0.0) ? qMax(real_dy_for_1st_point, real_dy_for_2nd_point) : qMin(real_dy_for_1st_point, real_dy_for_2nd_point);
|
||||
|
||||
// applique le mouvement au premier point
|
||||
if (has_prev_segment) {
|
||||
point1.ry() += final_movement;
|
||||
if (previous_segment -> isFirstSegment()) {
|
||||
new ConductorSegment(
|
||||
previous_segment -> point2,
|
||||
point1,
|
||||
previous_segment,
|
||||
this
|
||||
);
|
||||
} else previous_segment -> setSecondPoint(point1);
|
||||
}
|
||||
|
||||
// applique le mouvement au second point
|
||||
if (has_next_segment) {
|
||||
point2.ry() += final_movement;
|
||||
if (next_segment -> isLastSegment()) {
|
||||
new ConductorSegment(
|
||||
point2,
|
||||
next_segment -> point1,
|
||||
this,
|
||||
next_segment
|
||||
);
|
||||
} else next_segment -> setFirstPoint(point2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Change le segment precedent
|
||||
@param ps Le nouveau segment precedent
|
||||
*/
|
||||
void ConductorSegment::setPreviousSegment(ConductorSegment *ps) {
|
||||
previous_segment = ps;
|
||||
if (hasPreviousSegment()) {
|
||||
if (previousSegment() -> nextSegment() != this) previousSegment() -> setNextSegment(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Change le segment suivant
|
||||
@param ns Le nouveau segment suivant
|
||||
*/
|
||||
void ConductorSegment::setNextSegment(ConductorSegment *ns) {
|
||||
next_segment = ns;
|
||||
if (hasNextSegment()) {
|
||||
if (nextSegment() -> previousSegment() != this) nextSegment() -> setPreviousSegment(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// @return true si ce segment est un segment statique, cad un segment relie a une borne
|
||||
bool ConductorSegment::isStatic() const {
|
||||
return(isFirstSegment() || isLastSegment());
|
||||
}
|
||||
|
||||
/// @return true si ce segment est le premier du conducteur
|
||||
bool ConductorSegment::isFirstSegment() const {
|
||||
return(!hasPreviousSegment());
|
||||
}
|
||||
|
||||
/// @return true si ce segment est le dernier du conducteur
|
||||
bool ConductorSegment::isLastSegment() const {
|
||||
return(!hasNextSegment());
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le segment precedent
|
||||
*/
|
||||
ConductorSegment *ConductorSegment::previousSegment() const {
|
||||
return(previous_segment);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le segment suivant
|
||||
*/
|
||||
ConductorSegment *ConductorSegment::nextSegment() const {
|
||||
return(next_segment);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le segment est vertical, false sinon
|
||||
*/
|
||||
bool ConductorSegment::isVertical() const {
|
||||
return(point1.x() == point2.x());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le segment est horizontal, false sinon
|
||||
*/
|
||||
bool ConductorSegment::isHorizontal() const {
|
||||
return(point1.y() == point2.y());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le premier point du segment
|
||||
*/
|
||||
QPointF ConductorSegment::firstPoint() const {
|
||||
return(point1);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le second point du segment
|
||||
*/
|
||||
QPointF ConductorSegment::secondPoint() const {
|
||||
return(point2);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de changer la position du premier point du segment
|
||||
@param p La nouvelle position du premier point
|
||||
*/
|
||||
void ConductorSegment::setFirstPoint(const QPointF &p) {
|
||||
point1 = p;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de changer la position du second point du segment
|
||||
@param p La nouvelle position du second point
|
||||
*/
|
||||
void ConductorSegment::setSecondPoint(const QPointF &p) {
|
||||
point2 = p;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le segment a un segment precedent, false sinon
|
||||
*/
|
||||
bool ConductorSegment::hasPreviousSegment() const {
|
||||
return(previous_segment != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le segment a un segment suivant, false sinon
|
||||
*/
|
||||
bool ConductorSegment::hasNextSegment() const {
|
||||
return(next_segment != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le centre du rectangle delimitant le conducteur
|
||||
*/
|
||||
QPointF ConductorSegment::middle() const {
|
||||
return(
|
||||
QPointF(
|
||||
(point1.x() + point2.x()) / 2.0,
|
||||
(point1.y() + point2.y()) / 2.0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@return La longueur du conducteur
|
||||
*/
|
||||
qreal ConductorSegment::length() const {
|
||||
if (isHorizontal()) {
|
||||
return(secondPoint().x() - firstPoint().x());
|
||||
} else {
|
||||
return(secondPoint().y() - firstPoint().y());
|
||||
}
|
||||
}
|
||||
|
||||
/// @return QET::Horizontal si le segment est horizontal, QET::Vertical sinon
|
||||
QET::ConductorSegmentType ConductorSegment::type() const {
|
||||
return(isHorizontal() ? QET::Horizontal : QET::Vertical);
|
||||
}
|
||||
|
||||
/// @return true si les deux points constituant le segment sont egaux
|
||||
bool ConductorSegment::isPoint() const {
|
||||
return(point1 == point2);
|
||||
}
|
||||
70
sources/conductorsegment.h
Normal file
70
sources/conductorsegment.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_SEGMENT_H
|
||||
#define CONDUCTOR_SEGMENT_H
|
||||
#include <QPointF>
|
||||
#include "qet.h"
|
||||
/**
|
||||
Cette classe represente un segment de conducteur.
|
||||
*/
|
||||
class ConductorSegment {
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ConductorSegment(const QPointF &, const QPointF &, ConductorSegment * = NULL, ConductorSegment * = NULL);
|
||||
virtual ~ConductorSegment();
|
||||
|
||||
private:
|
||||
ConductorSegment(const ConductorSegment &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ConductorSegment *previous_segment;
|
||||
ConductorSegment *next_segment;
|
||||
QPointF point1;
|
||||
QPointF point2;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void moveX(const qreal &);
|
||||
void moveY(const qreal &);
|
||||
ConductorSegment *previousSegment() const;
|
||||
ConductorSegment *nextSegment() const;
|
||||
bool hasPreviousSegment() const;
|
||||
bool hasNextSegment() const;
|
||||
void setPreviousSegment(ConductorSegment *);
|
||||
void setNextSegment(ConductorSegment *);
|
||||
bool isStatic() const;
|
||||
bool isFirstSegment() const;
|
||||
bool isLastSegment() const;
|
||||
QPointF firstPoint() const;
|
||||
QPointF secondPoint() const;
|
||||
void setFirstPoint(const QPointF &);
|
||||
void setSecondPoint(const QPointF &);
|
||||
QPointF middle() const;
|
||||
bool isHorizontal() const;
|
||||
bool isVertical() const;
|
||||
QET::ConductorSegmentType type() const;
|
||||
qreal length() const;
|
||||
bool isPoint() const;
|
||||
bool canMove1stPointX(const qreal &, qreal &) const;
|
||||
bool canMove2ndPointX(const qreal &, qreal &) const;
|
||||
bool canMove1stPointY(const qreal &, qreal &) const;
|
||||
bool canMove2ndPointY(const qreal &, qreal &) const;
|
||||
};
|
||||
#endif
|
||||
61
sources/conductorsegmentprofile.h
Normal file
61
sources/conductorsegmentprofile.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONDUCTOR_SEGMENT_PROFILE_H
|
||||
#define CONDUCTOR_SEGMENT_PROFILE_H
|
||||
#include <QtCore>
|
||||
#include "conductorsegment.h"
|
||||
/**
|
||||
Cette classe contient le profil (= les caracteristiques essentielles) d'un
|
||||
segment de conducteur.
|
||||
*/
|
||||
class ConductorSegmentProfile {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
@param l longueur du segment
|
||||
@param ori true si le segment est horizontal, false s'il est vertical
|
||||
*/
|
||||
ConductorSegmentProfile(qreal l, bool ori = true) :
|
||||
length(l),
|
||||
isHorizontal(ori)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param segment ConductorSegment dont il faut extraire le profil
|
||||
*/
|
||||
ConductorSegmentProfile(ConductorSegment *segment) :
|
||||
length(segment -> length()),
|
||||
isHorizontal(segment -> isHorizontal())
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
virtual ~ConductorSegmentProfile() {
|
||||
}
|
||||
|
||||
// attributs
|
||||
public:
|
||||
/// longueur du segment
|
||||
qreal length;
|
||||
/// orientation du segment
|
||||
bool isHorizontal;
|
||||
};
|
||||
#endif
|
||||
105
sources/configdialog.cpp
Normal file
105
sources/configdialog.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "configdialog.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
|
||||
|
||||
setWindowTitle(tr("Configurer QElectroTech"));
|
||||
|
||||
// liste des pages
|
||||
pages_list = new QListWidget();
|
||||
pages_list -> setViewMode(QListView::IconMode);
|
||||
pages_list -> setIconSize(QSize(48, 48));
|
||||
pages_list -> setMovement(QListView::Static);
|
||||
pages_list -> setMinimumWidth(135);
|
||||
pages_list -> setMaximumWidth(135);
|
||||
pages_list -> setSpacing(4);
|
||||
|
||||
// pages
|
||||
pages_widget = new QStackedWidget();
|
||||
addPage(new NewDiagramPage());
|
||||
buildPagesList();
|
||||
|
||||
// boutons
|
||||
buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
|
||||
|
||||
// layouts
|
||||
QHBoxLayout *hlayout1 = new QHBoxLayout();
|
||||
hlayout1 -> addWidget(pages_list);
|
||||
hlayout1 -> addWidget(pages_widget);
|
||||
|
||||
QVBoxLayout *vlayout1 = new QVBoxLayout();
|
||||
vlayout1 -> addLayout(hlayout1);
|
||||
vlayout1 -> addWidget(buttons);
|
||||
setLayout(vlayout1);
|
||||
|
||||
// connexion signaux / slots
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(applyConf()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
connect(pages_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*)));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ConfigDialog::~ConfigDialog() {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements de page dans le dialogue de configuration
|
||||
*/
|
||||
void ConfigDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) {
|
||||
if (!current) current = previous;
|
||||
pages_widget -> setCurrentIndex(pages_list -> row(current));
|
||||
}
|
||||
|
||||
/**
|
||||
Construit la liste des pages sur la gauche
|
||||
*/
|
||||
void ConfigDialog::buildPagesList() {
|
||||
pages_list -> clear();
|
||||
foreach(ConfigPage *page, pages) {
|
||||
QListWidgetItem *new_button = new QListWidgetItem(pages_list);
|
||||
new_button -> setIcon(page -> icon());
|
||||
new_button -> setText(page -> title());
|
||||
new_button -> setTextAlignment(Qt::AlignHCenter);
|
||||
new_button -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Applique la configuration de toutes les pages
|
||||
*/
|
||||
void ConfigDialog::applyConf() {
|
||||
foreach(ConfigPage *page, pages) {
|
||||
page -> applyConf();
|
||||
}
|
||||
accept();
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute une page au dialogue de configuration
|
||||
*/
|
||||
void ConfigDialog::addPage(ConfigPage *page) {
|
||||
if (!page || pages.contains(page)) return;
|
||||
pages << page;
|
||||
pages_widget -> addWidget(page);
|
||||
}
|
||||
56
sources/configdialog.h
Normal file
56
sources/configdialog.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONFIG_DIALOG_H
|
||||
#define CONFIG_DIALOG_H
|
||||
#include <QDialog>
|
||||
#include "configpages.h"
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class QStackedWidget;
|
||||
class QDialogButtonBox;
|
||||
/**
|
||||
Cette classe represente le dialogue de configuration de QElectroTech.
|
||||
Il s'agit d'un dialogue affichant des "pages de configuration".
|
||||
Chaque page de configuration doit fournir une icone et un titre.
|
||||
*/
|
||||
class ConfigDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ConfigDialog(QWidget * = 0);
|
||||
virtual ~ConfigDialog();
|
||||
private:
|
||||
ConfigDialog(const ConfigDialog &);
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void changePage(QListWidgetItem *, QListWidgetItem *);
|
||||
void applyConf();
|
||||
void addPage(ConfigPage *);
|
||||
|
||||
private:
|
||||
void buildPagesList();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QListWidget *pages_list;
|
||||
QStackedWidget *pages_widget;
|
||||
QDialogButtonBox *buttons;
|
||||
QList<ConfigPage *> pages;
|
||||
};
|
||||
#endif
|
||||
139
sources/configpages.cpp
Normal file
139
sources/configpages.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "configpages.h"
|
||||
#include "conductorpropertieswidget.h"
|
||||
#include "insetpropertieswidget.h"
|
||||
#include "qetapp.h"
|
||||
#include "qetdiagrameditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
NewDiagramPage::NewDiagramPage(QWidget *parent) : ConfigPage(parent) {
|
||||
|
||||
// acces a la configuration de QElectroTech
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
// recupere les dimensions du schema
|
||||
int columns_count_value = settings.value("diagrameditor/defaultcols", 15).toInt();
|
||||
int columns_width_value = qRound(settings.value("diagrameditor/defaultcolsize", 50.0).toDouble());
|
||||
int columns_height_value = qRound(settings.value("diagrameditor/defaultheight", 500.0).toDouble());
|
||||
|
||||
QVBoxLayout *vlayout1 = new QVBoxLayout();
|
||||
|
||||
QLabel *title = new QLabel(tr("Nouveau sch\351ma"));
|
||||
vlayout1 -> addWidget(title);
|
||||
|
||||
QFrame *horiz_line = new QFrame();
|
||||
horiz_line -> setFrameShape(QFrame::HLine);
|
||||
vlayout1 -> addWidget(horiz_line);
|
||||
|
||||
QHBoxLayout *hlayout1 = new QHBoxLayout();
|
||||
QVBoxLayout *vlayout2 = new QVBoxLayout();
|
||||
|
||||
QGroupBox *diagram_size_box = new QGroupBox(tr("Dimensions du sch\351ma"));
|
||||
diagram_size_box -> setMinimumWidth(300);
|
||||
QGridLayout *diagram_size_box_layout = new QGridLayout(diagram_size_box);
|
||||
|
||||
QLabel *ds1 = new QLabel(tr("Colonnes :"));
|
||||
|
||||
columns_count = new QSpinBox(diagram_size_box);
|
||||
columns_count -> setMinimum(3); /// @todo methode statique pour recuperer ca
|
||||
columns_count -> setValue(columns_count_value);
|
||||
|
||||
columns_width = new QSpinBox(diagram_size_box);
|
||||
columns_width -> setMinimum(1);
|
||||
columns_width -> setSingleStep(10);
|
||||
columns_width -> setValue(columns_width_value);
|
||||
columns_width -> setPrefix(tr("\327"));
|
||||
columns_width -> setSuffix(tr("px"));
|
||||
|
||||
QLabel *ds2 = new QLabel(tr("Hauteur :"));
|
||||
|
||||
columns_height = new QSpinBox(diagram_size_box);
|
||||
columns_height -> setRange(80, 10000); /// @todo methode statique pour recuperer ca
|
||||
columns_height -> setSingleStep(80);
|
||||
columns_height -> setValue(columns_height_value);
|
||||
|
||||
diagram_size_box_layout -> addWidget(ds1, 0, 0);
|
||||
diagram_size_box_layout -> addWidget(columns_count, 0, 1);
|
||||
diagram_size_box_layout -> addWidget(columns_width, 0, 2);
|
||||
diagram_size_box_layout -> addWidget(ds2, 1, 0);
|
||||
diagram_size_box_layout -> addWidget(columns_height, 1, 1);
|
||||
|
||||
ipw = new InsetPropertiesWidget(QETDiagramEditor::defaultInsetProperties(), true, this);
|
||||
|
||||
// proprietes par defaut des conducteurs
|
||||
ConductorProperties cp;
|
||||
cp.fromSettings(settings, "diagrameditor/defaultconductor");
|
||||
cpw = new ConductorPropertiesWidget(cp);
|
||||
|
||||
vlayout2 -> addWidget(diagram_size_box);
|
||||
vlayout2 -> addWidget(ipw);
|
||||
hlayout1 -> addLayout(vlayout2);
|
||||
hlayout1 -> addWidget(cpw);
|
||||
vlayout1 -> addLayout(hlayout1);
|
||||
vlayout1 -> addStretch(1);
|
||||
hlayout1 -> setAlignment(cpw, Qt::AlignTop);
|
||||
setLayout(vlayout1);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
NewDiagramPage::~NewDiagramPage() {
|
||||
}
|
||||
|
||||
/**
|
||||
Applique la configuration de cette page
|
||||
*/
|
||||
void NewDiagramPage::applyConf() {
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
// dimensions des nouveaux schemas
|
||||
settings.setValue("diagrameditor/defaultcols", columns_count -> value());
|
||||
settings.setValue("diagrameditor/defaultcolsize", columns_width -> value());
|
||||
settings.setValue("diagrameditor/defaultheight", columns_height -> value());
|
||||
|
||||
// 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);
|
||||
|
||||
// proprietes par defaut des conducteurs
|
||||
cpw -> conductorProperties().toSettings(settings, "diagrameditor/defaultconductor");
|
||||
}
|
||||
|
||||
/// @return l'icone de cette page
|
||||
QIcon NewDiagramPage::icon() const {
|
||||
return(QIcon(":/ico/conf_new_diagram.png"));
|
||||
}
|
||||
|
||||
/// @return le titre de cette page
|
||||
QString NewDiagramPage::title() const {
|
||||
return(tr("Nouveau sch\351ma"));
|
||||
}
|
||||
72
sources/configpages.h
Normal file
72
sources/configpages.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 CONFIG_PAGES_H
|
||||
#define CONFIG_PAGES_H
|
||||
#include <QtGui>
|
||||
class ConductorPropertiesWidget;
|
||||
class InsetPropertiesWidget;
|
||||
|
||||
/**
|
||||
Cette classe abstraite contient les methodes que toutes les pages de
|
||||
configuration doivent implementer.
|
||||
*/
|
||||
class ConfigPage : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ConfigPage(QWidget *parent) : QWidget(parent) {};
|
||||
/// Destructeur
|
||||
virtual ~ConfigPage() {};
|
||||
/// Applique la configuration saisie par l'utilisateur dans la page de configuration
|
||||
virtual void applyConf() = 0;
|
||||
/// @return le titre de la page de configuration
|
||||
virtual QString title() const = 0;
|
||||
/// @return l'icone de la page de configuration
|
||||
virtual QIcon icon() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente la page de configuration des nouveaux schemas.
|
||||
*/
|
||||
class NewDiagramPage : public ConfigPage {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
NewDiagramPage(QWidget * = 0);
|
||||
virtual ~NewDiagramPage();
|
||||
private:
|
||||
NewDiagramPage(const NewDiagramPage &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void applyConf();
|
||||
QString title() const;
|
||||
QIcon icon() const;
|
||||
|
||||
// attributs
|
||||
public:
|
||||
QSpinBox *columns_count; ///< Widget d'edition du nombre par defaut de colonnes
|
||||
QSpinBox *columns_width; ///< Widget d'edition de la largeur par defaut des colonnes
|
||||
QSpinBox *columns_height; ///< Widget d'edition de la hauteur par defaut des colonnes
|
||||
InsetPropertiesWidget *ipw; ///< Widget d'edition des proprietes par defaut du cartouche
|
||||
ConductorPropertiesWidget *cpw; ///< Widget d'edition des proprietes par defaut des conducteurs
|
||||
};
|
||||
#endif
|
||||
565
sources/customelement.cpp
Normal file
565
sources/customelement.cpp
Normal file
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "customelement.h"
|
||||
#include "elementtextitem.h"
|
||||
#include "diagram.h"
|
||||
#include "qetapp.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
|
||||
@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
|
||||
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
|
||||
- 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;
|
||||
return;
|
||||
}
|
||||
|
||||
// le fichier doit etre lisible
|
||||
QFile fichier(nomfichier);
|
||||
if (!fichier.open(QIODevice::ReadOnly)) {
|
||||
if (etat != NULL) *etat = 2;
|
||||
elmt_etat = 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;
|
||||
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;
|
||||
}
|
||||
|
||||
// verifie basiquement que la version actuelle est capable de lire ce fichier
|
||||
if (racine.hasAttribute("version")) {
|
||||
bool conv_ok;
|
||||
qreal element_version = racine.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"
|
||||
" ult\351rieure de QElectroTech.")
|
||||
) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
) {
|
||||
if (etat != NULL) *etat = 5;
|
||||
elmt_etat = 5;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
// la definition est supposee avoir des enfants
|
||||
if (racine.firstChild().isNull()) {
|
||||
if (etat != NULL) *etat = 6;
|
||||
elmt_etat = 6;
|
||||
return;
|
||||
}
|
||||
|
||||
// initialisation du QPainter (pour dessiner l'element)
|
||||
QPainter qp;
|
||||
qp.begin(&dessin);
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.0);
|
||||
t.setJoinStyle(Qt::BevelJoin);
|
||||
qp.setPen(t);
|
||||
|
||||
// extrait les noms de la definition XML
|
||||
names.fromXml(racine);
|
||||
setToolTip(nom());
|
||||
|
||||
// parcours des enfants de la definition : parties du dessin
|
||||
int nb_elements_parses = 0;
|
||||
for (QDomNode node = racine.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
|
||||
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;
|
||||
else {
|
||||
if (etat != NULL) *etat = 7;
|
||||
elmt_etat = 7;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fin du dessin
|
||||
qp.end();
|
||||
|
||||
// il doit y avoir au moins un element charge
|
||||
if (!nb_elements_parses) {
|
||||
if (etat != NULL) *etat = 8;
|
||||
elmt_etat = 8;
|
||||
return;
|
||||
}
|
||||
|
||||
// fermeture du fichier
|
||||
fichier.close();
|
||||
|
||||
if (etat != NULL) *etat = 0;
|
||||
elmt_etat = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
CustomElement::~CustomElement() {
|
||||
}
|
||||
|
||||
/// @return la liste des bornes de cet element
|
||||
QList<Terminal *> CustomElement::terminals() const {
|
||||
return(list_terminals);
|
||||
}
|
||||
|
||||
/// @return la liste des conducteurs rattaches a cet element
|
||||
QList<Conductor *> CustomElement::conductors() const {
|
||||
QList<Conductor *> conductors;
|
||||
foreach(Terminal *t, list_terminals) conductors << t -> conductors();
|
||||
return(conductors);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nombre de bornes que l'element possede
|
||||
*/
|
||||
int CustomElement::nbTerminals() const {
|
||||
return(list_terminals.size());
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le composant sur le Diagram
|
||||
@param qp Le QPainter a utiliser pour dessiner l'element
|
||||
@param options Les options graphiques
|
||||
*/
|
||||
void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *) {
|
||||
dessin.play(qp);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse et prend en compte un element XML decrivant une partie du dessin
|
||||
de l'element perso. Si l'analyse reussit, la partie est ajoutee au dessin.
|
||||
Cette partie peut etre une borne, une ligne, une ellipse, un cercle, un arc
|
||||
de cercle ou un polygone. Cette methode renvoie false si l'analyse
|
||||
d'une de ces formes echoue. Si l'analyse reussit ou dans le cas d'une forme
|
||||
inconnue, cette methode renvoie true. A l'exception des bornes, toutes les
|
||||
formes peuvent avoir un attribut style. @see setPainterStyle
|
||||
@param e L'element XML a analyser
|
||||
@param qp Le QPainter a utiliser pour dessiner l'element perso
|
||||
@param s Le schema sur lequel sera affiche l'element perso
|
||||
@return true si l'analyse reussit, false sinon
|
||||
*/
|
||||
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() == "ellipse") return(parseEllipse(e, qp));
|
||||
else if (e.tagName() == "circle") return(parseCircle(e, qp));
|
||||
else if (e.tagName() == "arc") return(parseArc(e, qp));
|
||||
else if (e.tagName() == "polygon") return(parsePolygon(e, qp));
|
||||
else if (e.tagName() == "text") return(parseText(e, qp));
|
||||
else if (e.tagName() == "input") return(parseInput(e));
|
||||
else return(true); // on n'est pas chiant, on ignore l'element inconnu
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer une ligne. Si l'analyse
|
||||
reussit, la ligne est ajoutee au dessin.
|
||||
La ligne est definie par les attributs suivants :
|
||||
- x1, y1 : reels, coordonnees d'une extremite de la ligne
|
||||
- x2, y2 : reels, coordonnees de l'autre extremite de la ligne
|
||||
|
||||
@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::parseLine(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence et la validite des attributs obligatoires
|
||||
double x1, y1, x2, y2;
|
||||
if (!QET::attributeIsAReal(e, QString("x1"), &x1)) return(false);
|
||||
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);
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.drawLine(QLineF(x1, y1, x2, y2));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un cercle. Si l'analyse
|
||||
reussit, le cercle est ajoute au dessin.
|
||||
Le cercle est defini par les attributs suivants :
|
||||
- x : abscisse du coin superieur gauche de la quadrature du cercle
|
||||
- y : ordonnee du coin superieur gauche de la quadrature du cercle
|
||||
- diameter : diametre du cercle
|
||||
|
||||
@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
|
||||
double cercle_x, cercle_y, cercle_r;
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &cercle_x)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &cercle_y)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("diameter"), &cercle_r)) return(false);
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.drawEllipse(QRectF(cercle_x, cercle_y, cercle_r, cercle_r));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer une ellipse. Si l'analyse
|
||||
reussit, l'ellipse est ajoutee au dessin.
|
||||
L'ellipse est definie par les attributs suivants :
|
||||
- x : abscisse du coin superieur gauche du rectangle dans lequel s'inscrit l'ellipse
|
||||
- y : ordonnee du coin superieur gauche du rectangle dans lequel s'inscrit l'ellipse
|
||||
- width : dimension de la diagonale horizontale de l'ellipse
|
||||
- height : dimension de la diagonale verticale de l'ellipse
|
||||
|
||||
@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
|
||||
double ellipse_x, ellipse_y, ellipse_l, ellipse_h;
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &ellipse_x)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &ellipse_y)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("width"), &ellipse_l)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("height"), &ellipse_h)) return(false);
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.drawEllipse(QRectF(ellipse_x, ellipse_y, ellipse_l, ellipse_h));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un arc de cercle. Si l'analyse
|
||||
reussit, l'arc de cercle est ajoute au dessin.
|
||||
L'arc de cercle est defini par les quatres parametres d'une ellipse (en fait
|
||||
l'ellipse dans laquelle s'inscrit l'arc de cercle) auxquels s'ajoutent les
|
||||
attributs suivants :
|
||||
- start : angle de depart : l'angle "0 degre" est a trois heures
|
||||
- angle : etendue (en degres) de l'arc de cercle ; une valeur positive
|
||||
va dans le sens contraire des aiguilles d'une montre
|
||||
|
||||
@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::parseArc(QDomElement &e, QPainter &qp) {
|
||||
// verifie la presence des attributs obligatoires
|
||||
double arc_x, arc_y, arc_l, arc_h, arc_s, arc_a;
|
||||
if (!QET::attributeIsAReal(e, QString("x"), &arc_x)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("y"), &arc_y)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("width"), &arc_l)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("height"), &arc_h)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("start"), &arc_s)) return(false);
|
||||
if (!QET::attributeIsAReal(e, QString("angle"), &arc_a)) return(false);
|
||||
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.drawArc(QRectF(arc_x, arc_y, arc_l, arc_h), (int)(arc_s * 16), (int)(arc_a * 16));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un polygone. Si l'analyse
|
||||
reussit, le polygone est ajoute au dessin.
|
||||
Le polygone est defini par une serie d'attributs x1, x2, ..., xn et autant
|
||||
d'attributs y1, y2, ..., yn representant les coordonnees des differents
|
||||
points du polygone.
|
||||
Il est possible d'obtenir un polygone non ferme en utilisant closed="false"
|
||||
@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::parsePolygon(QDomElement &e, QPainter &qp) {
|
||||
int i = 1;
|
||||
while(true) {
|
||||
if (QET::attributeIsAReal(e, QString("x%1").arg(i)) && QET::attributeIsAReal(e, QString("y%1").arg(i))) ++ i;
|
||||
else break;
|
||||
}
|
||||
if (i < 3) return(false);
|
||||
QPointF points[i-1];
|
||||
for (int j = 1 ; j < i ; ++ j) {
|
||||
points[j-1] = QPointF(
|
||||
e.attribute(QString("x%1").arg(j)).toDouble(),
|
||||
e.attribute(QString("y%1").arg(j)).toDouble()
|
||||
);
|
||||
}
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
if (e.attribute("closed") == "false") qp.drawPolyline(points, i-1);
|
||||
else qp.drawPolygon(points, i-1);
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un texte. Si l'analyse
|
||||
reussit, le texte est ajoute au dessin.
|
||||
Le texte est defini par une position, une chaine de caracteres et une
|
||||
taille.
|
||||
@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::parseText(QDomElement &e, QPainter &qp) {
|
||||
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) ||\
|
||||
!e.hasAttribute("text")
|
||||
) return(false);
|
||||
|
||||
qp.save();
|
||||
setPainterStyle(e, qp);
|
||||
qp.setFont(QFont(QString(QETApp::diagramTextsFont()), size));
|
||||
qp.drawText(QPointF(pos_x, pos_y), e.attribute("text"));
|
||||
qp.restore();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer un champ de texte editable par
|
||||
l'utilisateur. Si l'analyse reussit, le champ est ajoute au dessin.
|
||||
Le texte est defini par :
|
||||
- une position
|
||||
- une chaine de caracteres facultative utilisee comme valeur par defaut
|
||||
- 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
|
||||
*/
|
||||
bool 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);
|
||||
|
||||
ElementTextItem *eti = new ElementTextItem(e.attribute("text"), this);
|
||||
eti -> setPos(pos_x, pos_y);
|
||||
eti -> setOriginalPos(QPointF(pos_x, pos_y));
|
||||
if (e.attribute("rotate") == "true") eti -> setFollowParentRotations(true);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Analyse un element XML suppose representer une borne. Si l'analyse
|
||||
reussit, la borne est ajoutee a l'element.
|
||||
Une borne est definie par les attributs suivants :
|
||||
- x, y : coordonnees de la borne
|
||||
- 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
|
||||
*/
|
||||
bool 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 (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);
|
||||
}
|
||||
|
||||
/**
|
||||
Active / desactive l'antialiasing sur un QPainter
|
||||
@param qp Le QPainter a modifier
|
||||
@param aa Booleen a true pour activer l'antialiasing, a false pour le desactiver
|
||||
*/
|
||||
void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) {
|
||||
qp.setRenderHint(QPainter::Antialiasing, aa);
|
||||
qp.setRenderHint(QPainter::TextAntialiasing, aa);
|
||||
qp.setRenderHint(QPainter::SmoothPixmapTransform, aa);
|
||||
}
|
||||
|
||||
/**
|
||||
Verifie si l'attribut "orientation" de l'element XML e correspond bien a la
|
||||
syntaxe decrivant les orientations possibles pour un element.
|
||||
Cette syntaxe comprend exactement 4 lettres :
|
||||
- une pour le Nord
|
||||
- une pour l'Est
|
||||
- une pour le Sud
|
||||
- une pour l'Ouest
|
||||
|
||||
Pour chaque orientation, on indique si elle est :
|
||||
- l'orientation par defaut : d
|
||||
- une orientation autorisee : y
|
||||
- une orientation interdire : n
|
||||
|
||||
Exemple : "dnny" represente un element par defaut oriente vers le nord et qui
|
||||
peut etre oriente vers l'ouest mais pas vers le sud ou vers l'est.
|
||||
@param e Element XML
|
||||
@return true si l'attribut "orientation" est valide, false sinon
|
||||
*/
|
||||
bool CustomElement::validOrientationAttribute(QDomElement &e) {
|
||||
return(ori.fromString(e.attribute("orientation")));
|
||||
}
|
||||
|
||||
/**
|
||||
Applique les parametres de style definis dans l'attribut "style" de
|
||||
l'element XML e au QPainter qp
|
||||
Les styles possibles sont :
|
||||
- line-style : style du trait
|
||||
- dashed : trait en pointilles
|
||||
- normal : trait plein [par defaut]
|
||||
- line-weight : epaiseur du trait
|
||||
- thin : trait fin
|
||||
- normal : trait d'epaisseur 1 [par defaut]
|
||||
- filling : remplissage de la forme
|
||||
- white : remplissage blanc
|
||||
- black : remplissage noir
|
||||
- none : pas de remplissage [par defaut]
|
||||
- color : couleur du trait et du texte
|
||||
- white : trait noir [par defaut]
|
||||
- black : trait blanc
|
||||
|
||||
Les autres valeurs ne sont pas prises en compte.
|
||||
@param e L'element XML a parser
|
||||
@param qp Le QPainter a modifier en fonction des styles
|
||||
*/
|
||||
void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) {
|
||||
// recupere le QPen et la QBrush du QPainter
|
||||
QPen pen = qp.pen();
|
||||
QBrush brush = qp.brush();
|
||||
|
||||
// attributs par defaut
|
||||
pen.setJoinStyle(Qt::BevelJoin);
|
||||
pen.setCapStyle(Qt::SquareCap);
|
||||
pen.setColor(Qt::black);
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
pen.setWidthF(1.0);
|
||||
brush.setStyle(Qt::NoBrush);
|
||||
|
||||
// recupere la liste des couples style / valeur
|
||||
QStringList styles = e.attribute("style").split(";", QString::SkipEmptyParts);
|
||||
|
||||
// agit sur le QPen et la QBrush en fonction des valeurs rencontrees
|
||||
QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$");
|
||||
foreach (QString style, styles) {
|
||||
if (rx.exactMatch(style)) {
|
||||
QString style_name = rx.cap(1);
|
||||
QString style_value = rx.cap(2);
|
||||
if (style_name == "line-style") {
|
||||
if (style_value == "dashed") pen.setStyle(Qt::DashLine);
|
||||
else if (style_value == "normal") pen.setStyle(Qt::SolidLine);
|
||||
} else if (style_name == "line-weight") {
|
||||
if (style_value == "thin") pen.setWidth(0);
|
||||
else if (style_value == "normal") pen.setWidthF(1.0);
|
||||
else if (style_value == "none") pen.setColor(QColor(0, 0, 0, 0));
|
||||
} else if (style_name == "filling") {
|
||||
if (style_value == "white") {
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(Qt::white);
|
||||
} else if (style_value == "black") {
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(Qt::black);
|
||||
} else if (style_value == "none") {
|
||||
brush.setStyle(Qt::NoBrush);
|
||||
}
|
||||
} else if (style_name == "color") {
|
||||
if (style_value == "black") {
|
||||
pen.setColor(QColor(0, 0, 0, pen.color().alpha()));
|
||||
} else if (style_value == "white") {
|
||||
pen.setColor(QColor(255, 255, 255, pen.color().alpha()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// affectation du QPen et de la QBrush modifies au QPainter
|
||||
qp.setPen(pen);
|
||||
qp.setBrush(brush);
|
||||
|
||||
// mise en place (ou non) de l'antialiasing
|
||||
setQPainterAntiAliasing(qp, e.attribute("antialias") == "true");
|
||||
}
|
||||
124
sources/customelement.h
Normal file
124
sources/customelement.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTPERSO_H
|
||||
#define ELEMENTPERSO_H
|
||||
#include "fixedelement.h"
|
||||
#include <QtGui>
|
||||
#include "nameslist.h"
|
||||
class CustomElementPart;
|
||||
|
||||
/**
|
||||
Cette classe represente un element electrique. Elle est utilisable
|
||||
comme un element fixe. La difference est que l'element perso lit
|
||||
sa description (noms, dessin, comportement) dans un fichier XML a fournir
|
||||
en parametre.
|
||||
*/
|
||||
class CustomElement : public FixedElement {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
CustomElement(QString &, QGraphicsItem * = 0, Diagram * = 0, int * = NULL);
|
||||
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
|
||||
NamesList names;
|
||||
QString nomfichier;
|
||||
QPicture dessin;
|
||||
QList<Terminal *> list_terminals;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual QList<Terminal *> terminals() const;
|
||||
virtual QList<Conductor *> conductors() const;
|
||||
virtual int nbTerminals() const;
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
QString typeId() const;
|
||||
QString fichier() const;
|
||||
bool isNull() const;
|
||||
int etat() const;
|
||||
QString nom() 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 &);
|
||||
};
|
||||
|
||||
/**
|
||||
@return L'ID du type de l'element ; pour un CustomElement, cela revient au
|
||||
nom du fichier
|
||||
@see fichier()
|
||||
*/
|
||||
inline QString CustomElement::typeId() const {
|
||||
return(nomfichier);
|
||||
}
|
||||
|
||||
/**
|
||||
@return L'adresse du fichier contenant la description XML de cet element
|
||||
*/
|
||||
inline QString CustomElement::fichier() const {
|
||||
return(nomfichier);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cet element est nul, c'est-a-dire si le chargement de sa
|
||||
description XML a echoue
|
||||
*/
|
||||
inline bool CustomElement::isNull() const {
|
||||
return(elmt_etat != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Un entier representant l'etat de l'element :
|
||||
- 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
|
||||
- 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
|
||||
*/
|
||||
inline int CustomElement::etat() const {
|
||||
return(elmt_etat);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nom de l'element
|
||||
*/
|
||||
inline QString CustomElement::nom() const {
|
||||
return(names.name(QFileInfo(nomfichier).baseName()));
|
||||
}
|
||||
|
||||
#endif
|
||||
675
sources/diagram.cpp
Normal file
675
sources/diagram.cpp
Normal file
@@ -0,0 +1,675 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 <math.h>
|
||||
#include "qetapp.h"
|
||||
#include "conductor.h"
|
||||
#include "customelement.h"
|
||||
#include "diagram.h"
|
||||
#include "exportdialog.h"
|
||||
#include "diagramcommands.h"
|
||||
#include "diagramcontent.h"
|
||||
|
||||
const int Diagram::xGrid = 10;
|
||||
const int Diagram::yGrid = 10;
|
||||
const qreal Diagram::margin = 5.0;
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QObject parent du schema
|
||||
*/
|
||||
Diagram::Diagram(QObject *parent) :
|
||||
QGraphicsScene(parent),
|
||||
draw_grid(true),
|
||||
use_border(true),
|
||||
moved_elements_fetched(false),
|
||||
draw_terminals(true)
|
||||
{
|
||||
undo_stack = new QUndoStack();
|
||||
qgi_manager = new QGIManager(this);
|
||||
setBackgroundBrush(Qt::white);
|
||||
conductor_setter = new QGraphicsLineItem(0, 0);
|
||||
conductor_setter -> setZValue(1000000);
|
||||
QPen t;
|
||||
t.setColor(Qt::black);
|
||||
t.setWidthF(1.5);
|
||||
t.setStyle(Qt::DashLine);
|
||||
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");
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
Diagram::~Diagram() {
|
||||
// suppression de la liste des annulations - l'undo stack fait appel au qgimanager pour supprimer certains elements
|
||||
delete undo_stack;
|
||||
// suppression du QGIManager - tous les elements qu'il connait sont supprimes
|
||||
delete qgi_manager;
|
||||
|
||||
// recense les items supprimables
|
||||
QList<QGraphicsItem *> deletable_items;
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (qgi -> parentItem()) continue;
|
||||
if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
|
||||
deletable_items << qgi;
|
||||
}
|
||||
|
||||
// suppression des items supprimables
|
||||
foreach(QGraphicsItem *qgi_d, deletable_items) {
|
||||
delete qgi_d;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'arriere-plan du schema, cad la grille.
|
||||
@param p Le QPainter a utiliser pour dessiner
|
||||
@param r Le rectangle de la zone a dessiner
|
||||
*/
|
||||
void Diagram::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);
|
||||
|
||||
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 % xGrid) ++ g_x;
|
||||
int g_y = (int)ceil(r.y());
|
||||
while (g_y % yGrid) ++ g_y;
|
||||
|
||||
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
|
||||
p -> drawPoint(gx, gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (use_border) border_and_inset.draw(p, margin, margin);
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les enfoncements de touches du clavier
|
||||
@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);
|
||||
}
|
||||
QGraphicsScene::keyPressEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les relachements de touches du clavier
|
||||
@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();
|
||||
}
|
||||
QGraphicsScene::keyReleaseEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le schema vers une image
|
||||
@return Une QImage representant le schema
|
||||
*/
|
||||
bool Diagram::toPaintDevice(QPaintDevice &pix, int width, int height, Qt::AspectRatioMode aspectRatioMode) {
|
||||
// determine la zone source = contenu du schema + marges
|
||||
QRectF source_area;
|
||||
if (!use_border) {
|
||||
source_area = itemsBoundingRect();
|
||||
source_area.translate(-margin, -margin);
|
||||
source_area.setWidth (source_area.width () + 2.0 * margin);
|
||||
source_area.setHeight(source_area.height() + 2.0 * margin);
|
||||
} else {
|
||||
source_area = QRectF(
|
||||
0.0,
|
||||
0.0,
|
||||
border_and_inset.borderWidth () + 2.0 * margin,
|
||||
border_and_inset.borderHeight() + 2.0 * margin
|
||||
);
|
||||
}
|
||||
|
||||
// si les dimensions ne sont pas precisees, l'image est exportee a l'echelle 1:1
|
||||
QSize image_size = (width == -1 && height == -1) ? source_area.size().toSize() : QSize(width, height);
|
||||
|
||||
// prepare le rendu
|
||||
QPainter p;
|
||||
if (!p.begin(&pix)) return(false);
|
||||
|
||||
// rendu antialiase
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::TextAntialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
|
||||
// deselectionne tous les elements
|
||||
QList<QGraphicsItem *> selected_elmts = selectedItems();
|
||||
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(false);
|
||||
|
||||
// effectue le rendu lui-meme
|
||||
render(&p, QRect(QPoint(0, 0), image_size), source_area, aspectRatioMode);
|
||||
p.end();
|
||||
|
||||
// restaure les elements selectionnes
|
||||
foreach (QGraphicsItem *qgi, selected_elmts) qgi -> setSelected(true);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de connaitre les dimensions qu'aura l'image generee par la methode toImage()
|
||||
@return La taille de l'image generee par toImage()
|
||||
*/
|
||||
QSize Diagram::imageSize() const {
|
||||
// determine la zone source = contenu du schema + marges
|
||||
qreal image_width, image_height;
|
||||
if (!use_border) {
|
||||
QRectF items_rect = itemsBoundingRect();
|
||||
image_width = items_rect.width();
|
||||
image_height = items_rect.height();
|
||||
} else {
|
||||
image_width = border_and_inset.borderWidth();
|
||||
image_height = border_and_inset.borderHeight();
|
||||
}
|
||||
|
||||
image_width += 2.0 * margin;
|
||||
image_height += 2.0 * margin;
|
||||
|
||||
// renvoie la taille de la zone source
|
||||
return(QSizeF(image_width, image_height).toSize());
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte tout ou partie du schema
|
||||
@param diagram Booleen (a vrai par defaut) indiquant si le XML genere doit
|
||||
representer tout le schema ou seulement les elements selectionnes
|
||||
@return Un Document XML (QDomDocument)
|
||||
*/
|
||||
QDomDocument Diagram::toXml(bool diagram) {
|
||||
// document
|
||||
QDomDocument document;
|
||||
|
||||
// racine de l'arbre XML
|
||||
QDomElement racine = document.createElement("diagram");
|
||||
|
||||
// proprietes du schema
|
||||
if (diagram) {
|
||||
if (!border_and_inset.author().isNull()) racine.setAttribute("author", border_and_inset.author());
|
||||
if (!border_and_inset.date().isNull()) racine.setAttribute("date", border_and_inset.date().toString("yyyyMMdd"));
|
||||
if (!border_and_inset.title().isNull()) racine.setAttribute("title", border_and_inset.title());
|
||||
if (!border_and_inset.fileName().isNull()) racine.setAttribute("filename", border_and_inset.fileName());
|
||||
if (!border_and_inset.folio().isNull()) racine.setAttribute("folio", border_and_inset.folio());
|
||||
racine.setAttribute("cols", border_and_inset.nbColumn());
|
||||
racine.setAttribute("colsize", border_and_inset.columnsWidth());
|
||||
racine.setAttribute("height", border_and_inset.columnsHeight());
|
||||
|
||||
// type de conducteur par defaut
|
||||
QDomElement default_conductor = document.createElement("defaultconductor");
|
||||
defaultConductorProperties.toXml(document, default_conductor);
|
||||
racine.appendChild(default_conductor);
|
||||
}
|
||||
document.appendChild(racine);
|
||||
|
||||
// si le schema ne contient pas d'element (et donc pas de conducteurs), on retourne de suite le document XML
|
||||
if (items().isEmpty()) return(document);
|
||||
|
||||
// creation de trois listes : une qui contient les elements, une qui contient les conducteurs, une qui contient les champs de texte
|
||||
QList<Element *> list_elements;
|
||||
QList<Conductor *> list_conductors;
|
||||
QList<DiagramTextItem *> list_texts;
|
||||
|
||||
// Determine les elements a « XMLiser »
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
|
||||
if (diagram) list_elements << elmt;
|
||||
else if (elmt -> isSelected()) list_elements << elmt;
|
||||
} else if (Conductor *f = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
if (diagram) list_conductors << f;
|
||||
// lorsqu'on n'exporte pas tout le diagram, il faut retirer les conducteurs non selectionnes
|
||||
// et pour l'instant, les conducteurs non selectionnes sont les conducteurs dont un des elements n'est pas relie
|
||||
else if (f -> terminal1 -> parentItem() -> isSelected() && f -> terminal2 -> parentItem() -> isSelected()) list_conductors << f;
|
||||
} else if (DiagramTextItem *dti = qgraphicsitem_cast<DiagramTextItem *>(qgi)) {
|
||||
if (!dti -> parentItem()) {
|
||||
if (diagram) list_texts << dti;
|
||||
else if (dti -> isSelected()) list_texts << dti;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// table de correspondance entre les adresses des bornes et leurs ids
|
||||
QHash<Terminal *, int> table_adr_id;
|
||||
|
||||
// enregistrement des elements
|
||||
if (!list_elements.isEmpty()) {
|
||||
QDomElement elements = document.createElement("elements");
|
||||
foreach(Element *elmt, list_elements) {
|
||||
elements.appendChild(elmt -> toXml(document, table_adr_id));
|
||||
}
|
||||
racine.appendChild(elements);
|
||||
}
|
||||
|
||||
// enregistrement des conducteurs
|
||||
if (!list_conductors.isEmpty()) {
|
||||
QDomElement conductors = document.createElement("conductors");
|
||||
foreach(Conductor *cond, list_conductors) {
|
||||
conductors.appendChild(cond -> toXml(document, table_adr_id));
|
||||
}
|
||||
racine.appendChild(conductors);
|
||||
}
|
||||
|
||||
// enregistrement des champs de texte
|
||||
if (!list_texts.isEmpty()) {
|
||||
QDomElement inputs = document.createElement("inputs");
|
||||
foreach(DiagramTextItem *dti, list_texts) {
|
||||
inputs.appendChild(dti -> toXml(document));
|
||||
}
|
||||
racine.appendChild(inputs);
|
||||
}
|
||||
|
||||
// on retourne le document XML ainsi genere
|
||||
return(document);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe le diagram 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 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
|
||||
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();
|
||||
// le premier element doit etre un schema
|
||||
if (root.tagName() != "diagram") return(false);
|
||||
|
||||
// lecture des attributs de ce schema
|
||||
if (consider_informations) {
|
||||
border_and_inset.setAuthor(root.attribute("author"));
|
||||
border_and_inset.setTitle(root.attribute("title"));
|
||||
border_and_inset.setDate(QDate::fromString(root.attribute("date"), "yyyyMMdd"));
|
||||
border_and_inset.setFileName(root.attribute("filename"));
|
||||
border_and_inset.setFolio(root.attribute("folio"));
|
||||
|
||||
bool ok;
|
||||
// nombre de colonnes
|
||||
int nb_cols = root.attribute("cols").toInt(&ok);
|
||||
if (ok) border_and_inset.setNbColumns(nb_cols);
|
||||
|
||||
// taille des colonnes
|
||||
double col_size = root.attribute("colsize").toDouble(&ok);
|
||||
if (ok) border_and_inset.setColumnsWidth(col_size);
|
||||
|
||||
// hauteur du schema
|
||||
double height = root.attribute("height").toDouble(&ok);
|
||||
if (ok) border_and_inset.setColumnsHeight(height);
|
||||
|
||||
border_and_inset.adjustInsetToColumns();
|
||||
|
||||
// repere le permier element "defaultconductor"
|
||||
for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
||||
QDomElement elmts = node.toElement();
|
||||
if(elmts.isNull() || elmts.tagName() != "defaultconductor") continue;
|
||||
defaultConductorProperties.fromXml(elmts);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// si la racine n'a pas d'enfant : le chargement est fini (schema vide)
|
||||
if (root.firstChild().isNull()) return(true);
|
||||
|
||||
// chargement de tous les elements du fichier XML
|
||||
QList<Element *> added_elements;
|
||||
QHash<int, Terminal *> table_adr_id;
|
||||
foreach (QDomElement e, QET::findInDomElement(root, "elements", "element")) {
|
||||
if (!Element::valideXml(e)) continue;
|
||||
|
||||
// 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);
|
||||
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());
|
||||
delete nvel_elmt;
|
||||
qDebug(debug_message.toLatin1().data());
|
||||
continue;
|
||||
}
|
||||
|
||||
// charge les caracteristiques de l'element
|
||||
if (nvel_elmt -> fromXml(e, table_adr_id)) {
|
||||
// ajout de l'element au schema et a la liste des elements ajoutes
|
||||
addItem(nvel_elmt);
|
||||
added_elements << nvel_elmt;
|
||||
} else {
|
||||
delete nvel_elmt;
|
||||
qDebug("Le chargement des parametres d'un element a echoue");
|
||||
}
|
||||
}
|
||||
|
||||
// chargement de tous les textes du fichiers XML
|
||||
QList<DiagramTextItem *> added_texts;
|
||||
foreach (QDomElement f, QET::findInDomElement(root, "inputs", "input")) {
|
||||
DiagramTextItem *dti = new DiagramTextItem(0, this);
|
||||
dti -> fromXml(f);
|
||||
added_texts << dti;
|
||||
}
|
||||
|
||||
// gere la translation des nouveaux elements et texte si celle-ci est demandee
|
||||
if (position != QPointF()) {
|
||||
// determine quel est le coin superieur gauche du rectangle entourant les elements ajoutes
|
||||
qreal minimum_x = 0, minimum_y = 0;
|
||||
bool init = false;
|
||||
QList<QGraphicsItem *> added_items;
|
||||
foreach (Element *added_element, added_elements) added_items << added_element;
|
||||
foreach (DiagramTextItem *added_text, added_texts) added_items << added_text;
|
||||
foreach (QGraphicsItem *item, added_items) {
|
||||
QPointF csg = item -> mapToScene(item -> boundingRect()).boundingRect().topLeft();
|
||||
qreal px = csg.x();
|
||||
qreal py = csg.y();
|
||||
if (!init) {
|
||||
minimum_x = px;
|
||||
minimum_y = py;
|
||||
init = true;
|
||||
} else {
|
||||
if (px < minimum_x) minimum_x = px;
|
||||
if (py < minimum_y) minimum_y = py;
|
||||
}
|
||||
}
|
||||
qreal diff_x = position.x() - minimum_x;
|
||||
qreal diff_y = position.y() - minimum_y;
|
||||
foreach (Element *added_element, added_elements) {
|
||||
added_element -> setPos(added_element -> pos().x() + diff_x, added_element -> pos().y() + diff_y);
|
||||
}
|
||||
foreach (DiagramTextItem *added_text, added_texts) {
|
||||
added_text -> setPos(added_text -> pos().x() + diff_x, added_text -> pos().y() + diff_y);
|
||||
}
|
||||
}
|
||||
|
||||
// chargement de tous les Conducteurs du fichier XML
|
||||
QList<Conductor *> added_conductors;
|
||||
foreach (QDomElement f, QET::findInDomElement(root, "conductors", "conductor")) {
|
||||
if (!Conductor::valideXml(f)) continue;
|
||||
// verifie que les bornes que le conducteur relie sont connues
|
||||
int id_p1 = f.attribute("terminal1").toInt();
|
||||
int id_p2 = f.attribute("terminal2").toInt();
|
||||
if (table_adr_id.contains(id_p1) && table_adr_id.contains(id_p2)) {
|
||||
// pose le conducteur... si c'est possible
|
||||
Terminal *p1 = table_adr_id.value(id_p1);
|
||||
Terminal *p2 = table_adr_id.value(id_p2);
|
||||
if (p1 != p2) {
|
||||
bool can_add_conductor = true;
|
||||
bool cia = ((Element *)p2 -> parentItem()) -> internalConnections();
|
||||
if (!cia) {
|
||||
foreach(QGraphicsItem *item, p2 -> parentItem() -> children()) {
|
||||
if (item == p1) can_add_conductor = false;
|
||||
}
|
||||
}
|
||||
if (can_add_conductor) {
|
||||
Conductor *c = new Conductor(table_adr_id.value(id_p1), table_adr_id.value(id_p2), 0, this);
|
||||
c -> fromXml(f);
|
||||
added_conductors << c;
|
||||
}
|
||||
}
|
||||
} else qDebug() << "Le chargement du conductor" << id_p1 << id_p2 << "a echoue";
|
||||
}
|
||||
|
||||
// remplissage des listes facultatives
|
||||
if (content_ptr != NULL) {
|
||||
content_ptr -> elements = added_elements;
|
||||
content_ptr -> conductorsToMove = added_conductors;
|
||||
content_ptr -> textFields = added_texts;
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le fait qu'un texte du schema ait ete modifie
|
||||
@param text_item Texte modifie
|
||||
@param old_text Ancien texte
|
||||
@param new_text Nouveau texte
|
||||
*/
|
||||
void Diagram::diagramTextChanged(DiagramTextItem *text_item, const QString &old_text, const QString &new_text) {
|
||||
if (!text_item) return;
|
||||
undo_stack -> push(new ChangeDiagramTextCommand(text_item, old_text, new_text));
|
||||
}
|
||||
|
||||
/**
|
||||
Verifie si la selection est passe d'un etat ou elle est vide a un etat ou
|
||||
elle ne l'est pas, et inversement. Si c'est le cas, le signal
|
||||
EmptinessChanged() est emis.
|
||||
*/
|
||||
void Diagram::slot_checkSelectionEmptinessChange() {
|
||||
static bool selection_was_empty = true;
|
||||
bool selection_is_empty = selectedItems().isEmpty();
|
||||
if (selection_was_empty != selection_is_empty) {
|
||||
emit(selectionEmptinessChanged());
|
||||
selection_was_empty = selection_is_empty;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le rectangle (coordonnees par rapport a la scene) delimitant le bord du schema
|
||||
*/
|
||||
QRectF Diagram::border() const {
|
||||
return(
|
||||
QRectF(
|
||||
margin,
|
||||
margin,
|
||||
border_and_inset.borderWidth(),
|
||||
border_and_inset.borderHeight()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// oublie la liste des elements et conducteurs en mouvement
|
||||
void Diagram::invalidateMovedElements() {
|
||||
if (!moved_elements_fetched) return;
|
||||
moved_elements_fetched = false;
|
||||
elements_to_move.clear();
|
||||
conductors_to_move.clear();
|
||||
conductors_to_update.clear();
|
||||
texts_to_move.clear();
|
||||
}
|
||||
|
||||
/// reconstruit la liste des elements et conducteurs en mouvement
|
||||
void Diagram::fetchMovedElements() {
|
||||
// recupere les elements deplaces
|
||||
foreach (QGraphicsItem *item, selectedItems()) {
|
||||
if (Element *elmt = qgraphicsitem_cast<Element *>(item)) {
|
||||
elements_to_move << elmt;
|
||||
} else if (DiagramTextItem *t = qgraphicsitem_cast<DiagramTextItem *>(item)) {
|
||||
if (!t -> parentItem()) texts_to_move << t;
|
||||
}
|
||||
}
|
||||
|
||||
// pour chaque element deplace, determine les conducteurs qui seront modifies
|
||||
foreach(Element *elmt, elements_to_move) {
|
||||
foreach(Terminal *terminal, elmt -> terminals()) {
|
||||
foreach(Conductor *conductor, terminal -> conductors()) {
|
||||
Terminal *other_terminal;
|
||||
if (conductor -> terminal1 == terminal) {
|
||||
other_terminal = conductor -> terminal2;
|
||||
} else {
|
||||
other_terminal = conductor -> terminal1;
|
||||
}
|
||||
// si les deux elements du conducteur sont deplaces
|
||||
if (elements_to_move.contains(static_cast<Element *>(other_terminal -> parentItem()))) {
|
||||
conductors_to_move << conductor;
|
||||
} else {
|
||||
conductors_to_update.insert(conductor, terminal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
moved_elements_fetched = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Deplace les elements, conducteurs et textes selectionnes en gerant au
|
||||
mieux les conducteurs (seuls les conducteurs dont un seul des elements
|
||||
est deplace sont recalcules, les autres sont deplaces).
|
||||
@param diff Translation a effectuer
|
||||
@param dontmove QGraphicsItem (optionnel) a ne pas deplacer ; note : ce
|
||||
parametre ne concerne que les elements et les champs de texte.
|
||||
*/
|
||||
void Diagram::moveElements(const QPointF &diff, QGraphicsItem *dontmove) {
|
||||
// inutile de deplacer les autres elements s'il n'y a pas eu de mouvement concret
|
||||
if (diff.isNull()) return;
|
||||
|
||||
current_movement += diff;
|
||||
|
||||
// deplace les elements selectionnes
|
||||
foreach(Element *element, elementsToMove()) {
|
||||
if (dontmove != NULL && element == dontmove) continue;
|
||||
element -> setPos(element -> pos() + diff);
|
||||
}
|
||||
|
||||
// deplace certains conducteurs
|
||||
foreach(Conductor *conductor, conductorsToMove()) {
|
||||
conductor -> setPos(conductor -> pos() + diff);
|
||||
}
|
||||
|
||||
// recalcule les autres conducteurs
|
||||
const QHash<Conductor *, Terminal *> &conductors_modify = conductorsToUpdate();
|
||||
foreach(Conductor *conductor, conductors_modify.keys()) {
|
||||
conductor -> updateWithNewPos(QRectF(), conductors_modify[conductor], conductors_modify[conductor] -> amarrageConductor());
|
||||
}
|
||||
|
||||
// deplace les champs de texte
|
||||
foreach(DiagramTextItem *dti, textsToMove()) {
|
||||
if (dontmove != NULL && dti == dontmove) continue;
|
||||
dti -> setPos(dti -> pos() + diff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Definit s'il faut afficher ou non les bornes
|
||||
@param dt true pour afficher les bornes, false sinon
|
||||
*/
|
||||
void Diagram::setDrawTerminals(bool dt) {
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (Terminal *t = qgraphicsitem_cast<Terminal *>(qgi)) {
|
||||
t -> setVisible(dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return la liste des conducteurs selectionnes sur le schema
|
||||
*/
|
||||
QSet<Conductor *> Diagram::selectedConductors() const {
|
||||
QSet<Conductor *> conductors_set;
|
||||
foreach(QGraphicsItem *qgi, selectedItems()) {
|
||||
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
conductors_set << c;
|
||||
}
|
||||
}
|
||||
return(conductors_set);
|
||||
}
|
||||
|
||||
/// @return true si le presse-papier semble contenir un schema
|
||||
bool Diagram::clipboardMayContainDiagram() {
|
||||
QString clipboard_text = QApplication::clipboard() -> text().trimmed();
|
||||
bool may_be_diagram = clipboard_text.startsWith("<diagram") && clipboard_text.endsWith("</diagram>");
|
||||
return(may_be_diagram);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le contenu du schema. Les conducteurs sont tous places dans
|
||||
conductorsToMove.
|
||||
*/
|
||||
DiagramContent Diagram::content() const {
|
||||
DiagramContent dc;
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (Element *e = qgraphicsitem_cast<Element *>(qgi)) {
|
||||
dc.elements << e;
|
||||
} else if (DiagramTextItem *dti = qgraphicsitem_cast<DiagramTextItem *>(qgi)) {
|
||||
dc.textFields << dti;
|
||||
} else if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
dc.conductorsToMove << c;
|
||||
}
|
||||
}
|
||||
return(dc);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le contenu selectionne du schema.
|
||||
*/
|
||||
DiagramContent Diagram::selectedContent() {
|
||||
invalidateMovedElements();
|
||||
DiagramContent dc;
|
||||
dc.elements = elementsToMove().toList();
|
||||
dc.textFields = textsToMove().toList();
|
||||
dc.conductorsToMove = conductorsToMove().toList();
|
||||
dc.conductorsToUpdate = conductorsToUpdate();
|
||||
|
||||
// recupere les conducteurs selectionnes isoles (= non deplacables mais supprimables)
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
if (
|
||||
c -> isSelected() &&\
|
||||
!c -> terminal1 -> parentItem() -> isSelected() &&\
|
||||
!c -> terminal2 -> parentItem() -> isSelected()
|
||||
) {
|
||||
dc.otherConductors << c;
|
||||
}
|
||||
}
|
||||
}
|
||||
invalidateMovedElements();
|
||||
return(dc);
|
||||
}
|
||||
269
sources/diagram.h
Normal file
269
sources/diagram.h
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 SCHEMA_H
|
||||
#define SCHEMA_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include "qetdiagrameditor.h"
|
||||
#include "borderinset.h"
|
||||
#include "qgimanager.h"
|
||||
#include "conductorproperties.h"
|
||||
class Element;
|
||||
class Terminal;
|
||||
class Conductor;
|
||||
class DiagramTextItem;
|
||||
class DiagramContent;
|
||||
/**
|
||||
Cette classe represente un schema electrique.
|
||||
Elle gere les differents elements et conducteurs qui le composent
|
||||
et en effectue le rendu graphique.
|
||||
*/
|
||||
class Diagram : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
Diagram(QObject * = 0);
|
||||
virtual ~Diagram();
|
||||
|
||||
private:
|
||||
Diagram(const Diagram &diagram);
|
||||
|
||||
// attributs
|
||||
public:
|
||||
/**
|
||||
Represente les options possibles pour l'affichage du schema :
|
||||
* EmptyBorder : N'afficher que la bordure
|
||||
* Inset : Afficher le cartouche
|
||||
* Columns : Afficher les colonnes
|
||||
*/
|
||||
enum BorderOptions { EmptyBorder, Inset, Columns };
|
||||
/// Proprietes par defaut des nouveaux conducteurs
|
||||
ConductorProperties defaultConductorProperties;
|
||||
/// Dimensions et cartouches du schema
|
||||
BorderInset border_and_inset;
|
||||
/// Mouvement en cours lors d'un deplacement d'elements et conducteurs
|
||||
QPointF current_movement;
|
||||
/// taille de la grille en abscisse
|
||||
static const int xGrid;
|
||||
/// taille de la grille en ordonnee
|
||||
static const int yGrid;
|
||||
/// marge autour du schema
|
||||
static const qreal margin;
|
||||
|
||||
private:
|
||||
QGraphicsLineItem *conductor_setter;
|
||||
bool draw_grid;
|
||||
bool use_border;
|
||||
bool moved_elements_fetched;
|
||||
QSet<Element *> elements_to_move;
|
||||
QSet<Conductor *> conductors_to_move;
|
||||
QHash<Conductor *, Terminal *> conductors_to_update;
|
||||
QSet<DiagramTextItem *> texts_to_move;
|
||||
QGIManager *qgi_manager;
|
||||
QUndoStack *undo_stack;
|
||||
bool draw_terminals;
|
||||
|
||||
// methodes
|
||||
protected:
|
||||
virtual void drawBackground(QPainter *, const QRectF &);
|
||||
virtual void keyPressEvent(QKeyEvent *);
|
||||
virtual void keyReleaseEvent(QKeyEvent *);
|
||||
|
||||
public:
|
||||
static bool clipboardMayContainDiagram();
|
||||
|
||||
// fonctions relatives a la pose de conducteurs
|
||||
void setConductor(bool);
|
||||
void setConductorStart (QPointF);
|
||||
void setConductorStop(QPointF);
|
||||
|
||||
// fonctions relatives a l'import / export XML
|
||||
QDomDocument toXml(bool = true);
|
||||
bool fromXml(QDomDocument &, QPointF = QPointF(), bool = true, DiagramContent * = NULL);
|
||||
|
||||
// fonctions relatives aux options graphiques
|
||||
void setDisplayGrid(bool);
|
||||
bool displayGrid();
|
||||
void setUseBorder(bool);
|
||||
bool useBorder();
|
||||
void setBorderOptions(BorderOptions);
|
||||
BorderOptions borderOptions();
|
||||
|
||||
bool drawTerminals() const;
|
||||
void setDrawTerminals(bool);
|
||||
|
||||
QRectF border() const;
|
||||
bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio);
|
||||
QSize imageSize() const;
|
||||
|
||||
void invalidateMovedElements();
|
||||
void fetchMovedElements();
|
||||
const QSet<Element *> &elementsToMove();
|
||||
const QSet<Conductor *> &conductorsToMove();
|
||||
const QHash<Conductor *, Terminal *> &conductorsToUpdate();
|
||||
const QSet<DiagramTextItem *> &textsToMove();
|
||||
QSet<Conductor *> selectedConductors() const;
|
||||
DiagramContent content() const;
|
||||
DiagramContent selectedContent();
|
||||
void moveElements(const QPointF &, QGraphicsItem * = NULL);
|
||||
|
||||
QUndoStack &undoStack();
|
||||
QGIManager &qgiManager();
|
||||
|
||||
public slots:
|
||||
void diagramTextChanged(DiagramTextItem *, const QString &, const QString &);
|
||||
|
||||
private slots:
|
||||
void slot_checkSelectionEmptinessChange();
|
||||
|
||||
signals:
|
||||
/**
|
||||
Ce signal est emis lorsque la selection passe de l'etat rempli (par un
|
||||
nombre quelconque d'elements et conducteurs) a l'etat vide et
|
||||
vice-versa.
|
||||
*/
|
||||
void selectionEmptinessChanged();
|
||||
};
|
||||
|
||||
/**
|
||||
Permet d'ajouter ou enlever le « poseur de conducteur », c'est-a-dire la
|
||||
droite en pointilles qui apparait lorsqu'on pose un conducteur entre deux
|
||||
bornes.
|
||||
@param pf true pour ajouter le poseur de conducteur, false pour l'enlever
|
||||
*/
|
||||
inline void Diagram::setConductor(bool pf) {
|
||||
if (pf) {
|
||||
if (!conductor_setter -> scene()) addItem(conductor_setter);
|
||||
} else {
|
||||
if (conductor_setter -> scene()) removeItem(conductor_setter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie les coordonnees du point de depart du poseur de conducteur
|
||||
@param d Le nouveau point de depart du poseur de conducteur
|
||||
*/
|
||||
inline void Diagram::setConductorStart(QPointF d) {
|
||||
conductor_setter -> setLine(QLineF(d, conductor_setter -> line().p2()));
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie les coordonnees du point d'arrivee du poseur de conducteur
|
||||
@param a Le nouveau point d'arrivee du poseur de conducteur
|
||||
*/
|
||||
inline void Diagram::setConductorStop(QPointF a) {
|
||||
conductor_setter -> setLine(QLineF(conductor_setter -> line().p1(), a));
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de specifier si la grille du schema doit etre dessinee ou non
|
||||
@param dg true pour afficher la grille, false pour ne pas l'afficher
|
||||
*/
|
||||
inline void Diagram::setDisplayGrid(bool dg) {
|
||||
draw_grid = dg;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si la grille du schema est dessinee ou non
|
||||
@return true si la grille est affichee , false sinon
|
||||
*/
|
||||
inline bool Diagram::displayGrid() {
|
||||
return(draw_grid);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de specifier si le cadre du schema doit etre pris en compte pour
|
||||
determiner le contour du schema.
|
||||
@param ub true pour prendre le schema en compte, false sinon
|
||||
*/
|
||||
inline void Diagram::setUseBorder(bool ub) {
|
||||
use_border = ub;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si le cadre du schema est pris en compte pour
|
||||
determiner le contour du schema.
|
||||
*/
|
||||
inline bool Diagram::useBorder() {
|
||||
return(use_border);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de definir les options du cadre, des colonnes et du cartouche.
|
||||
@param bo Un OU binaire entre les options possibles
|
||||
@see BorderOptions
|
||||
*/
|
||||
inline void Diagram::setBorderOptions(Diagram::BorderOptions bo) {
|
||||
border_and_inset.displayBorder(!(bo & EmptyBorder));
|
||||
border_and_inset.displayColumns(bo & Columns);
|
||||
border_and_inset.displayInset(bo & Inset);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir les options du cadre, des colonnes et du cartouche.
|
||||
@return Un OU binaire entre les options possibles
|
||||
@see BorderOptions
|
||||
*/
|
||||
inline Diagram::BorderOptions Diagram::borderOptions() {
|
||||
BorderOptions retour = EmptyBorder;
|
||||
if (border_and_inset.insetIsDisplayed()) retour = (BorderOptions)(retour|Inset);
|
||||
if (border_and_inset.columnsAreDisplayed()) retour = (BorderOptions)(retour|Columns);
|
||||
return(retour);
|
||||
}
|
||||
|
||||
/// @return la liste des elements a deplacer
|
||||
inline const QSet<Element *> &Diagram::elementsToMove() {
|
||||
if (!moved_elements_fetched) fetchMovedElements();
|
||||
return(elements_to_move);
|
||||
}
|
||||
|
||||
/// @return la liste des conducteurs a deplacer
|
||||
inline const QSet<Conductor *> &Diagram::conductorsToMove() {
|
||||
if (!moved_elements_fetched) fetchMovedElements();
|
||||
return(conductors_to_move);
|
||||
}
|
||||
|
||||
/// @return la liste des conducteurs a modifier (typiquement les conducteurs dont seul un element est deplace)
|
||||
inline const QHash<Conductor *, Terminal *> &Diagram::conductorsToUpdate() {
|
||||
if (!moved_elements_fetched) fetchMovedElements();
|
||||
return(conductors_to_update);
|
||||
}
|
||||
|
||||
/// @return la liste des textes a deplacer
|
||||
inline const QSet<DiagramTextItem *> &Diagram::textsToMove() {
|
||||
if (!moved_elements_fetched) fetchMovedElements();
|
||||
return(texts_to_move);
|
||||
}
|
||||
|
||||
/// @return la pile d'annulations de ce schema
|
||||
inline QUndoStack &Diagram::undoStack() {
|
||||
return(*undo_stack);
|
||||
}
|
||||
|
||||
/// @return le egstionnaire de QGraphicsItem de ce schema
|
||||
inline QGIManager &Diagram::qgiManager() {
|
||||
return(*qgi_manager);
|
||||
}
|
||||
|
||||
/// @return true si les bornes sont affichees, false sinon
|
||||
inline bool Diagram::drawTerminals() const {
|
||||
return(draw_terminals);
|
||||
}
|
||||
|
||||
#endif
|
||||
637
sources/diagramcommands.cpp
Normal file
637
sources/diagramcommands.cpp
Normal file
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "diagramcommands.h"
|
||||
#include "element.h"
|
||||
#include "conductor.h"
|
||||
#include "diagram.h"
|
||||
#include "qgimanager.h"
|
||||
/**
|
||||
Constructeur
|
||||
@param d Schema auquel on ajoute un element
|
||||
@param elmt Element ajoute
|
||||
@param p Position a laquelle l'element est ajoute
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AddElementCommand::AddElementCommand(
|
||||
Diagram *d,
|
||||
Element *elmt,
|
||||
const QPointF &p,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajouter 1 ") + elmt -> nom(), parent),
|
||||
element(elmt),
|
||||
diagram(d),
|
||||
position(p)
|
||||
{
|
||||
diagram -> qgiManager().manage(element);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
AddElementCommand::~AddElementCommand() {
|
||||
diagram -> qgiManager().release(element);
|
||||
}
|
||||
|
||||
/// Annule l'ajout
|
||||
void AddElementCommand::undo() {
|
||||
diagram -> removeItem(element);
|
||||
}
|
||||
|
||||
/// Refait l'ajout
|
||||
void AddElementCommand::redo() {
|
||||
diagram -> addItem(element);
|
||||
element -> setPos(position);
|
||||
element -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema auquel on ajoute du texte
|
||||
@param text Texte ajoute
|
||||
@param pos Position a laquelle le texte est ajoute
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AddTextCommand::AddTextCommand(Diagram *dia, DiagramTextItem *text, const QPointF &pos, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("Ajouter un champ de texte"), parent),
|
||||
textitem(text),
|
||||
diagram(dia),
|
||||
position(pos)
|
||||
{
|
||||
diagram -> qgiManager().manage(textitem);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
AddTextCommand::~AddTextCommand() {
|
||||
diagram -> qgiManager().release(textitem);
|
||||
}
|
||||
|
||||
/// Annule l'ajout
|
||||
void AddTextCommand::undo() {
|
||||
QObject::disconnect(
|
||||
textitem,
|
||||
SIGNAL(diagramTextChanged(DiagramTextItem *, const QString &, const QString &)),
|
||||
diagram,
|
||||
SLOT(diagramTextChanged(DiagramTextItem *, const QString &, const QString &))
|
||||
);
|
||||
diagram -> removeItem(textitem);
|
||||
}
|
||||
|
||||
/// Refait l'ajour
|
||||
void AddTextCommand::redo() {
|
||||
QObject::connect(
|
||||
textitem,
|
||||
SIGNAL(diagramTextChanged(DiagramTextItem *, const QString &, const QString &)),
|
||||
diagram,
|
||||
SLOT(diagramTextChanged(DiagramTextItem *, const QString &, const QString &))
|
||||
);
|
||||
diagram -> addItem(textitem);
|
||||
textitem -> setPos(position);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param d Schema auquel on ajoute un conducteur
|
||||
@param c Conducteur ajoute
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AddConductorCommand::AddConductorCommand(
|
||||
Diagram *d,
|
||||
Conductor *c,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajouter un conducteur"), parent),
|
||||
conductor(c),
|
||||
diagram(d)
|
||||
{
|
||||
diagram -> qgiManager().manage(conductor);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
AddConductorCommand::~AddConductorCommand() {
|
||||
diagram -> qgiManager().release(conductor);
|
||||
}
|
||||
|
||||
/// Annule l'ajout
|
||||
void AddConductorCommand::undo() {
|
||||
// detache le conducteur sans le detruire
|
||||
conductor -> terminal1 -> removeConductor(conductor);
|
||||
conductor -> terminal2 -> removeConductor(conductor);
|
||||
diagram -> removeItem(conductor);
|
||||
}
|
||||
|
||||
/// Refait l'ajout
|
||||
void AddConductorCommand::redo() {
|
||||
diagram -> addItem(conductor);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema dont on supprime des elements et conducteurs
|
||||
@param content Contenu supprime
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
DeleteElementsCommand::DeleteElementsCommand(
|
||||
Diagram *dia,
|
||||
const DiagramContent &content,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(parent),
|
||||
removed_content(content),
|
||||
diagram(dia)
|
||||
{
|
||||
setText(QObject::tr("supprimer ") + removed_content.sentence(DiagramContent::All));
|
||||
diagram -> qgiManager().manage(removed_content.items(DiagramContent::All));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
DeleteElementsCommand::~DeleteElementsCommand() {
|
||||
diagram -> qgiManager().release(removed_content.items(DiagramContent::All));
|
||||
}
|
||||
|
||||
/// annule les suppressions
|
||||
void DeleteElementsCommand::undo() {
|
||||
// remet les elements
|
||||
foreach(Element *e, removed_content.elements) {
|
||||
diagram -> addItem(e);
|
||||
}
|
||||
|
||||
// remet les conducteurs
|
||||
foreach(Conductor *c, removed_content.conductors(DiagramContent::AnyConductor)) {
|
||||
diagram -> addItem(c);
|
||||
c -> terminal1 -> addConductor(c);
|
||||
c -> terminal2 -> addConductor(c);
|
||||
}
|
||||
|
||||
// remet les textes
|
||||
foreach(DiagramTextItem *t, removed_content.textFields) {
|
||||
diagram -> addItem(t);
|
||||
}
|
||||
}
|
||||
|
||||
/// refait les suppressions
|
||||
void DeleteElementsCommand::redo() {
|
||||
// enleve les conducteurs
|
||||
foreach(Conductor *c, removed_content.conductors(DiagramContent::AnyConductor)) {
|
||||
c -> terminal1 -> removeConductor(c);
|
||||
c -> terminal2 -> removeConductor(c);
|
||||
diagram -> removeItem(c);
|
||||
}
|
||||
|
||||
// enleve les elements
|
||||
foreach(Element *e, removed_content.elements) {
|
||||
diagram -> removeItem(e);
|
||||
}
|
||||
|
||||
// enleve les textes
|
||||
foreach(DiagramTextItem *t, removed_content.textFields) {
|
||||
diagram -> removeItem(t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema sur lequel on colle les elements et conducteurs
|
||||
@param c Contenu a coller sur le schema
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
PasteDiagramCommand::PasteDiagramCommand(
|
||||
Diagram *dia,
|
||||
const DiagramContent &c,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(parent),
|
||||
content(c),
|
||||
diagram(dia),
|
||||
filter(DiagramContent::Elements|DiagramContent::TextFields|DiagramContent::ConductorsToMove),
|
||||
first_redo(true)
|
||||
{
|
||||
|
||||
setText(QObject::tr("coller ") + content.sentence(filter));
|
||||
diagram -> qgiManager().manage(content.items(filter));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PasteDiagramCommand::~PasteDiagramCommand() {
|
||||
diagram -> qgiManager().release(content.items(filter));
|
||||
}
|
||||
|
||||
/// annule le coller
|
||||
void PasteDiagramCommand::undo() {
|
||||
// enleve les conducteurs
|
||||
foreach(Conductor *c, content.conductorsToMove) {
|
||||
c -> terminal1 -> removeConductor(c);
|
||||
c -> terminal2 -> removeConductor(c);
|
||||
diagram -> removeItem(c);
|
||||
}
|
||||
|
||||
// enleve les elements
|
||||
foreach(Element *e, content.elements) diagram -> removeItem(e);
|
||||
|
||||
// enleve les textes
|
||||
foreach(DiagramTextItem *t, content.textFields) diagram -> removeItem(t);
|
||||
}
|
||||
|
||||
/// refait le coller
|
||||
void PasteDiagramCommand::redo() {
|
||||
if (first_redo) first_redo = false;
|
||||
else {
|
||||
// pose les elements
|
||||
foreach(Element *e, content.elements) diagram -> addItem(e);
|
||||
|
||||
// pose les conducteurs
|
||||
foreach(Conductor *c, content.conductorsToMove) {
|
||||
diagram -> addItem(c);
|
||||
c -> terminal1 -> addConductor(c);
|
||||
c -> terminal2 -> addConductor(c);
|
||||
}
|
||||
|
||||
// pose les textes
|
||||
foreach(DiagramTextItem *t, content.textFields) diagram -> addItem(t);
|
||||
}
|
||||
foreach(Element *e, content.elements) e -> setSelected(true);
|
||||
foreach(Conductor *c, content.conductorsToMove) c -> setSelected(true);
|
||||
foreach(DiagramTextItem *t, content.textFields) t -> setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema dont on coupe des elements et conducteurs
|
||||
@param content Contenu coupe
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
CutDiagramCommand::CutDiagramCommand(
|
||||
Diagram *dia,
|
||||
const DiagramContent &content,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
DeleteElementsCommand(dia, content, parent)
|
||||
{
|
||||
setText(QObject::tr("couper ") + content.sentence(DiagramContent::All));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
CutDiagramCommand::~CutDiagramCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema sur lequel on deplace des elements
|
||||
@param diagram_content Contenu a deplacer
|
||||
@param m translation subie par les elements
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
MoveElementsCommand::MoveElementsCommand(
|
||||
Diagram *dia,
|
||||
const DiagramContent &diagram_content,
|
||||
const QPointF &m,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(parent),
|
||||
diagram(dia),
|
||||
content_to_move(diagram_content),
|
||||
movement(m),
|
||||
first_redo(true)
|
||||
{
|
||||
setText(QObject::tr("d\351placer ") + content_to_move.sentence(DiagramContent::Elements|DiagramContent::TextFields|DiagramContent::ConductorsToUpdate|DiagramContent::ConductorsToMove));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
MoveElementsCommand::~MoveElementsCommand() {
|
||||
}
|
||||
|
||||
/// annule le deplacement
|
||||
void MoveElementsCommand::undo() {
|
||||
move(-movement);
|
||||
}
|
||||
|
||||
/// refait le deplacement
|
||||
void MoveElementsCommand::redo() {
|
||||
if (first_redo) first_redo = false;
|
||||
else move(movement);
|
||||
}
|
||||
|
||||
/**
|
||||
deplace les elements et conducteurs
|
||||
@param actual_movement translation a effectuer sur les elements et conducteurs
|
||||
*/
|
||||
void MoveElementsCommand::move(const QPointF &actual_movement) {
|
||||
// deplace les elements
|
||||
foreach(Element *element, content_to_move.elements) {
|
||||
element -> setPos(element -> pos() + actual_movement);
|
||||
}
|
||||
|
||||
// deplace certains conducteurs
|
||||
foreach(Conductor *conductor, content_to_move.conductorsToMove) {
|
||||
conductor -> setPos(conductor -> pos() + actual_movement);
|
||||
}
|
||||
|
||||
// recalcule les autres conducteurs
|
||||
foreach(Conductor *conductor, content_to_move.conductorsToUpdate.keys()) {
|
||||
conductor -> updateWithNewPos(
|
||||
QRectF(),
|
||||
content_to_move.conductorsToUpdate[conductor],
|
||||
content_to_move.conductorsToUpdate[conductor] -> amarrageConductor()
|
||||
);
|
||||
}
|
||||
|
||||
// deplace les textes
|
||||
foreach(DiagramTextItem *text, content_to_move.textFields) {
|
||||
text -> setPos(text -> pos() + actual_movement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dti Champ de texte modifie
|
||||
@param before texte avant
|
||||
@param after texte apres
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeDiagramTextCommand::ChangeDiagramTextCommand(
|
||||
DiagramTextItem *dti,
|
||||
const QString &before,
|
||||
const QString &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier le texte"), parent),
|
||||
text_item(dti),
|
||||
text_before(before),
|
||||
text_after(after),
|
||||
first_redo(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// destructeur
|
||||
ChangeDiagramTextCommand::~ChangeDiagramTextCommand() {
|
||||
}
|
||||
|
||||
/// annule la modification de texte
|
||||
void ChangeDiagramTextCommand::undo() {
|
||||
text_item -> setPlainText(text_before);
|
||||
text_item -> previous_text = text_before;
|
||||
}
|
||||
|
||||
/// refait la modification de texte
|
||||
void ChangeDiagramTextCommand::redo() {
|
||||
if (first_redo) first_redo = false;
|
||||
else {
|
||||
text_item -> setPlainText(text_after);
|
||||
text_item -> previous_text = text_after;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param elements Elements a pivoter associes a leur orientation d'origine
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
RotateElementsCommand::RotateElementsCommand(const QHash<Element *, QET::Orientation> &elements, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("pivoter ") + QET::ElementsAndConductorsSentence(elements.count(), 0), parent),
|
||||
elements_to_rotate(elements)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
RotateElementsCommand::~RotateElementsCommand() {
|
||||
}
|
||||
|
||||
/// defait le pivotement
|
||||
void RotateElementsCommand::undo() {
|
||||
foreach(Element *e, elements_to_rotate.keys()) {
|
||||
e -> setOrientation(elements_to_rotate[e]);
|
||||
}
|
||||
}
|
||||
|
||||
/// refait le pivotement
|
||||
void RotateElementsCommand::redo() {
|
||||
foreach(Element *e, elements_to_rotate.keys()) {
|
||||
e -> setOrientation(e -> orientation().next());
|
||||
e -> update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param c Conducteur modifie
|
||||
@param old_p ancien profil du conducteur
|
||||
@param new_p nouveau profil du conducteur
|
||||
@param path_t Trajectoire du trajet modifie
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeConductorCommand::ChangeConductorCommand(
|
||||
Conductor *c,
|
||||
const ConductorProfile &old_p,
|
||||
const ConductorProfile &new_p,
|
||||
Qt::Corner path_t,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier un conducteur"), parent),
|
||||
conductor(c),
|
||||
old_profile(old_p),
|
||||
new_profile(new_p),
|
||||
path_type(path_t),
|
||||
first_redo(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeConductorCommand::~ChangeConductorCommand() {
|
||||
}
|
||||
|
||||
/// Annule la modification du conducteur
|
||||
void ChangeConductorCommand::undo() {
|
||||
conductor -> setProfile(old_profile, path_type);
|
||||
}
|
||||
|
||||
/// Refait la modification du conducteur
|
||||
void ChangeConductorCommand::redo() {
|
||||
if (first_redo) first_redo = false;
|
||||
else conductor -> setProfile(new_profile, path_type);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param cp Conducteurs reinitialises, associes a leur ancien profil
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ResetConductorCommand::ResetConductorCommand(
|
||||
const QHash<Conductor *, ConductorProfilesGroup> &cp,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("R\351initialiser ") + QET::ElementsAndConductorsSentence(0, cp.count()), parent),
|
||||
conductors_profiles(cp)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ResetConductorCommand::~ResetConductorCommand() {
|
||||
}
|
||||
|
||||
/// Annule la reinitialisation des conducteurs
|
||||
void ResetConductorCommand::undo() {
|
||||
foreach(Conductor *c, conductors_profiles.keys()) {
|
||||
c -> setProfiles(conductors_profiles[c]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Refait la reinitialisation des conducteurs
|
||||
void ResetConductorCommand::redo() {
|
||||
foreach(Conductor *c, conductors_profiles.keys()) {
|
||||
c -> setProfiles(ConductorProfilesGroup());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param d Schema dont on modifie le cartouche
|
||||
@param old_ip Anciennes proprietes du cartouche
|
||||
@param new_ip Nouvelles proprietes du cartouche
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeInsetCommand::ChangeInsetCommand(
|
||||
Diagram *d,
|
||||
const InsetProperties &old_ip,
|
||||
const InsetProperties &new_ip,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modifier le cartouche"), parent),
|
||||
diagram(d),
|
||||
old_inset(old_ip),
|
||||
new_inset(new_ip)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeInsetCommand::~ChangeInsetCommand() {
|
||||
}
|
||||
|
||||
/// Annule la modification de cartouche
|
||||
void ChangeInsetCommand::undo() {
|
||||
diagram -> border_and_inset.importInset(old_inset);
|
||||
diagram -> invalidate(diagram -> border());
|
||||
}
|
||||
|
||||
/// Refait la modification de cartouche
|
||||
void ChangeInsetCommand::redo() {
|
||||
diagram -> border_and_inset.importInset(new_inset);
|
||||
diagram -> invalidate(diagram -> border());
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema modifie
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeBorderCommand::ChangeBorderCommand(Diagram *dia, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modifier les dimensions du sch\351ma"), parent),
|
||||
diagram(dia),
|
||||
columnsCountDifference(0),
|
||||
columnsHeightDifference(0.0),
|
||||
columnsWidthDifference(0.0),
|
||||
headersHeightDifference(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeBorderCommand::~ChangeBorderCommand() {
|
||||
}
|
||||
|
||||
/**
|
||||
Applique les changements au schema
|
||||
@param coeff comme les changements s'expriment sous forme de nombres dont
|
||||
il suffit d'inverser le signe pour les annuler, ces valeurs sont ici
|
||||
multipliees par le coefficient passe en parametre avant d'etre appliquees.
|
||||
Pour resumer : 1 pour refaire, -1 pour annuler.
|
||||
*/
|
||||
void ChangeBorderCommand::applyChanges(int coeff) {
|
||||
// reference vers l'objet border_and_inset du schema
|
||||
BorderInset &border = diagram -> border_and_inset;
|
||||
if (columnsCountDifference) {
|
||||
border.setNbColumns(border.nbColumn() + (columnsCountDifference * coeff));
|
||||
}
|
||||
if (columnsHeightDifference) {
|
||||
border.setColumnsHeight(border.columnsHeight() + (columnsHeightDifference * coeff));
|
||||
}
|
||||
if (columnsWidthDifference) {
|
||||
border.setColumnsWidth(border.columnsWidth() + (columnsWidthDifference * coeff));
|
||||
}
|
||||
if (headersHeightDifference) {
|
||||
border.setColumnsHeaderHeight(border.columnsHeaderHeight() + (headersHeightDifference * coeff));
|
||||
}
|
||||
border.adjustInsetToColumns();
|
||||
}
|
||||
|
||||
/// Annule les changements apportes au schema
|
||||
void ChangeBorderCommand::undo() {
|
||||
applyChanges(-1);
|
||||
}
|
||||
|
||||
/// Refait les changements apportes au schema
|
||||
void ChangeBorderCommand::redo() {
|
||||
applyChanges(1);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param c Le conducteur dont on modifie les proprietes
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeConductorPropertiesCommand::ChangeConductorPropertiesCommand(Conductor *c, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modifier les propri\351t\351s d'un conducteur"), parent),
|
||||
conductor(c),
|
||||
old_settings_set(false),
|
||||
new_settings_set(false)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeConductorPropertiesCommand::~ChangeConductorPropertiesCommand() {
|
||||
}
|
||||
|
||||
/// definit l'ancienne configuration
|
||||
void ChangeConductorPropertiesCommand::setOldSettings(const ConductorProperties &properties) {
|
||||
old_properties = properties;
|
||||
old_settings_set = true;
|
||||
}
|
||||
|
||||
/// definit la nouvelle configuration
|
||||
void ChangeConductorPropertiesCommand::setNewSettings(const ConductorProperties &properties) {
|
||||
new_properties = properties;
|
||||
new_settings_set = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Annule les changements - Attention : les anciens et nouveaux parametres
|
||||
doivent avoir ete definis a l'aide de setNewSettings et setOldSettings
|
||||
*/
|
||||
void ChangeConductorPropertiesCommand::undo() {
|
||||
if (old_settings_set && new_settings_set) {
|
||||
conductor -> setProperties(old_properties);
|
||||
conductor -> update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Refait les changements - Attention : les anciens et nouveaux parametres
|
||||
doivent avoir ete definis a l'aide de setNewSettings et setOldSettings
|
||||
*/
|
||||
void ChangeConductorPropertiesCommand::redo() {
|
||||
if (old_settings_set && new_settings_set) {
|
||||
conductor -> setProperties(new_properties);
|
||||
conductor -> update();
|
||||
}
|
||||
}
|
||||
394
sources/diagramcommands.h
Normal file
394
sources/diagramcommands.h
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 DIAGRAM_COMMANDS_H
|
||||
#define DIAGRAM_COMMANDS_H
|
||||
#include "qet.h"
|
||||
#include "diagram.h"
|
||||
#include "diagramcontent.h"
|
||||
#include "diagramtextitem.h"
|
||||
#include "conductor.h"
|
||||
#include "conductorproperties.h"
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe represente l'action d'ajouter un element au schema
|
||||
*/
|
||||
class AddElementCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AddElementCommand(Diagram *, Element *, const QPointF &, QUndoCommand * = 0);
|
||||
virtual ~AddElementCommand();
|
||||
private:
|
||||
AddElementCommand(const AddElementCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// element ajoute
|
||||
Element *element;
|
||||
/// schema sur lequel on ajoute l'element
|
||||
Diagram *diagram;
|
||||
/// position de l'element sur le schema
|
||||
QPointF position;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action d'ajouter du texte au schema
|
||||
*/
|
||||
class AddTextCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AddTextCommand(Diagram *, DiagramTextItem *, const QPointF &, QUndoCommand * = 0);
|
||||
virtual ~AddTextCommand();
|
||||
private:
|
||||
AddTextCommand(const AddTextCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// texte ajoute
|
||||
DiagramTextItem *textitem;
|
||||
/// schema sur lequel on ajoute le texte
|
||||
Diagram *diagram;
|
||||
/// position du texte sur le schema
|
||||
QPointF position;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action d'ajouter un conducteur au schema
|
||||
*/
|
||||
class AddConductorCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AddConductorCommand(Diagram *, Conductor *, QUndoCommand * = 0);
|
||||
virtual ~AddConductorCommand();
|
||||
private:
|
||||
AddConductorCommand(const AddConductorCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// conducteur ajoute
|
||||
Conductor *conductor;
|
||||
/// schema auquel on ajoute le conducteur
|
||||
Diagram *diagram;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de supprimer des elements et / ou
|
||||
conducteurs d'un schema
|
||||
*/
|
||||
class DeleteElementsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DeleteElementsCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
|
||||
virtual ~DeleteElementsCommand();
|
||||
private:
|
||||
DeleteElementsCommand(const DeleteElementsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// contenu enleve
|
||||
DiagramContent removed_content;
|
||||
/// schema dont on supprime des elements et conducteurs
|
||||
Diagram *diagram;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de coller quelque chose sur un schema
|
||||
*/
|
||||
class PasteDiagramCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PasteDiagramCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
|
||||
virtual ~PasteDiagramCommand();
|
||||
private:
|
||||
PasteDiagramCommand(const PasteDiagramCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// contenu ajoute
|
||||
DiagramContent content;
|
||||
/// schema sur lequel on colle les elements et conducteurs
|
||||
Diagram *diagram;
|
||||
/// entien pour filtrer le contenu du schema
|
||||
int filter;
|
||||
/// booleen pour empecher le premier appel a redo
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de supprimer des elements et / ou
|
||||
conducteurs d'un schema
|
||||
*/
|
||||
class CutDiagramCommand : public DeleteElementsCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
CutDiagramCommand(Diagram *, const DiagramContent &, QUndoCommand * = 0);
|
||||
virtual ~CutDiagramCommand();
|
||||
private:
|
||||
CutDiagramCommand(const CutDiagramCommand &);
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de deplacer des elements et des
|
||||
conducteurs sur un schema
|
||||
*/
|
||||
class MoveElementsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
MoveElementsCommand(Diagram *, const DiagramContent &, const QPointF &m, QUndoCommand * = 0);
|
||||
virtual ~MoveElementsCommand();
|
||||
private:
|
||||
MoveElementsCommand(const MoveElementsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
virtual void move(const QPointF &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// schema sur lequel on deplace les elements
|
||||
Diagram *diagram;
|
||||
/// contenu a deplacer
|
||||
DiagramContent content_to_move;
|
||||
/// mouvement effectue
|
||||
QPointF movement;
|
||||
/// booleen pour ne pas executer le premier redo()
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente la modification d'un champ de texte
|
||||
*/
|
||||
class ChangeDiagramTextCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeDiagramTextCommand(DiagramTextItem *, const QString &before, const QString &after, QUndoCommand * = 0);
|
||||
virtual ~ChangeDiagramTextCommand();
|
||||
private:
|
||||
ChangeDiagramTextCommand(const ChangeDiagramTextCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// DiagramTextItem modifie
|
||||
DiagramTextItem *text_item;
|
||||
/// texte avant changement
|
||||
QString text_before;
|
||||
/// texte apres changement
|
||||
QString text_after;
|
||||
/// booleen pour ne pas executer le premier redo()
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de pivoter plusieurs elements
|
||||
*/
|
||||
class RotateElementsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
RotateElementsCommand(const QHash<Element *, QET::Orientation> &elements, QUndoCommand * = 0);
|
||||
virtual ~RotateElementsCommand();
|
||||
private:
|
||||
RotateElementsCommand(const RotateElementsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// elements pivotes associes a leur ancienne orientation
|
||||
QHash<Element *, QET::Orientation> elements_to_rotate;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier un conducteur
|
||||
*/
|
||||
class ChangeConductorCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeConductorCommand(Conductor *, const ConductorProfile &, const ConductorProfile &, Qt::Corner, QUndoCommand * = 0);
|
||||
virtual ~ChangeConductorCommand();
|
||||
private:
|
||||
ChangeConductorCommand(const ChangeConductorCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// conducteur modifie
|
||||
Conductor *conductor;
|
||||
/// profil avant changement
|
||||
ConductorProfile old_profile;
|
||||
/// profil apres changement
|
||||
ConductorProfile new_profile;
|
||||
/// Type de trajet
|
||||
Qt::Corner path_type;
|
||||
/// booleen pour ne pas executer le premier redo()
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de reinitialiser des conducteurs
|
||||
*/
|
||||
class ResetConductorCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ResetConductorCommand(const QHash<Conductor *, ConductorProfilesGroup> &, QUndoCommand * = 0);
|
||||
virtual ~ResetConductorCommand();
|
||||
private:
|
||||
ResetConductorCommand(const ResetConductorCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// conducteurs reinitialises associes a leur ancien profil
|
||||
QHash<Conductor *, ConductorProfilesGroup> conductors_profiles;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier les informations du cartouche d'un schema
|
||||
*/
|
||||
class ChangeInsetCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeInsetCommand(Diagram *, const InsetProperties &, const InsetProperties &, QUndoCommand * = 0);
|
||||
virtual ~ChangeInsetCommand();
|
||||
private:
|
||||
ChangeInsetCommand(const ChangeInsetCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// schema modifie
|
||||
Diagram *diagram;
|
||||
/// proprietes avant changement
|
||||
InsetProperties old_inset;
|
||||
/// proprietes apres changement
|
||||
InsetProperties new_inset;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier :
|
||||
-le nombre de colonnes d'un schema
|
||||
-la hauteur des colonnes
|
||||
-la largeur des colonnes
|
||||
-la hauteur des en-tetes des colonnes
|
||||
*/
|
||||
class ChangeBorderCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeBorderCommand(Diagram *, QUndoCommand * = 0);
|
||||
virtual ~ChangeBorderCommand();
|
||||
private:
|
||||
ChangeBorderCommand(const ChangeBorderCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
private:
|
||||
virtual void applyChanges(int = 1);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// schema modifie
|
||||
Diagram *diagram;
|
||||
public:
|
||||
/// nombre de colonnes ajoutees / enlevees
|
||||
int columnsCountDifference;
|
||||
/// delta pour la hauteur des colonnes
|
||||
qreal columnsHeightDifference;
|
||||
/// delta pour la largeur des colonnes
|
||||
qreal columnsWidthDifference;
|
||||
/// delta pour la hauteur des entetes des colonnes
|
||||
qreal headersHeightDifference;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier les proprietes d'un conducteur
|
||||
*/
|
||||
class ChangeConductorPropertiesCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeConductorPropertiesCommand(Conductor *, QUndoCommand * = 0);
|
||||
virtual ~ChangeConductorPropertiesCommand();
|
||||
private:
|
||||
ChangeConductorPropertiesCommand(const ChangeConductorPropertiesCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
virtual void setOldSettings(const ConductorProperties &);
|
||||
virtual void setNewSettings(const ConductorProperties &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// conducteur modifie
|
||||
Conductor *conductor;
|
||||
/// anciennes proprietes
|
||||
ConductorProperties old_properties;
|
||||
/// nouvelles proprietes
|
||||
ConductorProperties new_properties;
|
||||
/// booleens indiquant si les proprietes ont ete definies ou non
|
||||
bool old_settings_set;
|
||||
bool new_settings_set;
|
||||
};
|
||||
#endif
|
||||
133
sources/diagramcontent.cpp
Normal file
133
sources/diagramcontent.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "diagramcontent.h"
|
||||
#include <QGraphicsItem>
|
||||
#include "element.h"
|
||||
#include "diagramtextitem.h"
|
||||
#include "conductor.h"
|
||||
|
||||
/**
|
||||
Constructeur par defaut. Ne contient rien.
|
||||
*/
|
||||
DiagramContent::DiagramContent() {
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur de copie.
|
||||
*/
|
||||
DiagramContent::DiagramContent(const DiagramContent &other) :
|
||||
elements(other.elements),
|
||||
textFields(other.textFields),
|
||||
conductorsToUpdate(other.conductorsToUpdate),
|
||||
conductorsToMove(other.conductorsToMove),
|
||||
otherConductors(other.otherConductors)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
*/
|
||||
DiagramContent::~DiagramContent() {
|
||||
}
|
||||
|
||||
/**
|
||||
@param filter Types de conducteurs desires
|
||||
@return tous les conducteurs
|
||||
*/
|
||||
QList<Conductor *> DiagramContent::conductors(int filter) const {
|
||||
QList<Conductor *> result;
|
||||
if (filter & ConductorsToMove) result += conductorsToMove;
|
||||
if (filter & ConductorsToUpdate) result += conductorsToUpdate.keys();
|
||||
if (filter & OtherConductors) result += otherConductors;
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
Vide le conteneur
|
||||
*/
|
||||
void DiagramContent::clear() {
|
||||
elements.clear();
|
||||
textFields.clear();
|
||||
conductorsToUpdate.clear();
|
||||
conductorsToMove.clear();
|
||||
otherConductors.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@param filter Types desires
|
||||
@return la liste des items formant le contenu du schema
|
||||
*/
|
||||
QList<QGraphicsItem *> DiagramContent::items(int filter) const {
|
||||
QList<QGraphicsItem *> items_list;
|
||||
foreach(QGraphicsItem *qgi, conductors(filter)) items_list << qgi;
|
||||
if (filter & Elements) foreach(QGraphicsItem *qgi, elements) items_list << qgi;
|
||||
if (filter & TextFields) foreach(QGraphicsItem *qgi, textFields) items_list << qgi;
|
||||
return(items_list);
|
||||
}
|
||||
|
||||
/**
|
||||
@param filter Types desires
|
||||
@return le nombre d'items formant le contenu du schema
|
||||
*/
|
||||
int DiagramContent::count(int filter) const {
|
||||
int count = 0;
|
||||
if (filter & Elements) count += elements.count();
|
||||
if (filter & TextFields) count += textFields.count();
|
||||
if (filter & ConductorsToMove) count += conductorsToMove.count();
|
||||
if (filter & ConductorsToUpdate) count += conductorsToUpdate.count();
|
||||
if (filter & OtherConductors) count += otherConductors.count();
|
||||
return(count);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de composer rapidement la proposition "x elements, y conducteurs et
|
||||
z champs de texte".
|
||||
@param filter Types desires
|
||||
@return la proposition decrivant le contenu.
|
||||
*/
|
||||
QString DiagramContent::sentence(int filter) const {
|
||||
int elements_count = (filter & Elements) ? elements.count() : 0;
|
||||
int conductors_count = conductors(filter).count();
|
||||
int textfields_count = (filter & TextFields) ? textFields.count() : 0;
|
||||
|
||||
return(
|
||||
QET::ElementsAndConductorsSentence(
|
||||
elements_count,
|
||||
conductors_count,
|
||||
textfields_count
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de debugger un contenu de schema
|
||||
@param d Object QDebug a utiliser pour l'affichage des informations de debug
|
||||
@param c Contenu de schema a debugger
|
||||
*/
|
||||
QDebug &operator<<(QDebug d, DiagramContent &) {
|
||||
d << "DiagramContent {" << "\n";
|
||||
/*
|
||||
FIXME Le double-heritage QObject / QGraphicsItem a casse cet operateur
|
||||
d << " elements :" << c.elements << "\n";
|
||||
d << " conductorsToUpdate :" << c.conductorsToUpdate.keys() << "\n";
|
||||
d << " conductorsToMove :" << c.conductorsToMove << "\n";
|
||||
d << " otherConductors :" << c.otherConductors << "\n";
|
||||
*/
|
||||
d << "}";
|
||||
return(d.space());
|
||||
}
|
||||
70
sources/diagramcontent.h
Normal file
70
sources/diagramcontent.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 DIAGRAM_CONTENT_H
|
||||
#define DIAGRAM_CONTENT_H
|
||||
#include <QtGui>
|
||||
class Conductor;
|
||||
class Element;
|
||||
class Terminal;
|
||||
class DiagramTextItem;
|
||||
/**
|
||||
Cette classe est un conteneur pour passer facilement le contenu d'un schema
|
||||
a une fonction. Il permet d'acceder rapidement aux differents types de
|
||||
composants que l'on peut trouver sur un schema, comme les elements, les
|
||||
champs de texte, les conducteurs (a deplacer ou a mettre a jour, en cas de
|
||||
deplacements), etc.
|
||||
A noter que ce container ne contient pas systematiquement l'integralite
|
||||
d'un schema. Il peut n'en contenir qu'une partie, typiquement les
|
||||
composants selectionnes.
|
||||
*/
|
||||
class DiagramContent {
|
||||
public:
|
||||
DiagramContent();
|
||||
DiagramContent(const DiagramContent &);
|
||||
~DiagramContent();
|
||||
|
||||
/// Permet de filtrer facilement les differentes parties d'un schema
|
||||
enum Filter {
|
||||
Elements = 1,
|
||||
TextFields = 2,
|
||||
ConductorsToMove = 4,
|
||||
ConductorsToUpdate = 8,
|
||||
OtherConductors = 16,
|
||||
AnyConductor = 28,
|
||||
All = 31
|
||||
};
|
||||
|
||||
/// Elements de texte du schema
|
||||
QList<Element *> elements;
|
||||
/// Champs de texte du schema
|
||||
QList<DiagramTextItem *> textFields;
|
||||
/// Conducteurs a mettre a jour du schema
|
||||
QHash<Conductor *, Terminal *> conductorsToUpdate;
|
||||
/// Conducteurs a deplacer du schema
|
||||
QList<Conductor *> conductorsToMove;
|
||||
/// Conducteurs isoles (ni a deplacer, ni a mettre a jour)
|
||||
QList<Conductor *> otherConductors;
|
||||
|
||||
QList<Conductor *> conductors(int = AnyConductor) const;
|
||||
QList<QGraphicsItem *> items(int = All) const;
|
||||
QString sentence(int = All) const;
|
||||
int count(int = All) const;
|
||||
void clear();
|
||||
};
|
||||
QDebug &operator<<(QDebug, DiagramContent &);
|
||||
#endif
|
||||
302
sources/diagramprintdialog.cpp
Normal file
302
sources/diagramprintdialog.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "diagramprintdialog.h"
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param dia Schema a imprimer
|
||||
@param printer Imprimante a utiliser
|
||||
@param parent Widget parent du dialogue
|
||||
*/
|
||||
DiagramPrintDialog::DiagramPrintDialog(Diagram *dia, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
diagram(dia),
|
||||
dialog(0)
|
||||
{
|
||||
// initialise l'imprimante
|
||||
printer = new QPrinter();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
DiagramPrintDialog::~DiagramPrintDialog() {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nom du PDF
|
||||
*/
|
||||
QString DiagramPrintDialog::PDFName() const {
|
||||
return(pdf_name);
|
||||
}
|
||||
|
||||
/**
|
||||
Execute le dialogue d'impression
|
||||
*/
|
||||
void DiagramPrintDialog::exec() {
|
||||
|
||||
// affichage du dialogue d'impression standard
|
||||
QPrintDialog print_dialog(printer);
|
||||
print_dialog.setEnabledOptions(QAbstractPrintDialog::PrintToFile);
|
||||
#ifndef Q_OS_WIN32
|
||||
if (!pdf_name.isEmpty()) printer -> setOutputFileName(pdf_name);
|
||||
#endif
|
||||
if (print_dialog.exec() == QDialog::Rejected) return;
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
// effectue l'impression en elle-meme
|
||||
print();
|
||||
}
|
||||
|
||||
/**
|
||||
@param fullPage true pour utiliser toute la feuille dans le calcul
|
||||
@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));
|
||||
}
|
||||
|
||||
/**
|
||||
@param fullPage true pour utiliser toute la feuille dans le calcul
|
||||
@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 {
|
||||
// note : pageRect et Paper Rect tiennent compte de l'orientation du papier
|
||||
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())));
|
||||
return(h_pages_count);
|
||||
}
|
||||
|
||||
/**
|
||||
@param fullPage true pour utiliser toute la feuille dans le calcul
|
||||
@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 {
|
||||
// note : pageRect et Paper Rect tiennent compte de l'orientation du papier
|
||||
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())));
|
||||
return(v_pages_count);
|
||||
}
|
||||
|
||||
/**
|
||||
Construit un dialogue non standard pour demander les pages a imprimer a l'utilisateur
|
||||
*/
|
||||
void DiagramPrintDialog::buildDialog() {
|
||||
dialog = new QDialog();
|
||||
dialog -> setWindowTitle(tr("Options d'impression"));
|
||||
options_label = new QLabel();
|
||||
use_full_page = new QCheckBox(tr("Utiliser toute la feuille"));
|
||||
fit_diagram_to_page = new QCheckBox(tr("Adapter le sch\351ma \340 la page"));
|
||||
range_from_label = new QLabel(tr("Plage de "));
|
||||
start_page = new QSpinBox();
|
||||
to_label = new QLabel(tr(" \340 "));
|
||||
end_page = new QSpinBox();
|
||||
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);
|
||||
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(dialog);
|
||||
dialog_layout -> addWidget(options_label);
|
||||
dialog_layout -> addWidget(use_full_page);
|
||||
dialog_layout -> addWidget(fit_diagram_to_page);
|
||||
dialog_layout -> addLayout(pages_layout);
|
||||
dialog_layout -> addStretch();
|
||||
dialog_layout -> addWidget(buttons);
|
||||
|
||||
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()));
|
||||
|
||||
updateDialog();
|
||||
}
|
||||
|
||||
/**
|
||||
Assure la coherence du dialogue
|
||||
*/
|
||||
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;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
S'assure que la derniere page ne soit pas inferieure a la premiere page
|
||||
*/
|
||||
void DiagramPrintDialog::checkEndPage() {
|
||||
if (end_page -> value() < start_page -> value()) {
|
||||
end_page -> blockSignals(true);
|
||||
end_page -> setValue(start_page -> value());
|
||||
end_page -> blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@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
|
||||
*/
|
||||
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);
|
||||
|
||||
// QPainter utiliser pour effectuer le rendu
|
||||
QPainter qp(printer);
|
||||
|
||||
// impression physique (!= fichier PDF)
|
||||
if (printer -> outputFileName().isEmpty()) {
|
||||
// lorsqu'on imprime en paysage sur imprimante reelle, il faut pivoter soi-meme le rendu
|
||||
if (printer -> orientation() == QPrinter::Landscape) {
|
||||
qp.rotate(90.0);
|
||||
qp.translate(0.0, -printer -> pageRect().height());
|
||||
}
|
||||
}
|
||||
|
||||
diagram -> setDisplayGrid(false);
|
||||
diagram -> setDrawTerminals(false);
|
||||
|
||||
if (fit_page) {
|
||||
// impression adaptee sur une seule page
|
||||
diagram -> render(&qp, QRectF(), diagram -> border(), Qt::KeepAspectRatio);
|
||||
} else {
|
||||
// impression sur une ou plusieurs pages
|
||||
QRect diagram_rect = diagram -> border().toRect();
|
||||
QRect printed_area = full_page ? printer -> paperRect() : printer -> pageRect();
|
||||
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);
|
||||
|
||||
QVector< QVector< QRect > > pages_grid;
|
||||
// le schema est imprime sur une matrice de feuilles
|
||||
// parcourt les lignes de la matrice
|
||||
int y_offset = 0;
|
||||
for (int i = 0 ; i < v_pages_count ; ++ i) {
|
||||
pages_grid << QVector< QRect >();
|
||||
|
||||
// parcourt les feuilles de la ligne
|
||||
int x_offset = 0;
|
||||
for (int j = 0 ; j < h_pages_count ; ++ j) {
|
||||
pages_grid.last() << QRect(
|
||||
QPoint(x_offset, y_offset),
|
||||
QSize(
|
||||
qMin(used_width, diagram_rect.width() - x_offset),
|
||||
qMin(used_height, diagram_rect.height() - y_offset)
|
||||
)
|
||||
);
|
||||
x_offset += used_width;
|
||||
}
|
||||
|
||||
y_offset += used_height;
|
||||
}
|
||||
|
||||
// ne retient que les pages a imprimer
|
||||
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) {
|
||||
pages_to_print << pages_grid.at(i).at(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parcourt les pages pour impression
|
||||
for (int i = 0 ; i < pages_to_print.count() ; ++ i) {
|
||||
QRect current_rect(pages_to_print.at(i));
|
||||
diagram -> render(
|
||||
&qp,
|
||||
QRect(QPoint(0,0), current_rect.size()),
|
||||
current_rect.translated(diagram_rect.topLeft()),
|
||||
Qt::KeepAspectRatio
|
||||
);
|
||||
if (i != pages_to_print.count() - 1) {
|
||||
printer -> newPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
diagram -> setDrawTerminals(true);
|
||||
diagram -> setDisplayGrid(true);
|
||||
}
|
||||
71
sources/diagramprintdialog.h
Normal file
71
sources/diagramprintdialog.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 DIAGRAM_PRINT_DIALOG_H
|
||||
#define DIAGRAM_PRINT_DIALOG_H
|
||||
#include <QtGui>
|
||||
#include "diagram.h"
|
||||
/**
|
||||
Cette classe represente le dialogue de configuration de l'impression d'un
|
||||
schema electrique.
|
||||
Elle se charge egalement de l'impression elle-meme
|
||||
*/
|
||||
class DiagramPrintDialog : public QWidget {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
DiagramPrintDialog(Diagram *, QWidget * = 0);
|
||||
virtual ~DiagramPrintDialog();
|
||||
private:
|
||||
DiagramPrintDialog(const DiagramPrintDialog &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setPDFName(const QString &);
|
||||
QString PDFName() const;
|
||||
int pagesCount(bool = false) const;
|
||||
int horizontalPagesCount(bool = false) const;
|
||||
int verticalPagesCount(bool = false) const;
|
||||
void exec();
|
||||
|
||||
private:
|
||||
void buildDialog();
|
||||
void print();
|
||||
|
||||
private slots:
|
||||
void updateDialog();
|
||||
void checkStartPage();
|
||||
void checkEndPage();
|
||||
void setPagesRangeVisible(bool);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
Diagram *diagram;
|
||||
QPrinter *printer;
|
||||
QString pdf_name;
|
||||
QDialog *dialog;
|
||||
QLabel *options_label;
|
||||
QLabel *range_from_label;
|
||||
QLabel *to_label;
|
||||
QCheckBox *use_full_page;
|
||||
QCheckBox *fit_diagram_to_page;
|
||||
QSpinBox *start_page;
|
||||
QSpinBox *end_page;
|
||||
QDialogButtonBox *buttons;
|
||||
};
|
||||
#endif
|
||||
201
sources/diagramtextitem.cpp
Normal file
201
sources/diagramtextitem.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "diagramtextitem.h"
|
||||
#include "diagramcommands.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QGraphicsItem parent du champ de texte
|
||||
@param scene La scene a laquelle appartient le champ de texte
|
||||
*/
|
||||
DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsTextItem(parent, scene)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFont(QFont(QETApp::diagramTextsFont(), 9));
|
||||
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
|
||||
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QGraphicsItem parent du champ de texte
|
||||
@param scene La scene a laquelle appartient le champ de texte
|
||||
@param text Le texte affiche par le champ de texte
|
||||
*/
|
||||
DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsTextItem(text, parent, scene),
|
||||
previous_text(text)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFont(QFont(QETApp::diagramTextsFont(), 9));
|
||||
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
|
||||
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
DiagramTextItem::~DiagramTextItem() {
|
||||
}
|
||||
|
||||
/// @return le Diagram auquel ce texte appartient, ou 0 si ce texte est independant
|
||||
Diagram *DiagramTextItem::diagram() const {
|
||||
return(qobject_cast<Diagram *>(scene()));
|
||||
}
|
||||
|
||||
/**
|
||||
gere la perte de focus du champ de texte
|
||||
*/
|
||||
void DiagramTextItem::focusOutEvent(QFocusEvent *e) {
|
||||
QGraphicsTextItem::focusOutEvent(e);
|
||||
// signale la modification du texte si besoin
|
||||
if (toPlainText() != previous_text) {
|
||||
emit(diagramTextChanged(this, previous_text, toPlainText()));
|
||||
previous_text = toPlainText();
|
||||
}
|
||||
|
||||
// deselectionne le texte
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
|
||||
if (flags() & QGraphicsItem::ItemIsMovable) {
|
||||
// hack a la con pour etre re-entrant
|
||||
setTextInteractionFlags(Qt::NoTextInteraction);
|
||||
QTimer::singleShot(0, this, SIGNAL(lostFocus()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de lire le texte a mettre dans le champ a partir d'un element XML.
|
||||
Cette methode se base sur la position du champ pour assigner ou non la
|
||||
valeur a ce champ.
|
||||
@param e L'element XML representant le champ de texte
|
||||
*/
|
||||
void DiagramTextItem::fromXml(const QDomElement &e) {
|
||||
setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
|
||||
setPlainText(e.attribute("text"));
|
||||
previous_text = e.attribute("text");
|
||||
}
|
||||
|
||||
/**
|
||||
@param document Le document XML a utiliser
|
||||
@return L'element XML representant ce champ de texte
|
||||
*/
|
||||
QDomElement DiagramTextItem::toXml(QDomDocument &document) const {
|
||||
QDomElement result = document.createElement("input");
|
||||
result.setAttribute("x", pos().x());
|
||||
result.setAttribute("y", pos().y());
|
||||
result.setAttribute("text", toPlainText());
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les double-clics sur ce champ de texte.
|
||||
@param event un QGraphicsSceneMouseEvent decrivant le double-clic
|
||||
*/
|
||||
void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
|
||||
if (flags() & QGraphicsItem::ItemIsMovable && !(textInteractionFlags() & Qt::TextEditable)) {
|
||||
// rend le champ de texte editable
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
|
||||
// simule un clic simple, ce qui edite le champ de texte
|
||||
QGraphicsSceneMouseEvent *mouseEvent = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMousePress);
|
||||
mouseEvent -> setAccepted(true);
|
||||
mouseEvent -> setPos(event -> pos());
|
||||
mouseEvent -> setScenePos(event -> scenePos());
|
||||
mouseEvent -> setScreenPos(event -> screenPos());
|
||||
mouseEvent -> setButtonDownPos(Qt::LeftButton, event -> buttonDownPos(Qt::LeftButton));
|
||||
mouseEvent -> setButtonDownScreenPos(Qt::LeftButton, event -> buttonDownScreenPos(Qt::LeftButton));
|
||||
mouseEvent -> setButtonDownScenePos(Qt::LeftButton, event -> buttonDownScenePos(Qt::LeftButton));
|
||||
mouseEvent -> setWidget(event -> widget());
|
||||
QGraphicsTextItem::mousePressEvent(mouseEvent);
|
||||
delete mouseEvent;
|
||||
} else {
|
||||
QGraphicsTextItem::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements de souris lies au champ de texte
|
||||
*/
|
||||
void DiagramTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (textInteractionFlags() & Qt::TextEditable) {
|
||||
QGraphicsTextItem::mouseMoveEvent(e);
|
||||
} else if ((flags() & QGraphicsItem::ItemIsMovable) && (e -> buttons() & Qt::LeftButton)) {
|
||||
QPointF oldPos = pos();
|
||||
setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton)));
|
||||
if (Diagram *diagram_ptr = diagram()) {
|
||||
diagram_ptr -> moveElements(pos() - oldPos, this);
|
||||
}
|
||||
} else e -> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le relachement de souris
|
||||
Cette methode a ete reimplementee pour tenir a jour la liste des elements
|
||||
et conducteurs a deplacer au niveau du schema.
|
||||
*/
|
||||
void DiagramTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (Diagram *diagram_ptr = diagram()) {
|
||||
if ((flags() & QGraphicsItem::ItemIsMovable) && (!diagram_ptr -> current_movement.isNull())) {
|
||||
diagram_ptr -> undoStack().push(
|
||||
new MoveElementsCommand(
|
||||
diagram_ptr,
|
||||
diagram_ptr -> selectedContent(),
|
||||
diagram_ptr -> current_movement
|
||||
)
|
||||
);
|
||||
diagram_ptr -> current_movement = QPointF();
|
||||
}
|
||||
diagram_ptr -> invalidateMovedElements();
|
||||
}
|
||||
QGraphicsTextItem::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position du champ de texte en veillant a ce qu'il
|
||||
reste sur la grille du schema auquel il appartient.
|
||||
@param p Nouvelles coordonnees de l'element
|
||||
*/
|
||||
void DiagramTextItem::setPos(const QPointF &p) {
|
||||
if (p == pos()) return;
|
||||
// pas la peine de positionner sur la grille si l'element n'est pas sur un Diagram
|
||||
if (scene()) {
|
||||
// arrondit l'abscisse a 10 px pres
|
||||
int p_x = qRound(p.x() / (Diagram::xGrid * 1.0)) * Diagram::xGrid;
|
||||
// arrondit l'ordonnee a 10 px pres
|
||||
int p_y = qRound(p.y() / (Diagram::yGrid * 1.0)) * Diagram::yGrid;
|
||||
QGraphicsTextItem::setPos(p_x, p_y);
|
||||
} else QGraphicsTextItem::setPos(p);
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position du champ de texte en veillant a ce que l'il
|
||||
reste sur la grille du schema auquel il appartient.
|
||||
@param x Nouvelle abscisse de l'element
|
||||
@param y Nouvelle ordonnee de l'element
|
||||
*/
|
||||
void DiagramTextItem::setPos(qreal x, qreal y) {
|
||||
setPos(QPointF(x, y));
|
||||
}
|
||||
|
||||
/// Rend le champ de texte non focusable
|
||||
void DiagramTextItem::setNonFocusable() {
|
||||
setFlag(QGraphicsTextItem::ItemIsFocusable, false);
|
||||
}
|
||||
69
sources/diagramtextitem.h
Normal file
69
sources/diagramtextitem.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 DIAGRAM_TEXT_ITEM_H
|
||||
#define DIAGRAM_TEXT_ITEM_H
|
||||
#include <QtGui>
|
||||
#include "diagram.h"
|
||||
/**
|
||||
Cette classe represente un champ de texte editable sur le schema.
|
||||
*/
|
||||
class DiagramTextItem : public QGraphicsTextItem {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DiagramTextItem(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
DiagramTextItem(const QString &, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~DiagramTextItem();
|
||||
|
||||
// attributs
|
||||
public:
|
||||
enum { Type = UserType + 1004 };
|
||||
/// Texte precedent
|
||||
QString previous_text;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
/**
|
||||
Cette methode permet d'utiliser qgraphicsitem_cast sur cet objet
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
Diagram *diagram() const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QDomElement toXml(QDomDocument &) const;
|
||||
virtual void setPos(const QPointF &);
|
||||
virtual void setPos(qreal, qreal);
|
||||
|
||||
protected:
|
||||
virtual void focusOutEvent(QFocusEvent *);
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
|
||||
// signaux
|
||||
signals:
|
||||
/// signal emis lorsque le champ de texte perd le focus
|
||||
void lostFocus();
|
||||
/// signal emis lorsque le champ de texte a ete modifie
|
||||
void diagramTextChanged(DiagramTextItem *, const QString &, const QString &);
|
||||
|
||||
// slots
|
||||
public slots:
|
||||
void setNonFocusable();
|
||||
};
|
||||
#endif
|
||||
968
sources/diagramview.cpp
Normal file
968
sources/diagramview.cpp
Normal file
@@ -0,0 +1,968 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "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"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidegt parent de cette vue de schema
|
||||
*/
|
||||
DiagramView::DiagramView(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 -> undoStack().setClean();
|
||||
setDragMode(RubberBandDrag);
|
||||
setAcceptDrops(true);
|
||||
setWindowIcon(QIcon(":/ico/qet-16.png"));
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
adjustSceneRect();
|
||||
updateWindowTitle();
|
||||
|
||||
context_menu = new QMenu(this);
|
||||
paste_here = new QAction(QIcon(":/ico/paste.png"), tr("Coller ici"), this);
|
||||
connect(paste_here, SIGNAL(triggered()), this, SLOT(pasteHere()));
|
||||
|
||||
connect(scene, SIGNAL(selectionEmptinessChanged()), this, SIGNAL(selectionChanged()));
|
||||
connect(&(scene -> border_and_inset), SIGNAL(borderChanged(QRectF, QRectF)), this, SLOT(adjustSceneRect()));
|
||||
connect(&(scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(updateWindowTitle()));
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
DiagramView::~DiagramView() {
|
||||
}
|
||||
|
||||
/**
|
||||
appelle la methode select sur tous les elements de la liste d'elements
|
||||
*/
|
||||
void DiagramView::selectAll() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
QPainterPath path;
|
||||
path.addRect(scene -> itemsBoundingRect());
|
||||
scene -> setSelectionArea(path);
|
||||
}
|
||||
|
||||
/**
|
||||
appelle la methode deselect sur tous les elements de la liste d'elements
|
||||
*/
|
||||
void DiagramView::selectNothing() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
scene -> clearSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
Inverse l'etat de selection de tous les elements de la liste d'elements
|
||||
*/
|
||||
void DiagramView::selectInvert() {
|
||||
if (scene -> items().isEmpty()) return;
|
||||
foreach (QGraphicsItem *item, scene -> items()) item -> setSelected(!item -> isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime les composants selectionnes
|
||||
*/
|
||||
void DiagramView::deleteSelection() {
|
||||
DiagramContent removed_content = scene -> selectedContent();
|
||||
scene -> clearSelection();
|
||||
scene -> undoStack().push(new DeleteElementsCommand(scene, removed_content));
|
||||
adjustSceneRect();
|
||||
}
|
||||
|
||||
/**
|
||||
Pivote les composants selectionnes
|
||||
*/
|
||||
void DiagramView::rotateSelection() {
|
||||
QHash<Element *, QET::Orientation> elements_to_rotate;
|
||||
foreach (QGraphicsItem *item, scene -> selectedItems()) {
|
||||
if (Element *e = qgraphicsitem_cast<Element *>(item)) {
|
||||
elements_to_rotate.insert(e, e -> orientation().current());
|
||||
}
|
||||
}
|
||||
if (elements_to_rotate.isEmpty()) return;
|
||||
scene -> undoStack().push(new RotateElementsCommand(elements_to_rotate));
|
||||
}
|
||||
|
||||
/**
|
||||
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
gere les dragleaveevent
|
||||
@param e le QDragEnterEvent correspondant au drag'n drop sortant
|
||||
*/
|
||||
void DiagramView::dragLeaveEvent(QDragLeaveEvent *) {
|
||||
}
|
||||
|
||||
/**
|
||||
accepte ou refuse le drag'n drop en fonction du type de donnees entrant
|
||||
@param e le QDragMoveEvent correspondant au drag'n drop tente
|
||||
*/
|
||||
void DiagramView::dragMoveEvent(QDragMoveEvent *e) {
|
||||
if (e -> mimeData() -> hasFormat("text/plain")) e -> acceptProposedAction();
|
||||
else e-> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
gere les depots (drop) acceptes sur le Diagram
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le Diagram en mode visualisation
|
||||
*/
|
||||
void DiagramView::setVisualisationMode() {
|
||||
setDragMode(ScrollHandDrag);
|
||||
setInteractive(false);
|
||||
emit(modeChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le Diagram en mode Selection
|
||||
*/
|
||||
void DiagramView::setSelectionMode() {
|
||||
setDragMode(RubberBandDrag);
|
||||
setInteractive(true);
|
||||
emit(modeChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
|
||||
*/
|
||||
void DiagramView::zoomIn() {
|
||||
scale(4.0/3.0, 4.0/3.0);
|
||||
adjustGridToZoom();
|
||||
}
|
||||
|
||||
/**
|
||||
Retrecit le schema (-25% = inverse des +33 % de zoomPlus())
|
||||
*/
|
||||
void DiagramView::zoomOut() {
|
||||
scale(0.75, 0.75);
|
||||
adjustGridToZoom();
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit ou rectrecit le schema de facon a ce que tous les elements du
|
||||
schema soient visibles a l'ecran. S'il n'y a aucun element sur le schema,
|
||||
le zoom est reinitialise
|
||||
*/
|
||||
void DiagramView::zoomFit() {
|
||||
adjustSceneRect();
|
||||
fitInView(sceneRect(), Qt::KeepAspectRatio);
|
||||
adjustGridToZoom();
|
||||
}
|
||||
|
||||
/**
|
||||
Reinitialise le zoom
|
||||
*/
|
||||
void DiagramView::zoomReset() {
|
||||
resetMatrix();
|
||||
adjustGridToZoom();
|
||||
}
|
||||
|
||||
/**
|
||||
copie les elements selectionnes du schema dans le presse-papier puis les supprime
|
||||
*/
|
||||
void DiagramView::cut() {
|
||||
copy();
|
||||
DiagramContent cut_content = scene -> selectedContent();
|
||||
scene -> clearSelection();
|
||||
scene -> undoStack().push(new CutDiagramCommand(scene, cut_content));
|
||||
}
|
||||
|
||||
/**
|
||||
copie les elements selectionnes du schema dans le presse-papier
|
||||
*/
|
||||
void DiagramView::copy() {
|
||||
QClipboard *presse_papier = QApplication::clipboard();
|
||||
QString contenu_presse_papier = scene -> toXml(false).toString(4);
|
||||
if (presse_papier -> supportsSelection()) presse_papier -> setText(contenu_presse_papier, QClipboard::Selection);
|
||||
presse_papier -> setText(contenu_presse_papier);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les elements contenus dans le presse-papier dans le schema
|
||||
@param pos coin superieur gauche (en coordonnees de la scene) du rectangle
|
||||
englobant le contenu colle
|
||||
@param clipboard_mode Type de presse-papier a prendre en compte
|
||||
*/
|
||||
void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) {
|
||||
QString texte_presse_papier = QApplication::clipboard() -> text(clipboard_mode);
|
||||
if ((texte_presse_papier).isEmpty()) return;
|
||||
|
||||
QDomDocument document_xml;
|
||||
if (!document_xml.setContent(texte_presse_papier)) return;
|
||||
|
||||
// objet pour recuperer le contenu ajoute au schema par le coller
|
||||
DiagramContent content_pasted;
|
||||
scene -> fromXml(document_xml, 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();
|
||||
scene -> undoStack().push(new PasteDiagramCommand(scene, content_pasted));
|
||||
adjustSceneRect();
|
||||
}
|
||||
}
|
||||
|
||||
/// Colle le contenu du presse-papier sur le schema a la position de la souris
|
||||
void DiagramView::pasteHere() {
|
||||
paste(mapToScene(paste_here_pos));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les clics et plus particulierement :
|
||||
* le clic du milieu (= coller pour X11)
|
||||
* le clic pour ajouter un champ de texte independant
|
||||
*/
|
||||
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) {
|
||||
addDiagramTextAtPos(mapToScene(e -> pos()));
|
||||
is_adding_text = false;
|
||||
}
|
||||
QGraphicsView::mousePressEvent(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(
|
||||
0,
|
||||
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
|
||||
*/
|
||||
void DiagramView::wheelEvent(QWheelEvent *e) {
|
||||
// si la touche Ctrl est enfoncee, on zoome / dezoome
|
||||
if (e -> modifiers() & Qt::ControlModifier) {
|
||||
if (e -> delta() > 0) {
|
||||
zoomIn();
|
||||
} else {
|
||||
zoomOut();
|
||||
}
|
||||
} else {
|
||||
QAbstractScrollArea::wheelEvent(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
|
||||
*/
|
||||
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, this);
|
||||
ed.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Imprime le schema.
|
||||
*/
|
||||
void DiagramView::dialogPrint() {
|
||||
|
||||
// determine un nom possible pour le pdf
|
||||
QString pdf_file_name;
|
||||
if (!file_name.isEmpty()) {
|
||||
pdf_file_name = file_name;
|
||||
pdf_file_name.replace(QRegExp("\\.qet$", Qt::CaseInsensitive), "");
|
||||
} else {
|
||||
pdf_file_name = QDir::toNativeSeparators(QDir::homePath() + "/" + tr("schema"));
|
||||
}
|
||||
pdf_file_name += ".pdf";
|
||||
|
||||
DiagramPrintDialog print_dialog(scene, this);
|
||||
print_dialog.setPDFName(pdf_file_name);
|
||||
print_dialog.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Edite les informations du schema.
|
||||
*/
|
||||
void DiagramView::dialogEditInfos() {
|
||||
// recupere le cartouche du schema
|
||||
InsetProperties inset = scene -> border_and_inset.exportInset();
|
||||
|
||||
// recupere les dimensions du schema
|
||||
int columns_count_value = scene -> border_and_inset.nbColumn();
|
||||
int columns_width_value = qRound(scene -> border_and_inset.columnsWidth());
|
||||
int columns_height_value = qRound(scene -> border_and_inset.columnsHeight());
|
||||
|
||||
// construit le dialogue
|
||||
QDialog popup;
|
||||
popup.setMinimumWidth(400);
|
||||
popup.setWindowTitle(tr("Propri\351t\351s du sch\351ma"));
|
||||
|
||||
QGroupBox *diagram_size_box = new QGroupBox(tr("Dimensions du sch\351ma"), &popup);
|
||||
QGridLayout diagram_size_box_layout(diagram_size_box);
|
||||
|
||||
QLabel *ds1 = new QLabel(tr("Colonnes :"));
|
||||
|
||||
QSpinBox *columns_count = new QSpinBox(diagram_size_box);
|
||||
columns_count -> setMinimum(scene -> border_and_inset.minNbColumns());
|
||||
columns_count -> setValue(columns_count_value);
|
||||
|
||||
QSpinBox *columns_width = new QSpinBox(diagram_size_box);
|
||||
columns_width -> setMinimum(1);
|
||||
columns_width -> setSingleStep(10);
|
||||
columns_width -> setValue(columns_width_value);
|
||||
columns_width -> setPrefix(tr("\327"));
|
||||
columns_width -> setSuffix(tr("px"));
|
||||
|
||||
QLabel *ds2 = new QLabel(tr("Hauteur :"));
|
||||
|
||||
QSpinBox *columns_height = new QSpinBox(diagram_size_box);
|
||||
columns_height -> setRange(qRound(scene -> border_and_inset.minColumnsHeight()), 10000);
|
||||
columns_height -> setSingleStep(80);
|
||||
columns_height -> setValue(columns_height_value);
|
||||
|
||||
diagram_size_box_layout.addWidget(ds1, 0, 0);
|
||||
diagram_size_box_layout.addWidget(columns_count, 0, 1);
|
||||
diagram_size_box_layout.addWidget(columns_width, 0, 2);
|
||||
diagram_size_box_layout.addWidget(ds2, 1, 0);
|
||||
diagram_size_box_layout.addWidget(columns_height, 1, 1);
|
||||
diagram_size_box_layout.setColumnStretch(0, 1);
|
||||
diagram_size_box_layout.setColumnStretch(1, 1);
|
||||
diagram_size_box_layout.setColumnStretch(2, 1);
|
||||
diagram_size_box_layout.setColumnStretch(3, 500);
|
||||
|
||||
InsetPropertiesWidget *inset_infos = new InsetPropertiesWidget(inset, false, &popup);
|
||||
|
||||
// boutons
|
||||
QDialogButtonBox boutons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(&boutons, SIGNAL(accepted()), &popup, SLOT(accept()));
|
||||
connect(&boutons, SIGNAL(rejected()), &popup, SLOT(reject()));
|
||||
|
||||
// ajout dans une disposition verticale
|
||||
QVBoxLayout layout_v(&popup);
|
||||
layout_v.addWidget(diagram_size_box);
|
||||
layout_v.addWidget(inset_infos);
|
||||
layout_v.addStretch();
|
||||
layout_v.addWidget(&boutons);
|
||||
// si le dialogue est accepte
|
||||
if (popup.exec() == QDialog::Accepted) {
|
||||
InsetProperties new_inset = inset_infos -> insetProperties();
|
||||
|
||||
// s'il y a des modifications au cartouche
|
||||
if (new_inset != inset) {
|
||||
scene -> undoStack().push(new ChangeInsetCommand(scene, inset, new_inset));
|
||||
}
|
||||
|
||||
// s'il y a des modifications aux dimensions du schema
|
||||
if (
|
||||
columns_count_value != columns_count -> value() ||\
|
||||
columns_width_value != columns_width -> value() ||\
|
||||
columns_height_value != columns_height -> value()
|
||||
) {
|
||||
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
|
||||
cbc -> columnsCountDifference = columns_count -> value() - columns_count_value;
|
||||
cbc -> columnsWidthDifference = columns_width -> value() - columns_width_value;
|
||||
cbc -> columnsHeightDifference = columns_height -> value() - columns_height_value;
|
||||
scene -> undoStack().push(cbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return true s'il y a des elements selectionnes sur le schema, false sinon
|
||||
*/
|
||||
bool DiagramView::hasSelectedItems() {
|
||||
return(scene -> selectedItems().size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute une colonne au schema.
|
||||
*/
|
||||
void DiagramView::addColumn() {
|
||||
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
|
||||
cbc -> columnsCountDifference = 1;
|
||||
scene -> undoStack().push(cbc);
|
||||
}
|
||||
|
||||
/**
|
||||
Enleve une colonne au schema.
|
||||
*/
|
||||
void DiagramView::removeColumn() {
|
||||
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
|
||||
cbc -> columnsCountDifference = -1;
|
||||
scene -> undoStack().push(cbc);
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit le schema en hauteur
|
||||
*/
|
||||
void DiagramView::expand() {
|
||||
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
|
||||
cbc -> columnsHeightDifference = 80.0;
|
||||
scene -> undoStack().push(cbc);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrecit le schema en hauteur
|
||||
*/
|
||||
void DiagramView::shrink() {
|
||||
ChangeBorderCommand *cbc = new ChangeBorderCommand(scene);
|
||||
cbc -> columnsHeightDifference = -80.0;
|
||||
scene -> undoStack().push(cbc);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajuste le sceneRect (zone du schema visualisee par le DiagramView) afin que
|
||||
celui inclut a la fois les elements dans et en dehors du cadre et le cadre
|
||||
lui-meme.
|
||||
*/
|
||||
void DiagramView::adjustSceneRect() {
|
||||
QRectF old_scene_rect = sceneRect();
|
||||
|
||||
// rectangle delimitant l'ensemble des elements
|
||||
QRectF elements_bounding_rect = scene -> itemsBoundingRect();
|
||||
|
||||
// rectangle contenant le cadre = colonnes + cartouche
|
||||
QRectF border_bounding_rect = scene -> border().adjusted(-Diagram::margin, -Diagram::margin, Diagram::margin, Diagram::margin);
|
||||
|
||||
// ajuste la sceneRect
|
||||
QRectF new_scene_rect = elements_bounding_rect.united(border_bounding_rect);
|
||||
setSceneRect(new_scene_rect);
|
||||
|
||||
// met a jour la scene
|
||||
scene -> update(old_scene_rect.united(new_scene_rect));
|
||||
}
|
||||
|
||||
/**
|
||||
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()));
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive le dessin de grille selon la quantite de pixels affichee
|
||||
*/
|
||||
void DiagramView::adjustGridToZoom() {
|
||||
QRectF viewed_scene = viewedSceneRect();
|
||||
scene -> setDisplayGrid(viewed_scene.width() < 2000 || viewed_scene.height() < 2000);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle du schema (classe Diagram) visualise par ce DiagramView
|
||||
*/
|
||||
QRectF DiagramView::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));
|
||||
}
|
||||
|
||||
/**
|
||||
Affiche un dialogue permettant d'editer le conducteur selectionne.
|
||||
Ne fait rien s'il y a 0 ou plusieurs conducteurs selectionnes.
|
||||
*/
|
||||
void DiagramView::editConductor() {
|
||||
QList<Conductor *> selected_conductors(scene -> selectedConductors().toList());
|
||||
|
||||
// on ne peut editer qu'un conducteur a la fois
|
||||
if (selected_conductors.count() != 1) return;
|
||||
Conductor *edited_conductor = selected_conductors.first();
|
||||
|
||||
editConductor(edited_conductor);
|
||||
}
|
||||
|
||||
/**
|
||||
Edite le conducteur passe en parametre
|
||||
@param edited_conductor Conducteur a editer
|
||||
*/
|
||||
void DiagramView::editConductor(Conductor *edited_conductor) {
|
||||
if (!edited_conductor) return;
|
||||
|
||||
// initialise l'editeur de proprietes pour le conducteur
|
||||
ConductorProperties old_properties = edited_conductor -> properties();
|
||||
ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(old_properties);
|
||||
|
||||
// l'insere dans un dialogue
|
||||
QDialog conductor_dialog;
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s d'un conducteur"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
|
||||
dialog_layout -> addWidget(cpw);
|
||||
dialog_layout -> addStretch();
|
||||
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
dialog_layout -> addWidget(dbb);
|
||||
connect(dbb, SIGNAL(accepted()), &conductor_dialog, SLOT(accept()));
|
||||
connect(dbb, SIGNAL(rejected()), &conductor_dialog, SLOT(reject()));
|
||||
|
||||
// execute le dialogue et met a jour le conducteur
|
||||
if (conductor_dialog.exec() == QDialog::Accepted) {
|
||||
// recupere les nouvelles proprietes
|
||||
ConductorProperties new_properties = cpw -> conductorProperties();
|
||||
|
||||
if (new_properties != old_properties) {
|
||||
// initialise l'objet UndoCommand correspondant
|
||||
ChangeConductorPropertiesCommand *ccpc = new ChangeConductorPropertiesCommand(edited_conductor);
|
||||
ccpc -> setOldSettings(old_properties);
|
||||
ccpc -> setNewSettings(new_properties);
|
||||
diagram() -> undoStack().push(ccpc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Reinitialise le profil des conducteurs selectionnes
|
||||
*/
|
||||
void DiagramView::resetConductors() {
|
||||
// recupere les conducteurs selectionnes
|
||||
QSet<Conductor *> selected_conductors = scene -> selectedConductors();
|
||||
|
||||
// repere les conducteurs modifies (= profil non nul)
|
||||
QHash<Conductor *, ConductorProfilesGroup> conductors_and_profiles;
|
||||
foreach(Conductor *conductor, selected_conductors) {
|
||||
ConductorProfilesGroup profile = conductor -> profiles();
|
||||
if (
|
||||
!profile[Qt::TopLeftCorner].isNull() ||\
|
||||
!profile[Qt::TopRightCorner].isNull() ||\
|
||||
!profile[Qt::BottomLeftCorner].isNull() ||\
|
||||
!profile[Qt::BottomRightCorner].isNull()
|
||||
) {
|
||||
conductors_and_profiles.insert(conductor, profile);
|
||||
}
|
||||
}
|
||||
|
||||
if (conductors_and_profiles.isEmpty()) return;
|
||||
scene -> undoStack().push(new ResetConductorCommand(conductors_and_profiles));
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un dialogue permettant de modifier les proprietes par defaut des
|
||||
futurs nouveaux conducteurs
|
||||
*/
|
||||
void DiagramView::editDefaultConductorProperties() {
|
||||
// initialise l'editeur de proprietes pour le conducteur
|
||||
ConductorPropertiesWidget *cpw = new ConductorPropertiesWidget(scene -> defaultConductorProperties);
|
||||
|
||||
// l'insere dans un dialogue
|
||||
QDialog conductor_dialog;
|
||||
conductor_dialog.setWindowTitle(tr("\311diter les propri\351t\351s par d\351faut des conducteurs"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&conductor_dialog);
|
||||
dialog_layout -> addWidget(cpw);
|
||||
QDialogButtonBox *dbb = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
dialog_layout -> addWidget(dbb);
|
||||
connect(dbb, SIGNAL(accepted()), &conductor_dialog, SLOT(accept()));
|
||||
connect(dbb, SIGNAL(rejected()), &conductor_dialog, SLOT(reject()));
|
||||
|
||||
// execute le dialogue et met a jour le conducteur
|
||||
if (conductor_dialog.exec() == QDialog::Accepted) {
|
||||
scene -> defaultConductorProperties = cpw -> conductorProperties();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les evenements de la DiagramView
|
||||
@param e Evenement
|
||||
*/
|
||||
bool DiagramView::event(QEvent *e) {
|
||||
// fait en sorte que les raccourcis clavier arrivent prioritairement sur la
|
||||
// vue plutot que de remonter vers les QMenu / QAction
|
||||
if (e -> type() == QEvent::ShortcutOverride && scene -> focusItem()) {
|
||||
e -> accept();
|
||||
return(true);
|
||||
}
|
||||
return(QGraphicsView::event(e));
|
||||
}
|
||||
|
||||
/**
|
||||
Passe le DiagramView en mode "ajout de texte". Un clic cree alors un
|
||||
nouveau champ de texte.
|
||||
*/
|
||||
void DiagramView::addText() {
|
||||
is_adding_text = true;
|
||||
}
|
||||
|
||||
/**
|
||||
Cree un nouveau champ de texte et le place a la position pos
|
||||
en gerant l'annulation ; enfin, le signal textAdded est emis.
|
||||
@param pos Position du champ de texte ajoute
|
||||
@return le champ de texte ajoute
|
||||
*/
|
||||
DiagramTextItem *DiagramView::addDiagramTextAtPos(const QPointF &pos) {
|
||||
// cree un nouveau champ de texte
|
||||
DiagramTextItem *dti = new DiagramTextItem();
|
||||
dti -> setPlainText("_");
|
||||
dti -> previous_text = "_";
|
||||
|
||||
// le place a la position pos en gerant l'annulation
|
||||
scene -> undoStack().push(new AddTextCommand(scene, dti, pos));
|
||||
adjustSceneRect();
|
||||
|
||||
// emet le signal textAdded
|
||||
emit(textAdded(false));
|
||||
|
||||
return(dti);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le menu contextuel
|
||||
@param e Evenement decrivant la demande de menu contextuel
|
||||
*/
|
||||
void DiagramView::contextMenuEvent(QContextMenuEvent *e) {
|
||||
if (QGraphicsItem *qgi = scene -> itemAt(mapToScene(e -> pos()))) {
|
||||
if (!qgi -> isSelected()) scene -> clearSelection();
|
||||
qgi -> setSelected(true);
|
||||
}
|
||||
|
||||
if (QETDiagramEditor *qde = diagramEditor()) {
|
||||
context_menu -> clear();
|
||||
if (scene -> selectedItems().isEmpty()) {
|
||||
paste_here_pos = e -> pos();
|
||||
paste_here -> setEnabled(Diagram::clipboardMayContainDiagram());
|
||||
context_menu -> addAction(paste_here);
|
||||
context_menu -> addSeparator();
|
||||
context_menu -> addAction(qde -> infos_diagram);
|
||||
context_menu -> addAction(qde -> add_column);
|
||||
context_menu -> addAction(qde -> remove_column);
|
||||
context_menu -> addAction(qde -> expand_diagram);
|
||||
context_menu -> addAction(qde -> shrink_diagram);
|
||||
} else {
|
||||
context_menu -> addAction(qde -> cut);
|
||||
context_menu -> addAction(qde -> copy);
|
||||
context_menu -> addSeparator();
|
||||
context_menu -> addAction(qde -> delete_selection);
|
||||
context_menu -> addAction(qde -> rotate_selection);
|
||||
context_menu -> addSeparator();
|
||||
context_menu -> addAction(qde -> conductor_prop);
|
||||
context_menu -> addAction(qde -> conductor_reset);
|
||||
}
|
||||
|
||||
// affiche le menu contextuel
|
||||
context_menu -> popup(e -> globalPos());
|
||||
}
|
||||
e -> accept();
|
||||
}
|
||||
|
||||
/// @return l'editeur de schemas parent ou 0
|
||||
QETDiagramEditor *DiagramView::diagramEditor() const {
|
||||
// remonte la hierarchie des widgets
|
||||
QWidget *w = const_cast<DiagramView *>(this);
|
||||
while (w -> parentWidget() && !w -> isWindow()) {
|
||||
w = w -> parentWidget();
|
||||
}
|
||||
// la fenetre est supposee etre un QETDiagramEditor
|
||||
return(qobject_cast<QETDiagramEditor *>(w));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les double-clics sur le schema
|
||||
*/
|
||||
void DiagramView::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
BorderInset &bi = scene -> border_and_inset;
|
||||
|
||||
// recupere le rectangle corespondant au cartouche
|
||||
QRectF inset_rect(
|
||||
Diagram::margin,
|
||||
Diagram::margin + bi.columnsHeight(),
|
||||
bi.insetWidth(),
|
||||
bi.insetHeight()
|
||||
);
|
||||
|
||||
// recupere le rectangle correspondant aux en-tetes des colonnes
|
||||
QRectF columns_rect(
|
||||
Diagram::margin,
|
||||
Diagram::margin,
|
||||
bi.borderWidth(),
|
||||
bi.columnsHeaderHeight()
|
||||
);
|
||||
|
||||
// coordonnees du clic par rapport au schema
|
||||
QPointF click_pos = viewportTransform().inverted().map(e -> pos());
|
||||
|
||||
// detecte le double-clic sur le cartouche ou les colonnes
|
||||
if (QGraphicsItem *qgi = itemAt(e -> pos())) {
|
||||
if (Conductor *c = qgraphicsitem_cast<Conductor *>(qgi)) {
|
||||
editConductor(c);
|
||||
} else {
|
||||
QGraphicsView::mouseDoubleClickEvent(e);
|
||||
}
|
||||
} else if (inset_rect.contains(click_pos) || columns_rect.contains(click_pos)) {
|
||||
// edite les proprietes du schema
|
||||
dialogEditInfos();
|
||||
} else {
|
||||
QGraphicsView::mouseDoubleClickEvent(e);
|
||||
}
|
||||
}
|
||||
120
sources/diagramview.h
Normal file
120
sources/diagramview.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 DIAGRAMVIEW_H
|
||||
#define DIAGRAMVIEW_H
|
||||
#include <QtGui>
|
||||
class Diagram;
|
||||
class DiagramTextItem;
|
||||
class QETDiagramEditor;
|
||||
class Conductor;
|
||||
/**
|
||||
Classe representant graphiquement un schema electrique
|
||||
*/
|
||||
class DiagramView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DiagramView(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;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool open(QString, int * = NULL);
|
||||
void closeEvent(QCloseEvent *);
|
||||
bool save();
|
||||
bool saveAs();
|
||||
void dialogExport();
|
||||
void dialogEditInfos();
|
||||
void dialogPrint();
|
||||
void addColumn();
|
||||
void removeColumn();
|
||||
void expand();
|
||||
void shrink();
|
||||
/// @return Le schema visualise par ce DiagramView
|
||||
Diagram *diagram() { return(scene); }
|
||||
QETDiagramEditor *diagramEditor() const;
|
||||
bool hasSelectedItems();
|
||||
void addText();
|
||||
DiagramTextItem *addDiagramTextAtPos(const QPointF &);
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *);
|
||||
virtual void contextMenuEvent(QContextMenuEvent *);
|
||||
virtual void wheelEvent(QWheelEvent *);
|
||||
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;
|
||||
|
||||
signals:
|
||||
/// Signal emis lorsque la selection change
|
||||
void selectionChanged();
|
||||
/// Signal emis lorsque le mode de selection change
|
||||
void modeChanged();
|
||||
/// Signal emis lorsqu'un texte a ete pose
|
||||
void textAdded(bool);
|
||||
|
||||
public slots:
|
||||
void selectNothing();
|
||||
void selectAll();
|
||||
void selectInvert();
|
||||
void deleteSelection();
|
||||
void rotateSelection();
|
||||
void setVisualisationMode();
|
||||
void setSelectionMode();
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void zoomFit();
|
||||
void zoomReset();
|
||||
void cut();
|
||||
void copy();
|
||||
void paste(const QPointF & = QPointF(), QClipboard::Mode = QClipboard::Clipboard);
|
||||
void pasteHere();
|
||||
void adjustSceneRect();
|
||||
void updateWindowTitle();
|
||||
void editConductor();
|
||||
void editConductor(Conductor *);
|
||||
void resetConductors();
|
||||
void editDefaultConductorProperties();
|
||||
|
||||
private slots:
|
||||
void adjustGridToZoom();
|
||||
};
|
||||
#endif
|
||||
128
sources/editor/arceditor.cpp
Normal file
128
sources/editor/arceditor.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "arceditor.h"
|
||||
#include "partarc.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param arc L'arc a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
ArcEditor::ArcEditor(QETElementEditor *editor, PartArc *arc, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
|
||||
part = arc;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
h = new QLineEdit();
|
||||
v = new QLineEdit();
|
||||
start_angle = new QSpinBox();
|
||||
angle = new QSpinBox();
|
||||
start_angle -> setRange(-360, 360);
|
||||
angle -> setRange(-360, 360);
|
||||
|
||||
x -> setValidator(new QDoubleValidator(x));
|
||||
y -> setValidator(new QDoubleValidator(y));
|
||||
h -> setValidator(new QDoubleValidator(h));
|
||||
v -> setValidator(new QDoubleValidator(v));
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
grid -> addWidget(new QLabel(tr("Centre : ")), 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("Diam\350tres : ")), 2, 0);
|
||||
grid -> addWidget(new QLabel(tr("horizontal :")), 3, 0);
|
||||
grid -> addWidget(h, 3, 1);
|
||||
grid -> addWidget(new QLabel(tr("vertical :")), 4, 0);
|
||||
grid -> addWidget(v, 4, 1);
|
||||
grid -> addWidget(new QLabel(tr("Angle de d\351part :")), 5, 0);
|
||||
grid -> addWidget(start_angle, 5, 1);
|
||||
grid -> addWidget(new QLabel(tr("Angle :")), 6, 0);
|
||||
grid -> addWidget(angle, 6, 1);
|
||||
updateForm();
|
||||
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ArcEditor::~ArcEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour l'arc a partir a partir des donnees du formulaire
|
||||
*/
|
||||
void ArcEditor::updateArc() {
|
||||
part -> setProperty("x", x -> text().toDouble());
|
||||
part -> setProperty("y", y -> text().toDouble());
|
||||
part -> setProperty("diameter_h", h -> text().toDouble());
|
||||
part -> setProperty("diameter_v", v -> text().toDouble());
|
||||
part -> setStartAngle(-start_angle -> value() + 90);
|
||||
part -> setAngle(-angle -> value());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du centre de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcX() { addChangePartCommand(tr("abscisse"), part, "x", x -> text().toDouble()); }
|
||||
/// Met a jour l'ordonnee du centre de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcY() { addChangePartCommand(tr("ordonn\351e"), part, "y", y -> text().toDouble()); }
|
||||
/// Met a jour le diametre horizontal de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcH() { addChangePartCommand(tr("diam\350tre horizontal"), part, "diameter_h", h -> text().toDouble()); }
|
||||
/// Met a jour le diametre vertical de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcV() { addChangePartCommand(tr("diam\350tre vertical"), part, "diameter_v", v -> text().toDouble()); }
|
||||
/// Met a jour l'angle de depart de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcS() { addChangePartCommand(tr("angle de d\351part"), part, "start_angle", -start_angle -> value() + 90); }
|
||||
/// Met a jour l'etendue de l'arc et cree un objet d'annulation
|
||||
void ArcEditor::updateArcA() { addChangePartCommand(tr("angle"), part, "angle", -angle -> value()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void ArcEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
x -> setText(part -> property("x").toString());
|
||||
y -> setText(part -> property("y").toString());
|
||||
h -> setText(part -> property("diameter_h").toString());
|
||||
v -> setText(part -> property("diameter_v").toString());
|
||||
start_angle -> setValue(-part -> startAngle() + 90);
|
||||
angle -> setValue(-part -> angle());
|
||||
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 ArcEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateArcX()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateArcY()));
|
||||
connect(h, SIGNAL(editingFinished()), this, SLOT(updateArcH()));
|
||||
connect(v, SIGNAL(editingFinished()), this, SLOT(updateArcV()));
|
||||
connect(start_angle, SIGNAL(editingFinished()), this, SLOT(updateArcS()));
|
||||
connect(angle, SIGNAL(editingFinished()), this, SLOT(updateArcA()));
|
||||
} else {
|
||||
disconnect(x, SIGNAL(editingFinished()), this, SLOT(updateArcX()));
|
||||
disconnect(y, SIGNAL(editingFinished()), this, SLOT(updateArcY()));
|
||||
disconnect(h, SIGNAL(editingFinished()), this, SLOT(updateArcH()));
|
||||
disconnect(v, SIGNAL(editingFinished()), this, SLOT(updateArcV()));
|
||||
disconnect(start_angle, SIGNAL(editingFinished()), this, SLOT(updateArcS()));
|
||||
disconnect(angle, SIGNAL(editingFinished()), this, SLOT(updateArcA()));
|
||||
}
|
||||
}
|
||||
56
sources/editor/arceditor.h
Normal file
56
sources/editor/arceditor.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 ARC_EDITOR_H
|
||||
#define ARC_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartArc;
|
||||
/**
|
||||
Cette classe represente le widget d'edition d'un arc dans l'editeur
|
||||
d'element.
|
||||
*/
|
||||
class ArcEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
ArcEditor(QETElementEditor *, PartArc *, QWidget * = 0);
|
||||
~ArcEditor();
|
||||
private:
|
||||
ArcEditor(const ArcEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartArc *part;
|
||||
QLineEdit *x, *y, *h, *v;
|
||||
QSpinBox *angle, *start_angle;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateArc();
|
||||
void updateArcX();
|
||||
void updateArcY();
|
||||
void updateArcH();
|
||||
void updateArcV();
|
||||
void updateArcS();
|
||||
void updateArcA();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
99
sources/editor/circleeditor.cpp
Normal file
99
sources/editor/circleeditor.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "circleeditor.h"
|
||||
#include "partcircle.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param circle Le cercle a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
CircleEditor::CircleEditor(QETElementEditor *editor, PartCircle *circle, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
|
||||
part = circle;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
r = new QLineEdit();
|
||||
|
||||
x -> setValidator(new QDoubleValidator(x));
|
||||
y -> setValidator(new QDoubleValidator(y));
|
||||
r -> setValidator(new QDoubleValidator(r));
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
grid -> addWidget(new QLabel(tr("Centre : ")), 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("Diam\350tre : ")), 2, 0);
|
||||
grid -> addWidget(r, 2, 1);
|
||||
|
||||
activeConnections(true);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
CircleEditor::~CircleEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
met a jour le cercle a partir des donnees du formulaire
|
||||
*/
|
||||
void CircleEditor::updateCircle() {
|
||||
part -> setProperty("x", x -> text().toDouble());
|
||||
part -> setProperty("y", y -> text().toDouble());
|
||||
part -> setProperty("diameter", r -> text().toDouble());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du cercle et cree un objet d'annulation
|
||||
void CircleEditor::updateCircleX() { addChangePartCommand(tr("abscisse"), part, "x", x -> text().toDouble()); }
|
||||
|
||||
/// Met a jour l'ordonnee du cercle et cree un objet d'annulation
|
||||
void CircleEditor::updateCircleY() { addChangePartCommand(tr("ordonn\351e"), part, "y", y -> text().toDouble()); }
|
||||
|
||||
/// Met a jour le diametre du cercle et cree un objet d'annulation
|
||||
void CircleEditor::updateCircleD() { addChangePartCommand(tr("diam\350tre"), part, "diameter", r -> text().toDouble()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void CircleEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
x -> setText(part -> property("x").toString());
|
||||
y -> setText(part -> property("y").toString());
|
||||
r -> setText(part -> property("diameter").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 CircleEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateCircleX()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateCircleY()));
|
||||
connect(r, SIGNAL(editingFinished()), this, SLOT(updateCircleD()));
|
||||
} else {
|
||||
disconnect(x, SIGNAL(editingFinished()), this, SLOT(updateCircleX()));
|
||||
disconnect(y, SIGNAL(editingFinished()), this, SLOT(updateCircleY()));
|
||||
disconnect(r, SIGNAL(editingFinished()), this, SLOT(updateCircleD()));
|
||||
}
|
||||
}
|
||||
53
sources/editor/circleeditor.h
Normal file
53
sources/editor/circleeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 CIRCLE_EDITOR_H
|
||||
#define CIRCLE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartCircle;
|
||||
/**
|
||||
Cette classe represente un editeur de cercle.
|
||||
Elle permet d'editer a travers une interface graphique les
|
||||
proprietes d'une cercle composant le dessin d'un element.
|
||||
*/
|
||||
class CircleEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
CircleEditor(QETElementEditor *, PartCircle *, QWidget * = 0);
|
||||
virtual ~CircleEditor();
|
||||
private:
|
||||
CircleEditor(const CircleEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartCircle *part;
|
||||
QLineEdit *x, *y, *r;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateCircle();
|
||||
void updateCircleX();
|
||||
void updateCircleY();
|
||||
void updateCircleD();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
208
sources/editor/customelementgraphicpart.cpp
Normal file
208
sources/editor/customelementgraphicpart.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "customelementgraphicpart.h"
|
||||
|
||||
/**
|
||||
Ecrit les attributs de style dans un element XML
|
||||
@param qde L'element XML a modifier
|
||||
|
||||
*/
|
||||
void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const {
|
||||
QString css_like_styles;
|
||||
|
||||
css_like_styles += "line-style:";
|
||||
if (_linestyle == DashedStyle) css_like_styles += "dashed";
|
||||
else if (_linestyle == NormalStyle) css_like_styles += "normal";
|
||||
|
||||
css_like_styles += ";line-weight:";
|
||||
if (_lineweight == NoneWeight) css_like_styles += "none";
|
||||
else if (_lineweight == ThinWeight) css_like_styles += "thin";
|
||||
else if (_lineweight == NormalWeight) css_like_styles += "normal";
|
||||
|
||||
css_like_styles += ";filling:";
|
||||
if (_filling == NoneFilling) css_like_styles += "none";
|
||||
else if (_filling == BlackFilling) css_like_styles += "black";
|
||||
else if (_filling == WhiteFilling) css_like_styles += "white";
|
||||
|
||||
css_like_styles += ";color:";
|
||||
if (_color == WhiteColor) css_like_styles += "white";
|
||||
else if (_color == BlackColor) css_like_styles += "black";
|
||||
|
||||
qde.setAttribute("style", css_like_styles);
|
||||
qde.setAttribute("antialias", _antialiased ? "true" : "false");
|
||||
}
|
||||
|
||||
/**
|
||||
Lit les attributs de style depuis un element XML
|
||||
@param qde L'element XML a analyser
|
||||
*/
|
||||
void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) {
|
||||
resetStyles();
|
||||
|
||||
// recupere la liste des couples style / valeur
|
||||
QStringList styles = qde.attribute("style").split(";", QString::SkipEmptyParts);
|
||||
|
||||
// analyse chaque couple
|
||||
QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$");
|
||||
foreach (QString style, styles) {
|
||||
if (!rx.exactMatch(style)) continue;
|
||||
QString style_name = rx.cap(1);
|
||||
QString style_value = rx.cap(2);
|
||||
if (style_name == "line-style") {
|
||||
if (style_value == "dashed") _linestyle = DashedStyle;
|
||||
else if (style_value == "normal") _linestyle = NormalStyle;
|
||||
// il n'y a pas de else car les valeurs non conformes sont ignorees (idem par la suite)
|
||||
} else if (style_name == "line-weight") {
|
||||
if (style_value == "thin") _lineweight = ThinWeight;
|
||||
else if (style_value == "normal") _lineweight = NormalWeight;
|
||||
else if (style_value == "none") _lineweight = NoneWeight;
|
||||
} else if (style_name == "filling") {
|
||||
if (style_value == "white") _filling = WhiteFilling;
|
||||
else if (style_value == "black") _filling = BlackFilling;
|
||||
else if (style_value == "none") _filling = NoneFilling;
|
||||
} else if (style_name == "color") {
|
||||
if (style_value == "black") _color = BlackColor;
|
||||
else if (style_value == "white") _color = WhiteColor;
|
||||
}
|
||||
}
|
||||
|
||||
// recupere l'antialiasing
|
||||
_antialiased = qde.attribute("antialias") == "true";
|
||||
|
||||
// met a jour l'editeur de style
|
||||
style_editor -> updateForm();
|
||||
}
|
||||
|
||||
/**
|
||||
Remet les styles par defaut
|
||||
*/
|
||||
void CustomElementGraphicPart::resetStyles() {
|
||||
_linestyle = NormalStyle;
|
||||
_lineweight = NormalWeight;
|
||||
_filling = NoneFilling;
|
||||
_color = BlackColor;
|
||||
_antialiased = false;
|
||||
}
|
||||
|
||||
/**
|
||||
Applique les styles a un Qpainter
|
||||
@param painter QPainter a modifier
|
||||
*/
|
||||
void CustomElementGraphicPart::applyStylesToQPainter(QPainter &painter) const {
|
||||
// recupere le QPen et la QBrush du QPainter
|
||||
QPen pen = painter.pen();
|
||||
QBrush brush = painter.brush();
|
||||
|
||||
// applique le style de trait
|
||||
if (_linestyle == DashedStyle) pen.setStyle(Qt::DashLine);
|
||||
else if (_linestyle == NormalStyle) pen.setStyle(Qt::SolidLine);
|
||||
|
||||
// applique l'epaisseur de trait
|
||||
if (_lineweight == NoneWeight) pen.setColor(QColor(0, 0, 0, 0));
|
||||
else if (_lineweight == ThinWeight) pen.setWidth(0);
|
||||
else if (_lineweight == NormalWeight) pen.setWidthF(1.0);
|
||||
|
||||
// applique le remplissage
|
||||
if (_filling == NoneFilling) {
|
||||
brush.setStyle(Qt::NoBrush);
|
||||
} else if (_filling == BlackFilling) {
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(Qt::black);
|
||||
} else if (_filling == WhiteFilling) {
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(Qt::white);
|
||||
}
|
||||
|
||||
// applique la couleur de trait
|
||||
if (_color == WhiteColor) pen.setColor(QColor(255, 255, 255, pen.color().alpha()));
|
||||
else if (_color == BlackColor) pen.setColor(QColor( 0, 0, 0, pen.color().alpha()));
|
||||
|
||||
|
||||
// applique l'antialiasing
|
||||
painter.setRenderHint(QPainter::Antialiasing, _antialiased);
|
||||
painter.setRenderHint(QPainter::TextAntialiasing, _antialiased);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, _antialiased);
|
||||
|
||||
painter.setPen(pen);
|
||||
painter.setBrush(brush);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget permettant d'editer les styles
|
||||
*/
|
||||
QWidget *CustomElementGraphicPart::elementInformations() {
|
||||
return(style_editor);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete de style donnee.
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* line-style : type de trait (@see LineStyle)
|
||||
* line-weight : epaisseur du traut (@see LineWeight)
|
||||
* filling : couleur de remplissage (@see Color)
|
||||
* color : couleur du trait (@see Color)
|
||||
* antialias : utiliser l'antialiasing ou non (booleen)
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void CustomElementGraphicPart::setProperty(const QString &property, const QVariant &value) {
|
||||
bool change_made = false;
|
||||
if (property == "line-style") {
|
||||
setLineStyle(static_cast<LineStyle>(value.toInt()));
|
||||
change_made = true;
|
||||
} else if (property == "line-weight") {
|
||||
setLineWeight(static_cast<LineWeight>(value.toInt()));
|
||||
change_made = true;
|
||||
} else if (property == "filling") {
|
||||
setFilling(static_cast<Filling>(value.toInt()));
|
||||
change_made = true;
|
||||
} else if (property == "color") {
|
||||
setColor(static_cast<Color>(value.toInt()));
|
||||
change_made = true;
|
||||
} else if (property == "antialias") {
|
||||
setAntialiased(value.toBool());
|
||||
change_made = true;
|
||||
}
|
||||
if (change_made) {
|
||||
style_editor -> updateForm();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete de style donnee.
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* line-style : type de trait (@see LineStyle)
|
||||
* line-weight : epaisseur du traut (@see LineWeight)
|
||||
* filling : couleur de remplissage (@see Color)
|
||||
* color : couleur du trait (@see Color)
|
||||
* antialias : utiliser l'antialiasing ou non (booleen)
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant CustomElementGraphicPart::property(const QString &property) {
|
||||
if (property == "line-style") {
|
||||
return(lineStyle());
|
||||
} else if (property == "line-weight") {
|
||||
return(lineWeight());
|
||||
} else if (property == "filling") {
|
||||
return(filling());
|
||||
} else if (property == "color") {
|
||||
return(color());
|
||||
} else if (property == "antialias") {
|
||||
return(antialiased());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
192
sources/editor/customelementgraphicpart.h
Normal file
192
sources/editor/customelementgraphicpart.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 CUSTOM_ELEMENT_GRAPHIC_PART_H
|
||||
#define CUSTOM_ELEMENT_GRAPHIC_PART_H
|
||||
#include <QPainter>
|
||||
#include "customelementpart.h"
|
||||
#include "styleeditor.h"
|
||||
class QETElementEditor;
|
||||
typedef CustomElementGraphicPart CEGP;
|
||||
/**
|
||||
Cette classe represente une partie graphique d'element
|
||||
Elle encapsule des methodes afin de gerer les attributs de style communs
|
||||
a la plupart des parties d'elements
|
||||
*/
|
||||
class CustomElementGraphicPart : public CustomElementPart {
|
||||
public:
|
||||
/// Qualifie le style de ligne utilise pour dessiner la partie
|
||||
enum LineStyle {
|
||||
NormalStyle, ///< Ligne pleine
|
||||
DashedStyle ///< Ligne pointillee
|
||||
};
|
||||
|
||||
/// Qualifie l'epaisseur de ligne utilisee pour dessiner la partie
|
||||
enum LineWeight {
|
||||
NormalWeight, ///< Ligne normale
|
||||
ThinWeight, ///< Ligne fine
|
||||
NoneWeight ///< Ligne invisible
|
||||
};
|
||||
|
||||
/// Qualifie la couleur utilisee pour remplir la partie
|
||||
enum Filling {
|
||||
NoneFilling, ///< Remplissage transparent
|
||||
BlackFilling, ///< Remplissage en noir
|
||||
WhiteFilling ///< Remplissage en blanc
|
||||
};
|
||||
|
||||
/// Qualifie la couleur de ligne utilisee pour dessiner la partie
|
||||
enum Color {
|
||||
BlackColor, ///< Ligne noire
|
||||
WhiteColor ///< Ligne blanche
|
||||
};
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
@param editor Editeur d'element auquel cette partie est rattachee
|
||||
*/
|
||||
CustomElementGraphicPart(QETElementEditor *editor) :
|
||||
CustomElementPart(editor),
|
||||
_linestyle(NormalStyle),
|
||||
_lineweight(NormalWeight),
|
||||
_filling(NoneFilling),
|
||||
_color(BlackColor),
|
||||
_antialiased(false)
|
||||
{
|
||||
style_editor = new StyleEditor(elementEditor(), this);
|
||||
};
|
||||
|
||||
/// Destructeur
|
||||
virtual ~CustomElementGraphicPart() {
|
||||
delete style_editor;
|
||||
};
|
||||
|
||||
// attributs
|
||||
private:
|
||||
LineStyle _linestyle;
|
||||
LineWeight _lineweight;
|
||||
Filling _filling ;
|
||||
Color _color;
|
||||
bool _antialiased;
|
||||
|
||||
protected:
|
||||
/// Widget d'edition des styles de cette partie graphique
|
||||
StyleEditor *style_editor;
|
||||
|
||||
//methodes
|
||||
public:
|
||||
void setLineStyle(LineStyle);
|
||||
void setLineWeight(LineWeight);
|
||||
void setFilling(Filling);
|
||||
void setColor(Color);
|
||||
void setAntialiased(bool);
|
||||
|
||||
LineStyle lineStyle() const;
|
||||
LineWeight lineWeight() const;
|
||||
Filling filling() const;
|
||||
Color color() const;
|
||||
bool antialiased() const;
|
||||
|
||||
QWidget *elementInformations();
|
||||
void setProperty(const QString &, const QVariant &);
|
||||
QVariant property(const QString &);
|
||||
|
||||
protected:
|
||||
void stylesToXml(QDomElement &) const;
|
||||
void stylesFromXml(const QDomElement &);
|
||||
void resetStyles();
|
||||
void applyStylesToQPainter(QPainter &) const;
|
||||
};
|
||||
|
||||
/**
|
||||
Change le style de trait
|
||||
@param ls Le nouveau style de trait
|
||||
*/
|
||||
inline void CustomElementGraphicPart::setLineStyle(LineStyle ls) {
|
||||
_linestyle = ls;
|
||||
}
|
||||
|
||||
/**
|
||||
Change l'epaisseur de trait
|
||||
@param lw La nouvelle epaisseur de trait
|
||||
*/
|
||||
inline void CustomElementGraphicPart::setLineWeight(LineWeight lw) {
|
||||
_lineweight = lw;
|
||||
}
|
||||
|
||||
/**
|
||||
Change la couleur de remplissage
|
||||
@param f La nouvelle couleur de remplissage
|
||||
*/
|
||||
inline void CustomElementGraphicPart::setFilling(Filling f) {
|
||||
_filling = f;
|
||||
}
|
||||
|
||||
/**
|
||||
Change la couleur de trait
|
||||
@param c La nouvelle couleur de trait
|
||||
*/
|
||||
inline void CustomElementGraphicPart::setColor(Color c) {
|
||||
_color = c;
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le style de trait
|
||||
*/
|
||||
inline CustomElementGraphicPart::LineStyle CustomElementGraphicPart::lineStyle() const {
|
||||
return(_linestyle);
|
||||
}
|
||||
|
||||
/**
|
||||
@return L'epaisseur de trait
|
||||
*/
|
||||
inline CustomElementGraphicPart::LineWeight CustomElementGraphicPart::lineWeight() const {
|
||||
return(_lineweight);
|
||||
}
|
||||
|
||||
/**
|
||||
@return La couleur de remplissage
|
||||
*/
|
||||
inline CustomElementGraphicPart::Filling CustomElementGraphicPart::filling() const {
|
||||
return(_filling);
|
||||
}
|
||||
|
||||
/**
|
||||
@return La couleur de trait
|
||||
*/
|
||||
inline CustomElementGraphicPart::Color CustomElementGraphicPart::color() const {
|
||||
return(_color);
|
||||
}
|
||||
|
||||
/**
|
||||
Definit si la partie doit etre antialiasee ou non
|
||||
@param aa True pour activer l'antialiasing, false pour le desactiver
|
||||
*/
|
||||
inline void CustomElementGraphicPart::setAntialiased(bool aa) {
|
||||
_antialiased = aa;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si la partie est antialiasee, false sinon
|
||||
*/
|
||||
inline bool CustomElementGraphicPart::antialiased() const {
|
||||
return(_antialiased);
|
||||
}
|
||||
|
||||
#endif
|
||||
35
sources/editor/customelementpart.cpp
Normal file
35
sources/editor/customelementpart.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "customelementpart.h"
|
||||
#include "customelement.h"
|
||||
#include "qetelementeditor.h"
|
||||
|
||||
/// @return le QETElementEditor auquel cet editeur appartient
|
||||
QETElementEditor *CustomElementPart::elementEditor() const {
|
||||
return(element_editor);
|
||||
}
|
||||
|
||||
/// @return l'ElementScene contenant les parties editees par cet editeur
|
||||
ElementScene *CustomElementPart::elementScene() const {
|
||||
return(element_editor -> elementScene());
|
||||
}
|
||||
|
||||
/// @return la QUndoStack a utiliser pour les annulations
|
||||
QUndoStack &CustomElementPart::undoStack() const {
|
||||
return(elementScene() -> undoStack());
|
||||
}
|
||||
87
sources/editor/customelementpart.h
Normal file
87
sources/editor/customelementpart.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 CUSTOM_ELEMENT_PART_H
|
||||
#define CUSTOM_ELEMENT_PART_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include <QImage>
|
||||
class CustomElement;
|
||||
class QETElementEditor;
|
||||
class ElementScene;
|
||||
/**
|
||||
Cette classe abstraite represente une partie de la representation graphique
|
||||
d'un element de schema electrique. Les attributs et methodes qu'elle
|
||||
encapsule ne sont pas integres directement dans la classe CustomElement
|
||||
afin de ne pas alourdir celle-ci. Il est en effet inutile pour cette classe
|
||||
de retenir sa conception graphique autrement que sous la forme d'une
|
||||
QImage.
|
||||
*/
|
||||
class CustomElementPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
@param editor Editeur d'element auquel cette partie est rattachee
|
||||
*/
|
||||
CustomElementPart(QETElementEditor *editor) : element_editor(editor) {}
|
||||
/// Destructeur
|
||||
virtual ~CustomElementPart() {}
|
||||
|
||||
private:
|
||||
CustomElementPart(const CustomElementPart &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QETElementEditor *element_editor;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
/**
|
||||
Charge la partie depuis un element XML sense le decrire
|
||||
*/
|
||||
virtual void fromXml(const QDomElement &) = 0;
|
||||
/**
|
||||
Enregistre la partie dans un document XML
|
||||
*/
|
||||
virtual const QDomElement toXml(QDomDocument &) const = 0;
|
||||
/// @return un widget suppose decrire et/ou permettre de modifier la partie
|
||||
virtual QWidget *elementInformations() = 0;
|
||||
/**
|
||||
Permet de modifier une des proprietes de la partie
|
||||
*/
|
||||
virtual void setProperty(const QString &, const QVariant &) = 0;
|
||||
/**
|
||||
Permet de lire une des proprietes de la partie
|
||||
*/
|
||||
virtual QVariant property(const QString &) = 0;
|
||||
/**
|
||||
@return true si la partie n'est pas pertinente, false sinon
|
||||
Typiquement, une partie non pertinente n'est pas conservee lors de
|
||||
l'enregistrement de l'element.
|
||||
*/
|
||||
virtual bool isUseless() const = 0;
|
||||
/// @return un pointeur vers l'editeur d'element parent
|
||||
virtual QETElementEditor *elementEditor() const;
|
||||
/// @return un pointeur vers la scene d'edition parente
|
||||
virtual ElementScene *elementScene() const;
|
||||
/// @return la pile d'annulations a utiliser
|
||||
virtual QUndoStack &undoStack() const;
|
||||
/// @return le nom de la partie
|
||||
virtual QString name() const = 0;
|
||||
};
|
||||
#endif
|
||||
504
sources/editor/editorcommands.cpp
Normal file
504
sources/editor/editorcommands.cpp
Normal file
@@ -0,0 +1,504 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "editorcommands.h"
|
||||
|
||||
/*** DeletePartsCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@param scene ElementScene concernee
|
||||
@param parts Liste des parties supprimees
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
DeletePartsCommand::DeletePartsCommand(
|
||||
ElementScene *scene,
|
||||
const QList<QGraphicsItem *> parts,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("suppression"), parent),
|
||||
deleted_parts(parts),
|
||||
editor_scene(scene)
|
||||
{
|
||||
foreach(QGraphicsItem *qgi, deleted_parts) {
|
||||
editor_scene -> qgiManager().manage(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructeur : detruit egalement les parties supprimees
|
||||
DeletePartsCommand::~DeletePartsCommand() {
|
||||
foreach(QGraphicsItem *qgi, deleted_parts) {
|
||||
editor_scene -> qgiManager().release(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/// Restaure les parties supprimees
|
||||
void DeletePartsCommand::undo() {
|
||||
foreach(QGraphicsItem *qgi, deleted_parts) {
|
||||
editor_scene -> addItem(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/// Supprime les parties
|
||||
void DeletePartsCommand::redo() {
|
||||
foreach(QGraphicsItem *qgi, deleted_parts) {
|
||||
editor_scene -> removeItem(qgi);
|
||||
}
|
||||
}
|
||||
|
||||
/*** MovePartsCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@param m Mouvement sous forme de QPointF
|
||||
@param scene ElementScene concernee
|
||||
@param parts Liste des parties deplacees
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
MovePartsCommand::MovePartsCommand(
|
||||
const QPointF &m,
|
||||
ElementScene *scene,
|
||||
const QList<QGraphicsItem *> parts,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("d\351placement"), parent),
|
||||
movement(m),
|
||||
first_redo(true)
|
||||
{
|
||||
moved_parts = parts;
|
||||
editor_scene = scene;
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
MovePartsCommand::~MovePartsCommand() {
|
||||
}
|
||||
|
||||
/// Annule le deplacement
|
||||
void MovePartsCommand::undo() {
|
||||
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(-movement.x(), -movement.y());
|
||||
}
|
||||
|
||||
/// Refait le deplacement
|
||||
void MovePartsCommand::redo() {
|
||||
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
|
||||
if (first_redo) {
|
||||
first_redo = false;
|
||||
return;
|
||||
}
|
||||
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(movement.x(), movement.y());
|
||||
}
|
||||
|
||||
/*** AddPartCommand ***/
|
||||
/**
|
||||
Constructeur
|
||||
@param name Nom de la partie ajoutee
|
||||
@param scene ElementScene concernee
|
||||
@param p partie ajoutee
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AddPartCommand::AddPartCommand(
|
||||
const QString &name,
|
||||
ElementScene *scene,
|
||||
QGraphicsItem *p,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("ajout ") + name, parent),
|
||||
part(p),
|
||||
editor_scene(scene),
|
||||
first_redo(true)
|
||||
{
|
||||
editor_scene -> qgiManager().manage(part);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
AddPartCommand::~AddPartCommand() {
|
||||
editor_scene -> qgiManager().release(part);
|
||||
}
|
||||
|
||||
/// Annule l'ajout
|
||||
void AddPartCommand::undo() {
|
||||
editor_scene -> removeItem(part);
|
||||
}
|
||||
|
||||
/// Refait l'ajout
|
||||
void AddPartCommand::redo() {
|
||||
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
|
||||
if (first_redo) {
|
||||
editor_scene -> clearSelection();
|
||||
part -> setSelected(true);
|
||||
first_redo = false;
|
||||
return;
|
||||
}
|
||||
editor_scene -> addItem(part);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param name nom de la propriete modifiee
|
||||
@param part partie modifiee
|
||||
@param prop propriete modifiee
|
||||
@param old_v ancienne valeur
|
||||
@param new_v nouvelle valeur
|
||||
@param parent qUndoCommand parent
|
||||
*/
|
||||
ChangePartCommand::ChangePartCommand(
|
||||
const QString &name,
|
||||
CustomElementPart *part,
|
||||
const QString &prop,
|
||||
const QVariant &old_v,
|
||||
const QVariant &new_v,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification ") + name, parent),
|
||||
cep(part),
|
||||
property(prop),
|
||||
old_value(old_v),
|
||||
new_value(new_v)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangePartCommand::~ChangePartCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement
|
||||
void ChangePartCommand::undo() {
|
||||
cep -> setProperty(property, old_value);
|
||||
}
|
||||
|
||||
/// Refait le changement
|
||||
void ChangePartCommand::redo() {
|
||||
cep -> setProperty(property, new_value);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param p Polygone edite
|
||||
@param o_points points avant le changement
|
||||
@param n_points points apres le changement
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangePolygonPointsCommand::ChangePolygonPointsCommand(
|
||||
PartPolygon *p,
|
||||
const QVector<QPointF> &o_points,
|
||||
const QVector<QPointF> &n_points,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification points polygone"), parent),
|
||||
polygon(p),
|
||||
old_points(o_points),
|
||||
new_points(n_points)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangePolygonPointsCommand::~ChangePolygonPointsCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement
|
||||
void ChangePolygonPointsCommand::undo() {
|
||||
polygon -> setPolygon(old_points);
|
||||
}
|
||||
|
||||
/// Refait le changement
|
||||
void ChangePolygonPointsCommand::redo() {
|
||||
polygon -> setPolygon(new_points);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param element_scene Element edite
|
||||
@param size_1 Dimensions de l'element avant le changement
|
||||
@param size_2 Dimensions de l'element apres le changement
|
||||
@param hotspot_1 Point de saisie de l'element avant le changement
|
||||
@param hotspot_2 Point de saisie de l'element apres le changement
|
||||
@param o Eventuel decalage a appliquer aux parties de l'element edite
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeHotspotCommand::ChangeHotspotCommand(
|
||||
ElementScene *element_scene,
|
||||
const QSize &size_1,
|
||||
const QSize &size_2,
|
||||
const QPoint &hotspot_1,
|
||||
const QPoint &hotspot_2,
|
||||
const QPoint &o,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification dimensions/hotspot"), parent),
|
||||
element(element_scene),
|
||||
size_before(size_1),
|
||||
size_after(size_2),
|
||||
hotspot_before(hotspot_1),
|
||||
hotspot_after(hotspot_2),
|
||||
offset(o)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeHotspotCommand::~ChangeHotspotCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement
|
||||
void ChangeHotspotCommand::undo() {
|
||||
QRectF sc(element -> sceneContent());
|
||||
|
||||
element -> setWidth(size_before.width());
|
||||
element -> setHeight(size_before.height());
|
||||
element -> setHotspot(hotspot_before);
|
||||
if (!offset.isNull()) applyOffset(-offset);
|
||||
|
||||
element -> update(element -> sceneContent().unite(sc));
|
||||
}
|
||||
|
||||
/// Refait le changement
|
||||
void ChangeHotspotCommand::redo() {
|
||||
QRectF sc(element -> sceneContent());
|
||||
|
||||
element -> setWidth(size_after.width());
|
||||
element -> setHeight(size_after.height());
|
||||
element -> setHotspot(hotspot_after);
|
||||
if (!offset.isNull()) applyOffset(offset);
|
||||
|
||||
element -> update(element -> sceneContent().unite(sc));
|
||||
}
|
||||
|
||||
/**
|
||||
Applique une translation aux parties de l'element edite
|
||||
@param o Translation a appliquer
|
||||
*/
|
||||
void ChangeHotspotCommand::applyOffset(const QPointF &o) {
|
||||
foreach(QGraphicsItem *qgi, element -> items()) {
|
||||
qgi -> translate(o.x(), o.y());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param element_scene Element edite
|
||||
@param before Listes des noms avant changement
|
||||
@param after Listes des noms apres changement
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeNamesCommand::ChangeNamesCommand(
|
||||
ElementScene *element_scene,
|
||||
const NamesList &before,
|
||||
const NamesList &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification noms"), parent),
|
||||
names_before(before),
|
||||
names_after(after),
|
||||
element(element_scene)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeNamesCommand::~ChangeNamesCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement
|
||||
void ChangeNamesCommand::undo() {
|
||||
element -> setNames(names_before);
|
||||
}
|
||||
|
||||
/// Refait le changement
|
||||
void ChangeNamesCommand::redo() {
|
||||
element -> setNames(names_after);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param element_scene Element edite
|
||||
@param before Orientations avant changement
|
||||
@param after Orientations apres changement
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeOrientationsCommand::ChangeOrientationsCommand(
|
||||
ElementScene *element_scene,
|
||||
const OrientationSet &before,
|
||||
const OrientationSet &after,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(QObject::tr("modification orientations"), parent),
|
||||
ori_before(before),
|
||||
ori_after(after),
|
||||
element(element_scene)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeOrientationsCommand::~ChangeOrientationsCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement
|
||||
void ChangeOrientationsCommand::undo() {
|
||||
element -> setOrientations(ori_before);
|
||||
}
|
||||
|
||||
/// Refait le changement
|
||||
void ChangeOrientationsCommand::redo() {
|
||||
element -> setOrientations(ori_after);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param elmt ElementScene concernee
|
||||
@param o Option decrivant le type de traitement applique aux zValues des parties de l'element
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
ChangeZValueCommand::ChangeZValueCommand(
|
||||
ElementScene *elmt,
|
||||
ChangeZValueCommand::Option o,
|
||||
QUndoCommand *parent
|
||||
) :
|
||||
QUndoCommand(parent),
|
||||
element(elmt),
|
||||
option(o)
|
||||
{
|
||||
// recupere les parties de l'elements, sauf les bornes
|
||||
QList<QGraphicsItem *> items_list = element -> zItems();
|
||||
|
||||
// prend un snapshot des zValues
|
||||
foreach(QGraphicsItem *qgi, items_list) undo_hash.insert(qgi, qgi -> zValue());
|
||||
|
||||
// choisit le nom en fonction du traitement
|
||||
if (option == BringForward) {
|
||||
setText(QObject::tr("amener au premier plan"));
|
||||
applyBringForward(items_list);
|
||||
} else if (option == Raise) {
|
||||
setText(QObject::tr("rapprocher"));
|
||||
applyRaise(items_list);
|
||||
} else if (option == Lower) {
|
||||
setText(QObject::tr("\351loigner"));
|
||||
applyLower(items_list);
|
||||
} else if (option == SendBackward) {
|
||||
setText(QObject::tr("envoyer au fond"));
|
||||
applySendBackward(items_list);
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ChangeZValueCommand::~ChangeZValueCommand() {
|
||||
}
|
||||
|
||||
/// Annule les changements de zValue
|
||||
void ChangeZValueCommand::undo() {
|
||||
foreach(QGraphicsItem *qgi, undo_hash.keys()) qgi -> setZValue(undo_hash[qgi]);
|
||||
}
|
||||
|
||||
/// Refait les changements de zValue
|
||||
void ChangeZValueCommand::redo() {
|
||||
foreach(QGraphicsItem *qgi, redo_hash.keys()) qgi -> setZValue(redo_hash[qgi]);
|
||||
}
|
||||
|
||||
/**
|
||||
Amene les elements selectionnes au premier plan
|
||||
@param items_list Liste des elements (selectionnes et non selectionnes)
|
||||
*/
|
||||
void ChangeZValueCommand::applyBringForward(const QList<QGraphicsItem *> &items_list) {
|
||||
QList<QGraphicsItem *> non_selected_items = items_list;
|
||||
QList<QGraphicsItem *> selected_items;
|
||||
foreach(QGraphicsItem *qgi, non_selected_items) {
|
||||
if (qgi -> isSelected()) {
|
||||
selected_items << qgi;
|
||||
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
|
||||
}
|
||||
}
|
||||
int z = 1;
|
||||
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
|
||||
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
|
||||
}
|
||||
|
||||
/**
|
||||
Remonte les elements selectionnes d'un plan
|
||||
@param items_list Liste des elements (selectionnes et non selectionnes)
|
||||
*/
|
||||
void ChangeZValueCommand::applyRaise(const QList<QGraphicsItem *> &items_list) {
|
||||
QList<QGraphicsItem *> my_items_list = items_list;
|
||||
|
||||
for (int i = my_items_list.count() - 2 ; i >= 0 ; -- i) {
|
||||
if (my_items_list[i] -> isSelected()) {
|
||||
if (!my_items_list[i +1] -> isSelected()) {
|
||||
my_items_list.swap(i, i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
int z = 1;
|
||||
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
|
||||
}
|
||||
|
||||
/**
|
||||
Descend les elements selectionnes d'un plan
|
||||
@param items_list Liste des elements (selectionnes et non selectionnes)
|
||||
*/
|
||||
void ChangeZValueCommand::applyLower(const QList<QGraphicsItem *> &items_list) {
|
||||
QList<QGraphicsItem *> my_items_list = items_list;
|
||||
|
||||
for (int i = 1 ; i < my_items_list.count() ; ++ i) {
|
||||
if (my_items_list[i] -> isSelected()) {
|
||||
if (!my_items_list[i - 1] -> isSelected()) {
|
||||
my_items_list.swap(i, i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int z = 1;
|
||||
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
|
||||
}
|
||||
|
||||
/**
|
||||
Envoie les elements selectionnes au fond
|
||||
@param items_list Liste des elements (selectionnes et non selectionnes)
|
||||
*/
|
||||
void ChangeZValueCommand::applySendBackward(const QList<QGraphicsItem *> &items_list) {
|
||||
QList<QGraphicsItem *> non_selected_items = items_list;
|
||||
QList<QGraphicsItem *> selected_items;
|
||||
foreach(QGraphicsItem *qgi, non_selected_items) {
|
||||
if (qgi -> isSelected()) {
|
||||
selected_items << qgi;
|
||||
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
|
||||
}
|
||||
}
|
||||
int z = 1;
|
||||
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
|
||||
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param elmt ElementScene concernee
|
||||
@param allow true pour que les connexions internes soient acceptees, false sinon
|
||||
@param parent QUndoCommand parent
|
||||
*/
|
||||
AllowInternalConnectionsCommand::AllowInternalConnectionsCommand(ElementScene *elmt, bool allow, QUndoCommand *parent) :
|
||||
QUndoCommand(QObject::tr("modification connexions internes"), parent),
|
||||
element(elmt),
|
||||
ic(allow)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
AllowInternalConnectionsCommand::~AllowInternalConnectionsCommand() {
|
||||
}
|
||||
|
||||
/// Annule le changement d'autorisation pour les connexions internes
|
||||
void AllowInternalConnectionsCommand::undo() {
|
||||
element -> setInternalConnections(!ic);
|
||||
}
|
||||
|
||||
/// Refait le changement d'autorisation pour les connexions internes
|
||||
void AllowInternalConnectionsCommand::redo() {
|
||||
element -> setInternalConnections(ic);
|
||||
}
|
||||
311
sources/editor/editorcommands.h
Normal file
311
sources/editor/editorcommands.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 EDITOR_COMMANDS_H
|
||||
#define EDITOR_COMMANDS_H
|
||||
#include "customelementpart.h"
|
||||
#include "partpolygon.h"
|
||||
#include "elementscene.h"
|
||||
#include "qgimanager.h"
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe represente l'action de supprimer une ou plusieurs
|
||||
parties lors de l'edition d'un element
|
||||
*/
|
||||
class DeletePartsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
DeletePartsCommand(ElementScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
|
||||
virtual ~DeletePartsCommand();
|
||||
private:
|
||||
DeletePartsCommand(const DeletePartsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Liste des parties supprimees
|
||||
QList<QGraphicsItem *> deleted_parts;
|
||||
/// scene sur laquelle se produisent les actions
|
||||
ElementScene *editor_scene;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de deplacer une ou plusieurs
|
||||
parties lors de l'edition d'un element
|
||||
*/
|
||||
class MovePartsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
MovePartsCommand(const QPointF &, ElementScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
|
||||
virtual ~MovePartsCommand();
|
||||
private:
|
||||
MovePartsCommand(const MovePartsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Liste des parties supprimees
|
||||
QList<QGraphicsItem *> moved_parts;
|
||||
/// scene sur laquelle se produisent les actions
|
||||
ElementScene *editor_scene;
|
||||
/// translation appliquee
|
||||
QPointF movement;
|
||||
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action d'ajouter une partie lors de l'edition
|
||||
d'un element
|
||||
*/
|
||||
class AddPartCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AddPartCommand(const QString &, ElementScene *, QGraphicsItem *, QUndoCommand * = 0);
|
||||
virtual ~AddPartCommand();
|
||||
private:
|
||||
AddPartCommand(const AddPartCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Liste des parties supprimees
|
||||
QGraphicsItem *part;
|
||||
/// scene sur laquelle se produisent les actions
|
||||
ElementScene *editor_scene;
|
||||
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
|
||||
bool first_redo;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier une propriete d'une partie
|
||||
lors de l'edition d'un element
|
||||
*/
|
||||
class ChangePartCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangePartCommand(const QString &, CustomElementPart *, const QString &, const QVariant &, const QVariant &, QUndoCommand * = 0);
|
||||
virtual ~ChangePartCommand();
|
||||
private:
|
||||
ChangePartCommand(const ChangePartCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Partie modifiee
|
||||
CustomElementPart *cep;
|
||||
/// Propriete modifiee
|
||||
QString property;
|
||||
/// ancienne valeur
|
||||
QVariant old_value;
|
||||
/// nouvelle valeur
|
||||
QVariant new_value;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier les points composants un polygone
|
||||
*/
|
||||
class ChangePolygonPointsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangePolygonPointsCommand(PartPolygon *, const QVector<QPointF> &, const QVector<QPointF> &, QUndoCommand * = 0);
|
||||
virtual ~ChangePolygonPointsCommand();
|
||||
private:
|
||||
ChangePolygonPointsCommand(const ChangePolygonPointsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
/// Polygone modifie
|
||||
PartPolygon *polygon;
|
||||
/// anciens points
|
||||
QVector<QPointF> old_points;
|
||||
/// nouveaux points
|
||||
QVector<QPointF> new_points;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de modifier les dimensions et le point de saisie d'un element
|
||||
*/
|
||||
class ChangeHotspotCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeHotspotCommand(ElementScene *, const QSize &, const QSize &, const QPoint &, const QPoint &, const QPoint & = QPoint(), QUndoCommand * = 0);
|
||||
virtual ~ChangeHotspotCommand();
|
||||
private:
|
||||
ChangeHotspotCommand(const ChangeHotspotCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
private:
|
||||
void applyOffset(const QPointF &);
|
||||
|
||||
// attributs
|
||||
/// Element edite auquel il faut appliquer les modifications
|
||||
ElementScene *element;
|
||||
/// dimensions avant l'action
|
||||
QSize size_before;
|
||||
/// dimensions apres l'action
|
||||
QSize size_after;
|
||||
/// point de saisie avant l'action
|
||||
QPoint hotspot_before;
|
||||
/// point de saisie apres l'action
|
||||
QPoint hotspot_after;
|
||||
/// decalage a appliquer aux elements
|
||||
QPoint offset;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de changer les noms d'un element
|
||||
*/
|
||||
class ChangeNamesCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeNamesCommand(ElementScene *, const NamesList &, const NamesList &, QUndoCommand * = 0);
|
||||
virtual ~ChangeNamesCommand();
|
||||
private:
|
||||
ChangeNamesCommand(const ChangeNamesCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Liste des noms avant changement
|
||||
NamesList names_before;
|
||||
/// Liste des noms apres changement
|
||||
NamesList names_after;
|
||||
/// Element edite auquel il faut appliquer les modifications
|
||||
ElementScene *element;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de changer les noms d'un element
|
||||
*/
|
||||
class ChangeOrientationsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ChangeOrientationsCommand(ElementScene *, const OrientationSet &, const OrientationSet &, QUndoCommand * = 0);
|
||||
virtual ~ChangeOrientationsCommand();
|
||||
private:
|
||||
ChangeOrientationsCommand(const ChangeOrientationsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Orientations avant changement
|
||||
OrientationSet ori_before;
|
||||
/// Orientations apres changement
|
||||
OrientationSet ori_after;
|
||||
/// Element edite auquel il faut appliquer les modifications
|
||||
ElementScene *element;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action de changer les noms d'un element
|
||||
*/
|
||||
class ChangeZValueCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/// Qualifie le type de changement de zValue
|
||||
enum Option {
|
||||
BringForward, ///< Amene la partie a l'avant-plan ; elle a alors la plus haute zValue
|
||||
Raise, ///< Amene la partie un plan au-dessus ; la zValue de la partie est incrementee
|
||||
Lower, ///< Envoie la partie un plan en-dessous ; la zValue de la partie est decrementee
|
||||
SendBackward ///< Envoie la partie a l'arriere-plan ; elle a alors la plus faible zValue
|
||||
};
|
||||
ChangeZValueCommand(ElementScene *, Option, QUndoCommand * = 0);
|
||||
virtual ~ChangeZValueCommand();
|
||||
private:
|
||||
ChangeZValueCommand(const ChangeZValueCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
private:
|
||||
void applyBringForward(const QList<QGraphicsItem *> &);
|
||||
void applyRaise(const QList<QGraphicsItem *> &);
|
||||
void applyLower(const QList<QGraphicsItem *> &);
|
||||
void applySendBackward(const QList<QGraphicsItem *> &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// zValues avant changement
|
||||
QHash<QGraphicsItem *, qreal> undo_hash;
|
||||
/// zValues apres changement
|
||||
QHash<QGraphicsItem *, qreal> redo_hash;
|
||||
/// Element edite auquel il faut appliquer les modifications
|
||||
ElementScene *element;
|
||||
/// type de traitement
|
||||
Option option;
|
||||
};
|
||||
|
||||
/**
|
||||
Cette classe represente l'action d'autoriser ou non les connexions
|
||||
internes pour un element.
|
||||
*/
|
||||
class AllowInternalConnectionsCommand : public QUndoCommand {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
AllowInternalConnectionsCommand(ElementScene *, bool, QUndoCommand * = 0);
|
||||
virtual ~AllowInternalConnectionsCommand();
|
||||
private:
|
||||
AllowInternalConnectionsCommand(const AllowInternalConnectionsCommand &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void undo();
|
||||
virtual void redo();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// Element edite auquel il faut appliquer les modifications
|
||||
ElementScene *element;
|
||||
/// autorisation des connexions internes apres modification
|
||||
bool ic;
|
||||
};
|
||||
#endif
|
||||
78
sources/editor/elementitemeditor.cpp
Normal file
78
sources/editor/elementitemeditor.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "elementitemeditor.h"
|
||||
#include "qetelementeditor.h"
|
||||
#include "editorcommands.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor QETElementEditor auquel cet editeur appartient
|
||||
@param parent QWidget parent de cet editeur
|
||||
*/
|
||||
ElementItemEditor::ElementItemEditor(QETElementEditor *editor, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
element_editor(editor)
|
||||
{
|
||||
}
|
||||
|
||||
/// @return le QETElementEditor auquel cet editeur appartient
|
||||
QETElementEditor *ElementItemEditor::elementEditor() const {
|
||||
return(element_editor);
|
||||
}
|
||||
|
||||
/// @return l'ElementScene contenant les parties editees par cet editeur
|
||||
ElementScene *ElementItemEditor::elementScene() const {
|
||||
return(element_editor -> elementScene());
|
||||
}
|
||||
|
||||
/// @return la QUndoStack a utiliser pour les annulations
|
||||
QUndoStack &ElementItemEditor::undoStack() const {
|
||||
return(elementScene() -> undoStack());
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute une ChangePartCommand a l'UndoStack. L'ancienne valeur sera
|
||||
automatiquement recuperee.
|
||||
@param desc nom de la propriete modifiee
|
||||
@param part partie modifiee
|
||||
@param prop propriete modifiee
|
||||
@param new_v nouvelle valeur
|
||||
*/
|
||||
void ElementItemEditor::addChangePartCommand(const QString &desc, CustomElementPart *part, const QString &prop, const QVariant &new_v) {
|
||||
QVariant old_v = part -> property(prop);
|
||||
if (old_v == new_v) return;
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
desc + " " + element_type_name,
|
||||
part,
|
||||
prop,
|
||||
old_v,
|
||||
new_v
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// @return Le nom du type d'element edite
|
||||
QString ElementItemEditor::elementTypeName() const {
|
||||
return(element_type_name);
|
||||
}
|
||||
|
||||
/// @param name Nom du type d'element edite
|
||||
void ElementItemEditor::setElementTypeName(const QString &name) {
|
||||
element_type_name = name;
|
||||
}
|
||||
53
sources/editor/elementitemeditor.h
Normal file
53
sources/editor/elementitemeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_ITEM_EDITOR_H
|
||||
#define ELEMENT_ITEM_EDITOR_H
|
||||
#include <QtGui>
|
||||
class QETElementEditor;
|
||||
class ElementScene;
|
||||
class CustomElementPart;
|
||||
/**
|
||||
Cette classe est la classe de base pour les editeurs de aprties 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.
|
||||
*/
|
||||
class ElementItemEditor : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementItemEditor(QETElementEditor *, QWidget * = 0);
|
||||
virtual ~ElementItemEditor() {};
|
||||
private:
|
||||
ElementItemEditor(const ElementItemEditor &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual QETElementEditor *elementEditor() const;
|
||||
virtual ElementScene *elementScene() const;
|
||||
virtual QUndoStack &undoStack() const;
|
||||
virtual void addChangePartCommand(const QString &, CustomElementPart *, const QString &, const QVariant &);
|
||||
virtual QString elementTypeName() const;
|
||||
virtual void setElementTypeName(const QString &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QETElementEditor *element_editor;
|
||||
QString element_type_name;
|
||||
};
|
||||
#endif
|
||||
732
sources/editor/elementscene.cpp
Normal file
732
sources/editor/elementscene.cpp
Normal file
@@ -0,0 +1,732 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "elementscene.h"
|
||||
#include "qetelementeditor.h"
|
||||
#include <cmath>
|
||||
#include "partline.h"
|
||||
#include "partellipse.h"
|
||||
#include "partcircle.h"
|
||||
#include "partpolygon.h"
|
||||
#include "partterminal.h"
|
||||
#include "parttext.h"
|
||||
#include "parttextfield.h"
|
||||
#include "partarc.h"
|
||||
#include "hotspoteditor.h"
|
||||
#include "editorcommands.h"
|
||||
|
||||
const int ElementScene::xGrid = 10;
|
||||
const int ElementScene::yGrid = 10;
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
||||
QGraphicsScene(parent),
|
||||
_width(3),
|
||||
_height(7),
|
||||
_hotspot(15, 35),
|
||||
internal_connections(false),
|
||||
qgi_manager(this),
|
||||
element_editor(editor)
|
||||
{
|
||||
current_polygon = NULL;
|
||||
undo_stack.setClean();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ElementScene::~ElementScene() {
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "selection et deplacement de parties"
|
||||
*/
|
||||
void ElementScene::slot_move() {
|
||||
behavior = Normal;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de ligne"
|
||||
*/
|
||||
void ElementScene::slot_addLine() {
|
||||
behavior = Line;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de cercle"
|
||||
*/
|
||||
void ElementScene::slot_addCircle() {
|
||||
behavior = Circle;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout d'ellipse"
|
||||
*/
|
||||
void ElementScene::slot_addEllipse() {
|
||||
behavior = Ellipse;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de polygone"
|
||||
*/
|
||||
void ElementScene::slot_addPolygon() {
|
||||
behavior = Polygon;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de texte statique"
|
||||
*/
|
||||
void ElementScene::slot_addText() {
|
||||
behavior = Text;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de borne"
|
||||
*/
|
||||
void ElementScene::slot_addTerminal() {
|
||||
behavior = Terminal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout d'arc de cercle"
|
||||
*/
|
||||
void ElementScene::slot_addArc() {
|
||||
behavior = Arc;
|
||||
}
|
||||
|
||||
/**
|
||||
Passe la scene en mode "ajout de champ de texte"
|
||||
*/
|
||||
void ElementScene::slot_addTextField() {
|
||||
behavior = TextField;
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements de la souris
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
QRectF temp_rect;
|
||||
qreal radius;
|
||||
QPointF temp_point;
|
||||
QPolygonF temp_polygon;
|
||||
if (e -> buttons() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Line:
|
||||
current_line -> setLine(QLineF(current_line -> line().p1(), e -> scenePos()));
|
||||
break;
|
||||
case Ellipse:
|
||||
temp_rect = current_ellipse -> rect();
|
||||
temp_rect.setBottomRight(e -> scenePos());
|
||||
current_ellipse -> setRect(temp_rect);
|
||||
break;
|
||||
case Arc:
|
||||
temp_rect = current_arc -> rect();
|
||||
temp_rect.setBottomRight(e -> scenePos());
|
||||
current_arc -> setRect(temp_rect);
|
||||
break;
|
||||
case Circle:
|
||||
temp_rect = current_circle -> rect();
|
||||
temp_point = e -> scenePos() - 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),
|
||||
QSizeF(2.0 * radius, 2.0 * radius)
|
||||
);
|
||||
current_circle -> setRect(temp_rect);
|
||||
break;
|
||||
case Polygon:
|
||||
if (current_polygon == NULL) break;
|
||||
temp_polygon = current_polygon -> polygon();
|
||||
temp_polygon.pop_back();
|
||||
temp_polygon << e -> scenePos();
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mouseMoveEvent(e);
|
||||
}
|
||||
} else if (behavior == Polygon && current_polygon != NULL) {
|
||||
temp_polygon = current_polygon -> polygon();
|
||||
temp_polygon.pop_back();
|
||||
temp_polygon << e -> scenePos();
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
} else QGraphicsScene::mouseMoveEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les appuis sur les boutons de la souris
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
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()));
|
||||
break;
|
||||
case Ellipse:
|
||||
current_ellipse = new PartEllipse(element_editor, 0, this);
|
||||
current_ellipse -> setRect(QRectF(e -> scenePos(), 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 -> 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 -> setProperty("antialias", true);
|
||||
break;
|
||||
case Polygon:
|
||||
if (current_polygon == NULL) {
|
||||
current_polygon = new PartPolygon(element_editor, 0, this);
|
||||
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();
|
||||
current_polygon -> setPolygon(temp_polygon);
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mousePressEvent(e);
|
||||
if (!selectedItems().isEmpty()) fsi_pos = selectedItems().first() -> scenePos();
|
||||
}
|
||||
} else QGraphicsScene::mousePressEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les relachements de boutons de la souris
|
||||
@param e objet decrivant l'evenement
|
||||
*/
|
||||
void ElementScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
PartTerminal *terminal;
|
||||
PartText *text;
|
||||
PartTextField *textfield;
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
break;
|
||||
case Terminal:
|
||||
terminal = new PartTerminal(element_editor, 0, this);
|
||||
terminal -> setPos(e -> scenePos());
|
||||
undo_stack.push(new AddPartCommand(tr("borne"), this, terminal));
|
||||
emit(partsAdded());
|
||||
break;
|
||||
case Text:
|
||||
text = new PartText(element_editor, 0, this);
|
||||
text -> setPos(e -> scenePos());
|
||||
undo_stack.push(new AddPartCommand(tr("texte"), this, text));
|
||||
emit(partsAdded());
|
||||
break;
|
||||
case TextField:
|
||||
textfield = new PartTextField(element_editor, 0, this);
|
||||
textfield -> setPos(e -> scenePos());
|
||||
undo_stack.push(new AddPartCommand(tr("champ de texte"), this, textfield));
|
||||
emit(partsAdded());
|
||||
break;
|
||||
case Normal:
|
||||
default:
|
||||
QGraphicsScene::mouseReleaseEvent(e);
|
||||
// detecte les deplacements de parties
|
||||
if (!selectedItems().isEmpty()) {
|
||||
QPointF movement = selectedItems().first() -> scenePos() - fsi_pos;
|
||||
if (!movement.isNull()) {
|
||||
undo_stack.push(new MovePartsCommand(movement, this, selectedItems()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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());
|
||||
} else QGraphicsScene::mouseReleaseEvent(e);
|
||||
} else QGraphicsScene::mouseReleaseEvent(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 ElementScene::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(-_hotspot.x(), -_hotspot.y(), width(), height());
|
||||
p -> setPen(Qt::black);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
p -> drawRect(drawable_area);
|
||||
|
||||
if (r.width() < 2500 && r.height() < 2500) {
|
||||
// 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 % xGrid) ++ g_x;
|
||||
int g_y = (int)ceil(r.y());
|
||||
while (g_y % yGrid) ++ g_y;
|
||||
|
||||
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
|
||||
p -> drawPoint(gx, gy);
|
||||
}
|
||||
}
|
||||
}
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'arriere-plan de l'editeur, cad l'indicateur de hotspot.
|
||||
@param p Le QPainter a utiliser pour dessiner
|
||||
@param r Le rectangle de la zone a dessiner
|
||||
*/
|
||||
void ElementScene::drawForeground(QPainter *p, const QRectF &) {
|
||||
p -> save();
|
||||
|
||||
// desactive tout antialiasing, sauf pour le texte
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, true);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
|
||||
p -> setPen(Qt::red);
|
||||
p -> setBrush(Qt::NoBrush);
|
||||
p -> drawLine(QLineF(0.0, -_hotspot.y(), 0.0, height() - _hotspot.y()));
|
||||
p -> drawLine(QLineF(-_hotspot.x(), 0.0, width() - _hotspot.x(), 0.0));
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte l'element en XML
|
||||
@return un document XML decrivant l'element
|
||||
*/
|
||||
const QDomDocument ElementScene::toXml() const {
|
||||
// document XML
|
||||
QDomDocument xml_document;
|
||||
|
||||
// racine du document XML
|
||||
QDomElement root = xml_document.createElement("definition");
|
||||
root.setAttribute("type", "element");
|
||||
root.setAttribute("width", QString("%1").arg(_width * 10));
|
||||
root.setAttribute("height", QString("%1").arg(_height * 10));
|
||||
root.setAttribute("hotspot_x", QString("%1").arg(_hotspot.x()));
|
||||
root.setAttribute("hotspot_y", QString("%1").arg(_hotspot.y()));
|
||||
root.setAttribute("orientation", ori.toString());
|
||||
root.setAttribute("version", QET::version);
|
||||
if (internal_connections) root.setAttribute("ic", "true");
|
||||
|
||||
// noms de l'element
|
||||
root.appendChild(_names.toXml(xml_document));
|
||||
|
||||
QDomElement description = xml_document.createElement("description");
|
||||
// description de l'element
|
||||
foreach(QGraphicsItem *qgi, zItems(true)) {
|
||||
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
|
||||
if (ce -> isUseless()) continue;
|
||||
description.appendChild(ce -> toXml(xml_document));
|
||||
}
|
||||
}
|
||||
root.appendChild(description);
|
||||
|
||||
xml_document.appendChild(root);
|
||||
return(xml_document);
|
||||
}
|
||||
|
||||
/**
|
||||
Lit un element depuis un document XML
|
||||
@param xml_document un document XML decrivant l'element
|
||||
*/
|
||||
void ElementScene::fromXml(const QDomDocument &xml_document) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@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 la pile d'annulations de cet editeur d'element
|
||||
*/
|
||||
QUndoStack &ElementScene::undoStack() {
|
||||
return(undo_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le gestionnaire de QGraphicsItem de cet editeur d'element
|
||||
*/
|
||||
QGIManager &ElementScene::qgiManager() {
|
||||
return(qgi_manager);
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne tout
|
||||
*/
|
||||
void ElementScene::slot_selectAll() {
|
||||
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Deselectionne tout
|
||||
*/
|
||||
void ElementScene::slot_deselectAll() {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
Inverse la selection
|
||||
*/
|
||||
void ElementScene::slot_invertSelection() {
|
||||
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(!qgi -> isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime les elements selectionnes
|
||||
*/
|
||||
void ElementScene::slot_delete() {
|
||||
// verifie qu'il y a qqc de selectionne
|
||||
QList<QGraphicsItem *> selected_items = selectedItems();
|
||||
if (selected_items.isEmpty()) return;
|
||||
|
||||
// efface tout ce qui est selectionne
|
||||
undo_stack.push(new DeletePartsCommand(this, selected_items));
|
||||
emit(partsRemoved());
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un dialogue pour editer les dimensions et le point de saisie
|
||||
(hotspot) de l'element.
|
||||
*/
|
||||
void ElementScene::slot_editSizeHotSpot() {
|
||||
// cree un dialogue
|
||||
QDialog dialog_sh;
|
||||
dialog_sh.setModal(true);
|
||||
dialog_sh.setMinimumSize(400, 230);
|
||||
dialog_sh.setWindowTitle(tr("\311diter la taille et le point de saisie"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_sh);
|
||||
|
||||
// ajoute un HotspotEditor au dialogue
|
||||
HotspotEditor *hotspot_editor = new HotspotEditor();
|
||||
hotspot_editor -> setElementWidth(static_cast<uint>(width() / 10));
|
||||
hotspot_editor -> setElementHeight(static_cast<uint>(height() / 10));
|
||||
hotspot_editor -> setHotspot(hotspot());
|
||||
hotspot_editor -> setOldHotspot(hotspot());
|
||||
hotspot_editor -> setPartsRect(itemsBoundingRect());
|
||||
hotspot_editor -> setPartsRectEnabled(true);
|
||||
dialog_layout -> addWidget(hotspot_editor);
|
||||
|
||||
// ajoute deux boutons au dialogue
|
||||
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
dialog_layout -> addWidget(dialog_buttons);
|
||||
connect(dialog_buttons, SIGNAL(accepted()), &dialog_sh, SLOT(accept()));
|
||||
connect(dialog_buttons, SIGNAL(rejected()), &dialog_sh, SLOT(reject()));
|
||||
|
||||
// lance le dialogue
|
||||
if (dialog_sh.exec() != QDialog::Accepted) return;
|
||||
QSize new_size(hotspot_editor -> elementSize());
|
||||
QSize old_size(width(), height());
|
||||
QPoint new_hotspot(hotspot_editor -> hotspot());
|
||||
QPoint old_hotspot(_hotspot);
|
||||
|
||||
if (new_size != old_size || new_hotspot != old_hotspot) {
|
||||
undo_stack.push(new ChangeHotspotCommand(this, old_size, new_size, old_hotspot, new_hotspot, hotspot_editor -> offsetParts()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un dialogue pour editer les noms de cete element
|
||||
*/
|
||||
void ElementScene::slot_editOrientations() {
|
||||
|
||||
// cree un dialogue
|
||||
QDialog dialog_ori;
|
||||
dialog_ori.setModal(true);
|
||||
dialog_ori.setMinimumSize(400, 260);
|
||||
dialog_ori.setWindowTitle(tr("\311diter les orientations"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_ori);
|
||||
|
||||
// ajoute un champ explicatif au dialogue
|
||||
QLabel *information_label = new QLabel(tr("L'orientation par d\351faut est l'orientation dans laquelle s'effectue la cr\351ation de l'\351l\351ment."));
|
||||
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
|
||||
information_label -> setWordWrap(true);
|
||||
dialog_layout -> addWidget(information_label);
|
||||
|
||||
// ajoute un OrientationSetWidget au dialogue
|
||||
OrientationSetWidget *ori_widget = new OrientationSetWidget();
|
||||
ori_widget -> setOrientationSet(ori);
|
||||
dialog_layout -> addWidget(ori_widget);
|
||||
|
||||
// ajoute une case a cocher pour les connexions internes
|
||||
QCheckBox *ic_checkbox = new QCheckBox(tr("Autoriser les connexions internes"));
|
||||
ic_checkbox -> setChecked(internal_connections);
|
||||
dialog_layout -> addWidget(ic_checkbox);
|
||||
dialog_layout -> addStretch();
|
||||
// ajoute deux boutons au dialogue
|
||||
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
dialog_layout -> addWidget(dialog_buttons);
|
||||
connect(dialog_buttons, SIGNAL(accepted()), &dialog_ori, SLOT(accept()));
|
||||
connect(dialog_buttons, SIGNAL(rejected()), &dialog_ori, SLOT(reject()));
|
||||
|
||||
// lance le dialogue
|
||||
if (dialog_ori.exec() == QDialog::Accepted) {
|
||||
OrientationSet new_ori = ori_widget -> orientationSet();
|
||||
if (new_ori != ori) {
|
||||
undoStack().push(new ChangeOrientationsCommand(this, ori, new_ori));
|
||||
}
|
||||
if (ic_checkbox -> isChecked() != internal_connections) {
|
||||
undoStack().push(new AllowInternalConnectionsCommand(this, ic_checkbox -> isChecked()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un dialogue pour editer les noms de cet element
|
||||
*/
|
||||
void ElementScene::slot_editNames() {
|
||||
|
||||
// cree un dialogue
|
||||
QDialog dialog;
|
||||
dialog.setModal(true);
|
||||
dialog.setMinimumSize(400, 330);
|
||||
dialog.setWindowTitle(tr("\311diter les noms"));
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog);
|
||||
|
||||
// ajoute un champ explicatif au dialogue
|
||||
QLabel *information_label = new QLabel(tr("Vous pouvez sp\351cifier le nom de l'\351l\351ment dans plusieurs langues."));
|
||||
information_label -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
|
||||
information_label -> setWordWrap(true);
|
||||
dialog_layout -> addWidget(information_label);
|
||||
|
||||
// ajoute un NamesListWidget au dialogue
|
||||
NamesListWidget *names_widget = new NamesListWidget();
|
||||
names_widget -> setNames(_names);
|
||||
dialog_layout -> addWidget(names_widget);
|
||||
|
||||
// ajoute deux boutons au dialogue
|
||||
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
dialog_layout -> addWidget(dialog_buttons);
|
||||
connect(dialog_buttons, SIGNAL(accepted()), names_widget, SLOT(check()));
|
||||
connect(names_widget, SIGNAL(inputChecked()), &dialog, SLOT(accept()));
|
||||
connect(dialog_buttons, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
||||
|
||||
// lance le dialogue
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
NamesList new_names(names_widget -> names());
|
||||
if (new_names != _names) undoStack().push(new ChangeNamesCommand(this, _names, new_names));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Amene les elements selectionnes au premier plan
|
||||
*/
|
||||
void ElementScene::slot_bringForward() {
|
||||
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::BringForward));
|
||||
emit(partsZValueChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Remonte les elements selectionnes d'un plan
|
||||
*/
|
||||
void ElementScene::slot_raise() {
|
||||
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Raise));
|
||||
emit(partsZValueChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Descend les elements selectionnes d'un plan
|
||||
*/
|
||||
void ElementScene::slot_lower() {
|
||||
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Lower));
|
||||
emit(partsZValueChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
Envoie les elements selectionnes au fond
|
||||
*/
|
||||
void ElementScene::slot_sendBackward() {
|
||||
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::SendBackward));
|
||||
emit(partsZValueChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
@param include_terminals true pour inclure les bornes, false sinon
|
||||
@return les parties de l'element ordonnes par zValue croissante
|
||||
*/
|
||||
QList<QGraphicsItem *> ElementScene::zItems(bool include_terminals) const {
|
||||
// recupere les elements
|
||||
QList<QGraphicsItem *> all_items_list(items());
|
||||
|
||||
// enleve les bornes
|
||||
QList<QGraphicsItem *> terminals;
|
||||
foreach(QGraphicsItem *qgi, all_items_list) {
|
||||
if (qgraphicsitem_cast<PartTerminal *>(qgi)) {
|
||||
all_items_list.removeAt(all_items_list.indexOf(qgi));
|
||||
terminals << qgi;
|
||||
}
|
||||
}
|
||||
|
||||
// ordonne les parties par leur zValue
|
||||
QMultiMap<qreal, QGraphicsItem *> mm;
|
||||
foreach(QGraphicsItem *qgi, all_items_list) mm.insert(qgi -> zValue(), qgi);
|
||||
all_items_list.clear();
|
||||
QMapIterator<qreal, QGraphicsItem *> i(mm);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
all_items_list << i.value();
|
||||
}
|
||||
|
||||
// rajoute eventuellement les bornes
|
||||
if (include_terminals) all_items_list += terminals;
|
||||
return(all_items_list);
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime les parties de l'element et les objets d'annulations.
|
||||
Les autres caracteristiques sont conservees.
|
||||
*/
|
||||
void ElementScene::reset() {
|
||||
// supprime les objets d'annulation
|
||||
undoStack().clear();
|
||||
// enleve les elements de la scene
|
||||
foreach (QGraphicsItem *qgi, items()) {
|
||||
removeItem(qgi);
|
||||
qgiManager().release(qgi);
|
||||
}
|
||||
}
|
||||
238
sources/editor/elementscene.h
Normal file
238
sources/editor/elementscene.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_SCENE_H
|
||||
#define ELEMENT_SCENE_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include "nameslistwidget.h"
|
||||
#include "orientationsetwidget.h"
|
||||
#include "qgimanager.h"
|
||||
class QETElementEditor;
|
||||
class PartLine;
|
||||
class PartEllipse;
|
||||
class PartCircle;
|
||||
class PartPolygon;
|
||||
class PartArc;
|
||||
/**
|
||||
Cette classe est le canevas permettant l'edition d'un element electrique.
|
||||
Elle regroupe les differentes parties composant le dessin de l'element mais
|
||||
egalement les informations complementaires : dimensions, orientations,
|
||||
noms.
|
||||
*/
|
||||
class ElementScene : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
|
||||
// enum
|
||||
enum Behavior { Normal, Line, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField };
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementScene(QETElementEditor *, QObject * = 0);
|
||||
virtual ~ElementScene();
|
||||
|
||||
private:
|
||||
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;
|
||||
/// hauteur de l'element en dizaines de pixels
|
||||
uint _height;
|
||||
/// position du point de saisie
|
||||
QPoint _hotspot;
|
||||
/// Liste des noms de l'element
|
||||
NamesList _names;
|
||||
/// Liste des orientations de l'element
|
||||
OrientationSet ori;
|
||||
/// booleen indiquant si les bornes de l'element peuvent etre reliees a des bornes de ce meme element
|
||||
bool internal_connections;
|
||||
/// Gestionnaire de QGraphicsItem
|
||||
QGIManager qgi_manager;
|
||||
/// Pile des actions annulables
|
||||
QUndoStack undo_stack;
|
||||
/// Position du premier item selectionne (utilise pour annuler les deplacements)
|
||||
QPointF fsi_pos;
|
||||
|
||||
/// Variables relatives a la gestion du dessin des parties sur la scene
|
||||
Behavior behavior;
|
||||
PartLine *current_line;
|
||||
PartEllipse *current_ellipse;
|
||||
PartCircle *current_circle;
|
||||
PartPolygon *current_polygon;
|
||||
PartArc *current_arc;
|
||||
QETElementEditor *element_editor;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setWidth(const uint &);
|
||||
uint width() const;
|
||||
void setHeight(const uint &);
|
||||
uint height() const;
|
||||
void setHotspot(const QPoint &);
|
||||
QPoint hotspot() const;
|
||||
void setNames(const NamesList &);
|
||||
NamesList names() const;
|
||||
OrientationSet orientations();
|
||||
void setOrientations(const OrientationSet &);
|
||||
bool internalConnections();
|
||||
void setInternalConnections(bool);
|
||||
virtual const QDomDocument toXml() const;
|
||||
virtual void fromXml(const QDomDocument &);
|
||||
virtual void reset();
|
||||
virtual QList<QGraphicsItem *> zItems(bool = false) const;
|
||||
QRectF sceneContent() const;
|
||||
QUndoStack &undoStack();
|
||||
QGIManager &qgiManager();
|
||||
|
||||
protected:
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual void drawBackground(QPainter *, const QRectF &);
|
||||
virtual void drawForeground(QPainter *, const QRectF &);
|
||||
|
||||
public slots:
|
||||
void slot_move();
|
||||
void slot_addLine();
|
||||
void slot_addCircle();
|
||||
void slot_addEllipse();
|
||||
void slot_addPolygon();
|
||||
void slot_addText();
|
||||
void slot_addArc();
|
||||
void slot_addTerminal();
|
||||
void slot_addTextField();
|
||||
void slot_selectAll();
|
||||
void slot_deselectAll();
|
||||
void slot_invertSelection();
|
||||
void slot_delete();
|
||||
void slot_editSizeHotSpot();
|
||||
void slot_editNames();
|
||||
void slot_editOrientations();
|
||||
void slot_bringForward();
|
||||
void slot_raise();
|
||||
void slot_lower();
|
||||
void slot_sendBackward();
|
||||
|
||||
signals:
|
||||
/**
|
||||
Signal emis lorsque la scene exige que l'editeur d'element repasse
|
||||
en mode normal
|
||||
*/
|
||||
void needNormalMode();
|
||||
/// Signal emis lorsqu'une ou plusieurs parties sont ajoutees
|
||||
void partsAdded();
|
||||
/// Signal emis lorsqu'une ou plusieurs parties sont enlevees
|
||||
void partsRemoved();
|
||||
/// Signal emis lorsque la zValue d'une ou plusieurs parties change
|
||||
void partsZValueChanged();
|
||||
};
|
||||
|
||||
/**
|
||||
@param wid Nouvelle largeur de l'element edite
|
||||
*/
|
||||
inline void ElementScene::setWidth(const uint &wid) {
|
||||
_width = wid;
|
||||
while (_width % 10) ++ _width;
|
||||
_width /= 10;
|
||||
}
|
||||
|
||||
/**
|
||||
@return la largeur de l'element edite
|
||||
*/
|
||||
inline uint ElementScene::width() const {
|
||||
return(_width * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@param hei Nouvelle hauteur de l'element edite
|
||||
*/
|
||||
inline void ElementScene::setHeight(const uint &hei) {
|
||||
_height = hei;
|
||||
while (_height % 10) ++ _height;
|
||||
_height /= 10;
|
||||
}
|
||||
|
||||
/**
|
||||
@return la largeur de l'element edite
|
||||
*/
|
||||
inline uint ElementScene::height() const {
|
||||
return(_height * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@param hs Nouveau point de saisie de l'element edite
|
||||
*/
|
||||
inline void ElementScene::setHotspot(const QPoint &hs) {
|
||||
_hotspot = hs;
|
||||
}
|
||||
|
||||
/**
|
||||
@return le point de saisie de l'element edite
|
||||
*/
|
||||
inline QPoint ElementScene::hotspot() const {
|
||||
return(_hotspot);
|
||||
}
|
||||
|
||||
/**
|
||||
@param nameslist Nouvel ensemble de noms de l'element edite
|
||||
*/
|
||||
inline void ElementScene::setNames(const NamesList &nameslist) {
|
||||
_names = nameslist;
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'ensemble de noms de l'element edite
|
||||
*/
|
||||
inline NamesList ElementScene::names() const {
|
||||
return(_names);
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'ensemble d'orientations de l'element edite
|
||||
*/
|
||||
inline OrientationSet ElementScene::orientations() {
|
||||
return(ori);
|
||||
}
|
||||
|
||||
/**
|
||||
@param orientation_set Nouvel ensemble d'orientations de l'element edite
|
||||
*/
|
||||
inline void ElementScene::setOrientations(const OrientationSet &orientation_set) {
|
||||
ori = orientation_set;
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si les connexions internes sont acceptees, false sinon
|
||||
*/
|
||||
inline bool ElementScene::internalConnections() {
|
||||
return(internal_connections);
|
||||
}
|
||||
|
||||
/**
|
||||
@param ic true pour que les connexions internes soient acceptees, false sinon
|
||||
*/
|
||||
inline void ElementScene::setInternalConnections(bool ic) {
|
||||
internal_connections = ic;
|
||||
}
|
||||
|
||||
#endif
|
||||
128
sources/editor/elementview.cpp
Normal file
128
sources/editor/elementview.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "elementview.h"
|
||||
/**
|
||||
Constructeur
|
||||
@param scene ElementScene visualisee par cette ElementView
|
||||
@param parent QWidget parent de cette ElementView
|
||||
*/
|
||||
ElementView::ElementView(ElementScene *scene, QWidget *parent) :
|
||||
QGraphicsView(scene, parent),
|
||||
scene_(scene)
|
||||
{
|
||||
setInteractive(true);
|
||||
setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
zoomReset();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ElementView::~ElementView() {
|
||||
}
|
||||
|
||||
/// @return l'ElementScene visualisee par cette ElementView
|
||||
ElementScene *ElementView::scene() const {
|
||||
return(scene_);
|
||||
}
|
||||
|
||||
/**
|
||||
Definit l'ElementScene visualisee par cette ElementView
|
||||
@param s l'ElementScene visualisee par cette ElementView
|
||||
*/
|
||||
void ElementView::setScene(ElementScene *s) {
|
||||
QGraphicsView::setScene(s);
|
||||
scene_ = s;
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les evenements envoyes a la vue.
|
||||
Methode reimplentee pour gerer le conflit de raccourcis avec Suppr
|
||||
(supprimer une partie ou supprimer le caractere suivant)
|
||||
@param e evenement a gerer
|
||||
*/
|
||||
bool ElementView::event(QEvent *e) {
|
||||
if (e -> type() == QEvent::ShortcutOverride && scene_ -> focusItem()) {
|
||||
e -> accept();
|
||||
return(true);
|
||||
}
|
||||
return(QGraphicsView::event(e));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
|
||||
*/
|
||||
void ElementView::zoomIn() {
|
||||
scale(4.0/3.0, 4.0/3.0);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrecit le schema (-25% = inverse des +33 % de zoomPlus())
|
||||
*/
|
||||
void ElementView::zoomOut() {
|
||||
scale(0.75, 0.75);
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit ou rectrecit le schema de facon a ce que tous les elements du
|
||||
schema soient visibles a l'ecran. S'il n'y a aucun element sur le schema,
|
||||
le zoom est reinitialise
|
||||
*/
|
||||
void ElementView::zoomFit() {
|
||||
adjustSceneRect();
|
||||
fitInView(sceneRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
Reinitialise le zoom
|
||||
*/
|
||||
void ElementView::zoomReset() {
|
||||
resetMatrix();
|
||||
scale(4.0, 4.0);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajuste le sceneRect (zone du schema visualisee par l'ElementView) afin que
|
||||
celui inclut a la fois les parties dans et en dehors du cadre et le cadre
|
||||
lui-meme.
|
||||
*/
|
||||
void ElementView::adjustSceneRect() {
|
||||
QRectF old_scene_rect = scene_ -> sceneRect();
|
||||
QRectF new_scene_rect = scene_ -> sceneContent();
|
||||
setSceneRect(new_scene_rect);
|
||||
|
||||
// met a jour la scene
|
||||
scene_ -> update(old_scene_rect.united(new_scene_rect));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les actions liees a la rollette de la souris
|
||||
@param e QWheelEvent decrivant l'evenement rollette
|
||||
*/
|
||||
void ElementView::wheelEvent(QWheelEvent *e) {
|
||||
// si la touche Ctrl est enfoncee, on zoome / dezoome
|
||||
if (e -> modifiers() & Qt::ControlModifier) {
|
||||
if (e -> delta() > 0) {
|
||||
zoomIn();
|
||||
} else {
|
||||
zoomOut();
|
||||
}
|
||||
} else {
|
||||
QAbstractScrollArea::wheelEvent(e);
|
||||
}
|
||||
}
|
||||
56
sources/editor/elementview.h
Normal file
56
sources/editor/elementview.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_VIEW_H
|
||||
#define ELEMENT_VIEW_H
|
||||
#include <QGraphicsView>
|
||||
#include "elementscene.h"
|
||||
/**
|
||||
Cette classe represente un widget permettant de visualiser une
|
||||
ElementScene, c'est-a-dire la classe d'edition des elements.
|
||||
*/
|
||||
class ElementView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementView(ElementScene *, QWidget * = 0);
|
||||
virtual ~ElementView();
|
||||
|
||||
private:
|
||||
ElementView(const ElementView &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
ElementScene *scene() const;
|
||||
void setScene(ElementScene *);
|
||||
protected:
|
||||
bool event(QEvent *);
|
||||
void wheelEvent(QWheelEvent *);
|
||||
|
||||
// slots
|
||||
public slots:
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void zoomFit();
|
||||
void zoomReset();
|
||||
void adjustSceneRect();
|
||||
|
||||
//attributs
|
||||
private:
|
||||
ElementScene *scene_;
|
||||
};
|
||||
#endif
|
||||
108
sources/editor/ellipseeditor.cpp
Normal file
108
sources/editor/ellipseeditor.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "ellipseeditor.h"
|
||||
#include "partellipse.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param ellipse L'ellipse a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
EllipseEditor::EllipseEditor(QETElementEditor *editor, PartEllipse *ellipse, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
|
||||
part = ellipse;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
h = new QLineEdit();
|
||||
v = new QLineEdit();
|
||||
|
||||
x -> setValidator(new QDoubleValidator(x));
|
||||
y -> setValidator(new QDoubleValidator(y));
|
||||
h -> setValidator(new QDoubleValidator(h));
|
||||
v -> setValidator(new QDoubleValidator(v));
|
||||
|
||||
QGridLayout *grid = new QGridLayout(this);
|
||||
grid -> addWidget(new QLabel(tr("Centre : ")), 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("Diam\350tres : ")), 2, 0);
|
||||
grid -> addWidget(new QLabel(tr("horizontal :")), 3, 0);
|
||||
grid -> addWidget(h, 3, 1);
|
||||
grid -> addWidget(new QLabel(tr("vertical :")), 4, 0);
|
||||
grid -> addWidget(v, 4, 1);
|
||||
|
||||
activeConnections(true);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
EllipseEditor::~EllipseEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour l'ellipse a partir des donnees du formulaire
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du centre de l'ellipse et cree un objet d'annulation
|
||||
void EllipseEditor::updateEllipseX() { addChangePartCommand(tr("abscisse"), part, "x", x -> text().toDouble()); }
|
||||
/// Met a jour l'ordonnee du centre de l'ellipse et cree un objet d'annulation
|
||||
void EllipseEditor::updateEllipseY() { addChangePartCommand(tr("ordonn\351e"), part, "y", y -> text().toDouble()); }
|
||||
/// Met a jour le diametre horizontal de l'ellipse et cree un objet d'annulation
|
||||
void EllipseEditor::updateEllipseH() { addChangePartCommand(tr("diam\350tre horizontal"), part, "diameter_h", h -> text().toDouble()); }
|
||||
/// Met a jour le diametre vertical de l'ellipse et cree un objet d'annulation
|
||||
void EllipseEditor::updateEllipseV() { addChangePartCommand(tr("diam\350tre vertical"), part, "diameter_v", v -> text().toDouble()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void EllipseEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
x -> setText(part -> property("x").toString());
|
||||
y -> setText(part -> property("y").toString());
|
||||
h -> setText(part -> property("diameter_h").toString());
|
||||
v -> setText(part -> property("diameter_v").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 EllipseEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateEllipseX()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateEllipseY()));
|
||||
connect(h, SIGNAL(editingFinished()), this, SLOT(updateEllipseH()));
|
||||
connect(v, SIGNAL(editingFinished()), this, SLOT(updateEllipseV()));
|
||||
} else {
|
||||
disconnect(x, SIGNAL(editingFinished()), this, SLOT(updateEllipseX()));
|
||||
disconnect(y, SIGNAL(editingFinished()), this, SLOT(updateEllipseY()));
|
||||
disconnect(h, SIGNAL(editingFinished()), this, SLOT(updateEllipseH()));
|
||||
disconnect(v, SIGNAL(editingFinished()), this, SLOT(updateEllipseV()));
|
||||
}
|
||||
}
|
||||
53
sources/editor/ellipseeditor.h
Normal file
53
sources/editor/ellipseeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 ELLIPSE_EDITOR_H
|
||||
#define ELLIPSE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartEllipse;
|
||||
/**
|
||||
Cette classe represente le widget d'edition d'une ellipse dans l'editeur
|
||||
d'element.
|
||||
*/
|
||||
class EllipseEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
EllipseEditor(QETElementEditor *, PartEllipse *, QWidget * = 0);
|
||||
~EllipseEditor();
|
||||
private:
|
||||
EllipseEditor(const EllipseEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartEllipse *part;
|
||||
QLineEdit *x, *y, *h, *v;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateEllipse();
|
||||
void updateEllipseX();
|
||||
void updateEllipseY();
|
||||
void updateEllipseH();
|
||||
void updateEllipseV();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
115
sources/editor/lineeditor.cpp
Normal file
115
sources/editor/lineeditor.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "lineeditor.h"
|
||||
#include "partline.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param line La ligne a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
LineEditor::LineEditor(QETElementEditor *editor, PartLine *line, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
|
||||
part = line;
|
||||
|
||||
x1 = new QLineEdit();
|
||||
y1 = new QLineEdit();
|
||||
x2 = new QLineEdit();
|
||||
y2 = new QLineEdit();
|
||||
|
||||
x1 -> setValidator(new QDoubleValidator(x1));
|
||||
y1 -> setValidator(new QDoubleValidator(y1));
|
||||
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);
|
||||
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
LineEditor::~LineEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la ligne a partir des donnees du formulaire
|
||||
*/
|
||||
void LineEditor::updateLine() {
|
||||
part -> setLine(
|
||||
QLineF(
|
||||
part -> mapFromScene(
|
||||
x1 -> text().toDouble(),
|
||||
y1 -> text().toDouble()
|
||||
),
|
||||
part -> mapFromScene(
|
||||
x2 -> text().toDouble(),
|
||||
y2 -> text().toDouble()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse du premier point de la ligne et cree un objet d'annulation
|
||||
void LineEditor::updateLineX1() { addChangePartCommand(tr("abscisse point 1"), part, "x1", x1 -> text().toDouble()); }
|
||||
/// Met a jour l'ordonnee du premier point de la ligne et cree un objet d'annulation
|
||||
void LineEditor::updateLineY1() { addChangePartCommand(tr("ordonn\351e point 1"), part, "y1", y1 -> text().toDouble()); }
|
||||
/// Met a jour l'abscisse du second point de la ligne et cree un objet d'annulation
|
||||
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 formulaire d'edition
|
||||
*/
|
||||
void LineEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
QPointF p1(part -> sceneP1());
|
||||
QPointF p2(part -> sceneP2());
|
||||
x1 -> setText(QString("%1").arg(p1.x()));
|
||||
y1 -> setText(QString("%1").arg(p1.y()));
|
||||
x2 -> setText(QString("%1").arg(p2.x()));
|
||||
y2 -> setText(QString("%1").arg(p2.y()));
|
||||
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 LineEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
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()));
|
||||
} 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()));
|
||||
}
|
||||
}
|
||||
53
sources/editor/lineeditor.h
Normal file
53
sources/editor/lineeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 LINE_EDITOR_H
|
||||
#define LINE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartLine;
|
||||
/**
|
||||
Cette classe represente le widget d'edition d'une ligne dans l'editeur
|
||||
d'element.
|
||||
*/
|
||||
class LineEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
LineEditor(QETElementEditor *, PartLine *, QWidget * = 0);
|
||||
~LineEditor();
|
||||
private:
|
||||
LineEditor(const LineEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartLine *part;
|
||||
QLineEdit *x1, *y1, *x2, *y2;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateLine();
|
||||
void updateLineX1();
|
||||
void updateLineY1();
|
||||
void updateLineX2();
|
||||
void updateLineY2();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
263
sources/editor/partarc.cpp
Normal file
263
sources/editor/partarc.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partarc.h"
|
||||
#include "arceditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de cet arc
|
||||
@param scene La scene sur laquelle figure cet arc
|
||||
*/
|
||||
PartArc::PartArc(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsEllipseItem(parent, scene),
|
||||
CustomElementGraphicPart(editor),
|
||||
_angle(-90),
|
||||
start_angle(0)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new ArcEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartArc::~PartArc() {
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'arc de cercle
|
||||
@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 PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
applyStylesToQPainter(*painter);
|
||||
// enleve systematiquement la couleur de fond
|
||||
painter -> setBrush(Qt::NoBrush);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
// dessine l'ellipse en noir
|
||||
painter -> drawEllipse(rect());
|
||||
|
||||
// dessine l'arc en rouge
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
painter -> drawArc(rect(), start_angle * 16, _angle * 16);
|
||||
if (isSelected()) {
|
||||
// dessine la croix au centre de l'ellipse
|
||||
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 l'arc de cercle en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant l'arc de cercle
|
||||
*/
|
||||
const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("arc");
|
||||
QPointF top_left(sceneTopLeft());
|
||||
xml_element.setAttribute("x", top_left.x());
|
||||
xml_element.setAttribute("y", top_left.y());
|
||||
xml_element.setAttribute("width", rect().width());
|
||||
xml_element.setAttribute("height", rect().height());
|
||||
xml_element.setAttribute("start", start_angle);
|
||||
xml_element.setAttribute("angle", _angle);
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'un arc de cercle depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartArc::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()
|
||||
)
|
||||
)
|
||||
);
|
||||
setStartAngle(qde.attribute("start", "0").toInt());
|
||||
setAngle(qde.attribute("angle", "-90").toInt());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le coin superieur gauche du rectangle dans lequel s'inscrit
|
||||
l'ellipse dont fait partie cet arc, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartArc::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee de l'arc
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse du centre de l'ellipse dont fait partie l'arc
|
||||
* y : ordonnee du centre de l'ellipse dont fait partie l'arc
|
||||
* diameter_h : diametre horizontal de l'ellipse dont fait partie l'arc
|
||||
* diameter_v : diametre vertical de l'ellipse dont fait partie l'arc
|
||||
* start_angle : angle de depart
|
||||
* angle : taille de l'arc de cercle
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartArc::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.center());
|
||||
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.center());
|
||||
setRect(current_rect.translated(0.0, value.toDouble() - current_pos.y()));
|
||||
} else if (property == "diameter_h") {
|
||||
qreal new_width = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.translate((new_width - current_rect.width()) / -2.0, 0.0);
|
||||
current_rect.setWidth(new_width);
|
||||
setRect(current_rect);
|
||||
} else if (property == "diameter_v") {
|
||||
qreal new_height = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.translate(0.0, (new_height - current_rect.height()) / -2.0);
|
||||
current_rect.setHeight(new_height);
|
||||
setRect(current_rect);
|
||||
} else if (property == "start_angle") {
|
||||
setStartAngle(value.toInt() );
|
||||
} else if (property == "angle") {
|
||||
setAngle(value.toInt());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee de l'arc de cercle
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse du centre de l'ellipse dont fait partie l'arc
|
||||
* y : ordonnee du centre de l'ellipse dont fait partie l'arc
|
||||
* diameter_h : diametre horizontal de l'ellipse dont fait partie l'arc
|
||||
* diameter_v : diametre vertical de l'ellipse dont fait partie l'arc
|
||||
* start_angle : angle de depart
|
||||
* angle : taille de l'arc de cercle
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartArc::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().center()).x());
|
||||
} else if (property == "y") {
|
||||
return(mapToScene(rect().center()).y());
|
||||
} else if (property == "diameter_h") {
|
||||
return(rect().width());
|
||||
} else if (property == "diameter_v") {
|
||||
return(rect().height());
|
||||
} else if (property == "start_angle") {
|
||||
return(start_angle);
|
||||
} else if (property == "angle") {
|
||||
return(_angle);
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartArc::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsEllipseItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de modifier l'etendue de l'arc de cercle.
|
||||
Il s'agit d'un angle, exprime en degres.
|
||||
Si l'angle est positif, l'arc s'etendra dans le sens des aiguilles d'une
|
||||
montre.
|
||||
@param a la nouvelle taille de l'arc de cercle
|
||||
*/
|
||||
void PartArc::setAngle(int a) {
|
||||
_angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de modifier la position de depart de l'arc de cercle.
|
||||
Il s'agit d'un angle, exprime en degres.
|
||||
l'angle "0 degre" est situe a "3 heures".
|
||||
@param a la nouvelle taille de l'arc de cercle
|
||||
*/
|
||||
void PartArc::setStartAngle(int a) {
|
||||
start_angle = a;
|
||||
}
|
||||
|
||||
/**
|
||||
@return l'etendue de l'arc de cercle
|
||||
*/
|
||||
int PartArc::angle() const {
|
||||
return(_angle);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la position de depart de l'arc de cercle
|
||||
*/
|
||||
int PartArc::startAngle() const {
|
||||
return(start_angle);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un arc est pertinent des lors que ses dimensions et son etendue ne sont
|
||||
pas nulles.
|
||||
*/
|
||||
bool PartArc::isUseless() const {
|
||||
return(rect().isNull() || !angle());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartArc::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsEllipseItem::boundingRect().normalized());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
67
sources/editor/partarc.h
Normal file
67
sources/editor/partarc.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_ARC_H
|
||||
#define PART_ARC_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class ArcEditor;
|
||||
/**
|
||||
Cette classe represente un arc pouvant etre utilise pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartArc : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartArc(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartArc();
|
||||
|
||||
private:
|
||||
PartArc(const PartArc &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ArcEditor *informations;
|
||||
int _angle;
|
||||
int start_angle;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1101 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartArc 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("arc")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
virtual QRectF boundingRect() const;
|
||||
virtual void setAngle(int);
|
||||
virtual void setStartAngle(int);
|
||||
virtual int angle() const;
|
||||
virtual int startAngle() const;
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
#endif
|
||||
199
sources/editor/partcircle.cpp
Normal file
199
sources/editor/partcircle.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partcircle.h"
|
||||
#include "circleeditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de ce cercle
|
||||
@param scene La scene sur laquelle figure ce cercle
|
||||
*/
|
||||
PartCircle::PartCircle(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart(editor) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new CircleEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartCircle::~PartCircle() {
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le cercle
|
||||
@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 PartCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
painter -> drawEllipse(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 cercle en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant le cercle
|
||||
*/
|
||||
const QDomElement PartCircle::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("circle");
|
||||
QPointF top_left(sceneTopLeft());
|
||||
xml_element.setAttribute("x", top_left.x());
|
||||
xml_element.setAttribute("y", top_left.y());
|
||||
xml_element.setAttribute("diameter", rect().width());
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'un cercle depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartCircle::fromXml(const QDomElement &qde) {
|
||||
stylesFromXml(qde);
|
||||
qreal diameter = qde.attribute("diameter", "0").toDouble();
|
||||
setRect(
|
||||
QRectF(
|
||||
mapFromScene(
|
||||
qde.attribute("x", "0").toDouble(),
|
||||
qde.attribute("y", "0").toDouble()
|
||||
),
|
||||
QSizeF(
|
||||
diameter,
|
||||
diameter
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee du cercle
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse du centre du cercle
|
||||
* y : ordonnee du centre du cercle
|
||||
* diameter : diametre du cercle
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartCircle::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.center());
|
||||
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.center());
|
||||
setRect(current_rect.translated(0.0, value.toDouble() - current_pos.y()));
|
||||
} else if (property == "diameter") {
|
||||
QRectF current_rect = rect();
|
||||
qreal new_diameter = qAbs(value.toDouble());
|
||||
current_rect.translate(
|
||||
(new_diameter - current_rect.width()) / -2.0,
|
||||
(new_diameter - current_rect.height()) / -2.0
|
||||
);
|
||||
current_rect.setSize(QSizeF(new_diameter, new_diameter));
|
||||
setRect(current_rect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete de style donnee.
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse du centre du cercle
|
||||
* y : ordonnee du centre du cercle
|
||||
* diameter : diametre du cercle
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartCircle::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().center()).x());
|
||||
} else if (property == "y") {
|
||||
return(mapToScene(rect().center()).y());
|
||||
} else if (property == "diameter") {
|
||||
return(rect().width());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartCircle::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsEllipseItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le coin superieur gauche du rectangle dans lequel s'inscrit
|
||||
le cercle, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartCircle::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le centre du cercle, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartCircle::sceneCenter() const {
|
||||
return(mapToScene(rect().center()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartCircle::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsEllipseItem::boundingRect());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un cercle est pertinent des lors que son rayon n'est pas nul
|
||||
*/
|
||||
bool PartCircle::isUseless() const {
|
||||
return(rect().isNull());
|
||||
}
|
||||
62
sources/editor/partcircle.h
Normal file
62
sources/editor/partcircle.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_CIRCLE_H
|
||||
#define PART_CIRCLE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class CircleEditor;
|
||||
/**
|
||||
Cette classe represente un cercle pouvant etre utilise pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartCircle : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartCircle(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartCircle();
|
||||
|
||||
private:
|
||||
PartCircle(const PartCircle &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
CircleEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1102 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartCircle 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("cercle")); }
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
virtual QRectF boundingRect() const;
|
||||
QPointF sceneCenter() const;
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
#endif
|
||||
199
sources/editor/partellipse.cpp
Normal file
199
sources/editor/partellipse.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partellipse.h"
|
||||
#include "ellipseeditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de cette ellipse
|
||||
@param scene La scene sur laquelle figure cette ellipse
|
||||
*/
|
||||
PartEllipse::PartEllipse(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart(editor) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new EllipseEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartEllipse::~PartEllipse() {
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine l'ellipse
|
||||
@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 PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
painter -> drawEllipse(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 l'ellipse en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant l'ellipse
|
||||
*/
|
||||
const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("ellipse");
|
||||
QPointF top_left(sceneTopLeft());
|
||||
xml_element.setAttribute("x", top_left.x());
|
||||
xml_element.setAttribute("y", top_left.y());
|
||||
xml_element.setAttribute("width", rect().width());
|
||||
xml_element.setAttribute("height", rect().height());
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'une ellipse depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartEllipse::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 de l'ellipse
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse du centre de l'ellipse
|
||||
* y : ordonnee du centre de l'ellipse
|
||||
* diameter_h : diametre horizontal de l'ellipse
|
||||
* diameter_v : diametre vertical de l'ellipse
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartEllipse::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.center());
|
||||
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.center());
|
||||
setRect(current_rect.translated(0.0, value.toDouble() - current_pos.y()));
|
||||
} else if (property == "diameter_h") {
|
||||
qreal new_width = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.translate((new_width - current_rect.width()) / -2.0, 0.0);
|
||||
current_rect.setWidth(new_width);
|
||||
setRect(current_rect);
|
||||
} else if (property == "diameter_v") {
|
||||
qreal new_height = qAbs(value.toDouble());
|
||||
QRectF current_rect = rect();
|
||||
current_rect.translate(0.0, (new_height - current_rect.height()) / -2.0);
|
||||
current_rect.setHeight(new_height);
|
||||
setRect(current_rect);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee de l'ellipse
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse du centre de l'ellipse
|
||||
* y : ordonnee du centre de l'ellipse
|
||||
* diameter_h : diametre horizontal de l'ellipse
|
||||
* diameter_v : diametre vertical de l'ellipse
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartEllipse::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().center()).x());
|
||||
} else if (property == "y") {
|
||||
return(mapToScene(rect().center()).y());
|
||||
} else if (property == "diameter_h") {
|
||||
return(rect().width());
|
||||
} else if (property == "diameter_v") {
|
||||
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 PartEllipse::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsEllipseItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le coin superieur gauche du rectangle dans lequel s'inscrit
|
||||
l'ellipse, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartEllipse::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Une ellipse est pertinente des lors que ses dimensions ne sont pas nulles
|
||||
*/
|
||||
bool PartEllipse::isUseless() const {
|
||||
return(rect().isNull());
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartEllipse::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsEllipseItem::boundingRect().normalized());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
61
sources/editor/partellipse.h
Normal file
61
sources/editor/partellipse.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_ELLIPSE_H
|
||||
#define PART_ELLIPSE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class EllipseEditor;
|
||||
/**
|
||||
Cette classe represente une ellipse pouvant etre utilisee pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartEllipse(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartEllipse();
|
||||
|
||||
private:
|
||||
PartEllipse(const PartEllipse &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
EllipseEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1103 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartEllipse 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("ellipse")); }
|
||||
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
|
||||
253
sources/editor/partline.cpp
Normal file
253
sources/editor/partline.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partline.h"
|
||||
#include "lineeditor.h"
|
||||
#include <cmath>
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@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) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new LineEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartLine::~PartLine() {
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine la ligne
|
||||
@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 PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
painter -> setBrush(Qt::NoBrush);
|
||||
painter -> drawLine(line());
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte la ligne en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant la ligne
|
||||
*/
|
||||
const QDomElement PartLine::toXml(QDomDocument &xml_document) const {
|
||||
|
||||
QPointF p1(sceneP1());
|
||||
QPointF p2(sceneP2());
|
||||
|
||||
QDomElement xml_element = xml_document.createElement("line");
|
||||
xml_element.setAttribute("x1", p1.x());
|
||||
xml_element.setAttribute("y1", p1.y());
|
||||
xml_element.setAttribute("x2", p2.x());
|
||||
xml_element.setAttribute("y2", p2.y());
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'une ligne depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartLine::fromXml(const QDomElement &qde) {
|
||||
stylesFromXml(qde);
|
||||
setLine(
|
||||
QLineF(
|
||||
mapFromScene(
|
||||
qde.attribute("x1", "0").toDouble(),
|
||||
qde.attribute("y1", "0").toDouble()
|
||||
),
|
||||
mapFromScene(
|
||||
qde.attribute("x2", "0").toDouble(),
|
||||
qde.attribute("y2", "0").toDouble()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee de la ligne
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x1 : abscisse du premier point
|
||||
* y1 : ordonnee du second point
|
||||
* x2 : abscisse du premier point
|
||||
* y2 : ordonnee du second point
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartLine::setProperty(const QString &property, const QVariant &value) {
|
||||
CustomElementGraphicPart::setProperty(property, value);
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
QPointF new_p1(sceneP1()), new_p2(sceneP2());
|
||||
bool setline = true;
|
||||
if (property == "x1") {
|
||||
new_p1.setX(value.toDouble());
|
||||
} else if (property == "y1") {
|
||||
new_p1.setY(value.toDouble());
|
||||
} else if (property == "x2") {
|
||||
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)));
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee de la ligne
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x1 : abscisse du premier point
|
||||
* y1 : ordonnee du second point
|
||||
* x2 : abscisse du premier point
|
||||
* y2 : ordonnee du second point
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartLine::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 == "x1") {
|
||||
return(sceneP1().x());
|
||||
} else if (property == "y1") {
|
||||
return(sceneP1().y());
|
||||
} else if (property == "x2") {
|
||||
return(sceneP2().x());
|
||||
} else if (property == "y2") {
|
||||
return(sceneP2().y());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartLine::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsLineItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le premier point, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartLine::sceneP1() const {
|
||||
return(mapToScene(line().p1()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le second point, dans les coordonnees de la scene.
|
||||
*/
|
||||
QPointF PartLine::sceneP2() const {
|
||||
return(mapToScene(line().p2()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return la forme selectionnable de la ligne
|
||||
*/
|
||||
QPainterPath PartLine::shape() const {
|
||||
QList<QPointF> points = fourShapePoints();
|
||||
QPainterPath t;
|
||||
t.setFillRule(Qt::WindingFill);
|
||||
t.moveTo(points.at(0));
|
||||
t.lineTo(points.at(1));
|
||||
t.lineTo(points.at(2));
|
||||
t.lineTo(points.at(3));
|
||||
t.lineTo(points.at(0));
|
||||
return(t);
|
||||
}
|
||||
|
||||
/**
|
||||
@return une liste contenant les deux points de la droite + les 4 points entourant ces deux points
|
||||
*/
|
||||
QList<QPointF> PartLine::fourShapePoints() const {
|
||||
const qreal marge = 2.0;
|
||||
// on a donc A(xa , ya) et B(xb, yb)
|
||||
QPointF a = line().p1();
|
||||
QPointF b = line().p2();
|
||||
|
||||
QList<QPointF> result;
|
||||
|
||||
// cas particulier : la droite se ramene a un point
|
||||
if (a == b) {
|
||||
result << QPointF(a.x() - marge, a.y() - marge);
|
||||
result << QPointF(a.x() - marge, a.y() + marge);
|
||||
result << QPointF(a.x() + marge, a.y() + marge);
|
||||
result << QPointF(a.x() + marge, a.y() - marge);
|
||||
} else {
|
||||
|
||||
// on calcule le vecteur AB : (xb-xa, yb-ya)
|
||||
QPointF v_ab = b - a;
|
||||
|
||||
// et la distance AB : racine des coordonnees du vecteur au carre
|
||||
qreal ab = sqrt(pow(v_ab.x(), 2) + pow(v_ab.y(), 2));
|
||||
|
||||
// ensuite on definit le vecteur u(a, b) qui est egal au vecteur AB divise
|
||||
// par sa longueur et multiplie par la longueur de la marge que tu veux
|
||||
// laisser
|
||||
QPointF u = v_ab / ab * marge;
|
||||
|
||||
// on definit le vecteur v(-b , a) qui est perpendiculaire a AB
|
||||
QPointF v(-u.y(), u.x());
|
||||
QPointF m = -u + v; // on a le vecteur M = -u + v
|
||||
QPointF n = -u - v; // et le vecteur N=-u-v
|
||||
QPointF h = a + m; // H = A + M
|
||||
QPointF k = a + n; // K = A + N
|
||||
QPointF i = b - n; // I = B - N
|
||||
QPointF j = b - m; // J = B - M
|
||||
|
||||
result << h << i << j << k;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartLine::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsLineItem::boundingRect());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Une ligne est pertinente des lors que ses deux points sont differents
|
||||
*/
|
||||
bool PartLine::isUseless() const {
|
||||
return(sceneP1() == sceneP2());
|
||||
}
|
||||
66
sources/editor/partline.h
Normal file
66
sources/editor/partline.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_LINE_H
|
||||
#define PART_LINE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class LineEditor;
|
||||
/**
|
||||
Cette classe represente une ligne pouvant etre utilisee pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartLine(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartLine();
|
||||
|
||||
private:
|
||||
PartLine(const PartLine &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
LineEditor *informations;
|
||||
|
||||
// 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 const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneP1() const;
|
||||
virtual QPointF sceneP2() const;
|
||||
virtual QPainterPath shape() 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 &);
|
||||
|
||||
private:
|
||||
QList<QPointF> fourShapePoints() const;
|
||||
};
|
||||
#endif
|
||||
175
sources/editor/partpolygon.cpp
Normal file
175
sources/editor/partpolygon.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partpolygon.h"
|
||||
#include "qet.h"
|
||||
#include "polygoneditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de ce polygone
|
||||
@param scene La scene sur laquelle figure ce polygone
|
||||
*/
|
||||
PartPolygon::PartPolygon(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsPolygonItem(parent, scene),
|
||||
CustomElementGraphicPart(editor),
|
||||
closed(false)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new PolygonEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
style_editor -> appendWidget(informations);
|
||||
style_editor -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartPolygon::~PartPolygon() {
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'un polygone depuis un element XML
|
||||
@param qde Element XML a lire
|
||||
*/
|
||||
void PartPolygon::fromXml(const QDomElement &qde) {
|
||||
stylesFromXml(qde);
|
||||
int i = 1;
|
||||
while(true) {
|
||||
if (
|
||||
QET::attributeIsAReal(qde, QString("x%1").arg(i)) &&\
|
||||
QET::attributeIsAReal(qde, QString("y%1").arg(i))
|
||||
) ++ i;
|
||||
else break;
|
||||
}
|
||||
|
||||
QPolygonF temp_polygon;
|
||||
for (int j = 1 ; j < i ; ++ j) {
|
||||
temp_polygon << QPointF(
|
||||
qde.attribute(QString("x%1").arg(j)).toDouble(),
|
||||
qde.attribute(QString("y%1").arg(j)).toDouble()
|
||||
);
|
||||
}
|
||||
setPolygon(temp_polygon);
|
||||
|
||||
closed = qde.attribute("closed") != "false";
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le polygone en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant le polygone
|
||||
*/
|
||||
const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("polygon");
|
||||
int i = 1;
|
||||
foreach(QPointF point, polygon()) {
|
||||
point = mapToScene(point);
|
||||
xml_element.setAttribute(QString("x%1").arg(i), point.x());
|
||||
xml_element.setAttribute(QString("y%1").arg(i), point.y());
|
||||
++ i;
|
||||
}
|
||||
if (!closed) xml_element.setAttribute("closed", "false");
|
||||
stylesToXml(xml_element);
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine le polygone
|
||||
@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 PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
if (closed) painter -> drawPolygon(polygon());
|
||||
else painter -> drawPolyline(polygon());
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee du polygone
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* closed : true pour fermer le polygone, false sinon
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartPolygon::setProperty(const QString &property, const QVariant &value) {
|
||||
CustomElementGraphicPart::setProperty(property, value);
|
||||
if (property == "closed") closed = value.toBool();
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee de la ligne
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* closed : true pour fermer le polygone, false sinon
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartPolygon::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 == "closed") return(closed);
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartPolygon::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsPolygonItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un polygone est pertinent des lors qu'il possede deux points differents.
|
||||
*/
|
||||
bool PartPolygon::isUseless() const {
|
||||
QPolygonF poly(polygon());
|
||||
|
||||
if (polygon().count() < 2) return(true);
|
||||
|
||||
QPointF previous_point;
|
||||
for (int i = 1 ; i < poly.count() ; ++ i) {
|
||||
if (poly[i] != poly[i-1]) return(false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartPolygon::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsPolygonItem::boundingRect());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
92
sources/editor/partpolygon.h
Normal file
92
sources/editor/partpolygon.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_POLYGON_H
|
||||
#define PART_POLYGON_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class PolygonEditor;
|
||||
/**
|
||||
Cette classe represente un polygone pouvant etre utilise pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartPolygon(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartPolygon();
|
||||
|
||||
private:
|
||||
PartPolygon(const PartPolygon &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
bool closed;
|
||||
PolygonEditor *informations;
|
||||
|
||||
/**
|
||||
constructeur
|
||||
paint()
|
||||
widget bidon pour l'edition
|
||||
methode pour poser le polygone :
|
||||
-mousePressEvent = pose un nouveau point
|
||||
-mouseMoveEvent = deplace ce point
|
||||
-mouveReleaseEvent = finalise ce point
|
||||
utiliser QPolygonF ; memoriser le point en cours (tout comme le
|
||||
partploygon en cours) et ne l'ajouter au qpolygonf que lors du
|
||||
mouseReleaseEvent
|
||||
*/
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1105 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartPolygon avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("polygone")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
virtual QRectF boundingRect() const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
void setClosed(bool c);
|
||||
bool isClosed() const;
|
||||
void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
|
||||
/**
|
||||
Specifie si le polygone doit etre ferme
|
||||
@param c true pour un polygone ferme, false sinon
|
||||
*/
|
||||
inline void PartPolygon::setClosed(bool c) {
|
||||
closed = c;
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si le polygone est ferme
|
||||
@return true si le polygone est ferme, false sinon
|
||||
*/
|
||||
inline bool PartPolygon::isClosed() const {
|
||||
return(closed);
|
||||
}
|
||||
|
||||
#endif
|
||||
228
sources/editor/partterminal.cpp
Normal file
228
sources/editor/partterminal.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "partterminal.h"
|
||||
#include "terminal.h"
|
||||
#include "terminaleditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de cette borne
|
||||
@param scene La scene sur laquelle figure cette borne
|
||||
*/
|
||||
PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
CustomElementPart(editor),
|
||||
QGraphicsItem(parent, scene),
|
||||
_orientation(QET::North)
|
||||
{
|
||||
informations = new TerminalEditor(elementEditor(), this);
|
||||
informations -> setElementTypeName(name());
|
||||
updateSecondPoint();
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setZValue(100000);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartTerminal::~PartTerminal() {
|
||||
delete informations;
|
||||
};
|
||||
|
||||
/**
|
||||
Importe les proprietes d'une borne depuis un element XML
|
||||
@param xml_elmt Element XML a lire
|
||||
*/
|
||||
void PartTerminal::fromXml(const QDomElement &xml_elmt) {
|
||||
// lit la position de la borne
|
||||
qreal term_x = 0.0, term_y = 0.0;
|
||||
QET::attributeIsAReal(xml_elmt, "x", &term_x);
|
||||
QET::attributeIsAReal(xml_elmt, "y", &term_y);
|
||||
setPos(QPointF(term_x, term_y));
|
||||
|
||||
// lit l'orientation de la borne
|
||||
_orientation = QET::orientationFromString(xml_elmt.attribute("orientation"));
|
||||
updateSecondPoint();
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte la borne en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant la borne
|
||||
*/
|
||||
const QDomElement PartTerminal::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("terminal");
|
||||
|
||||
// ecrit la position de la borne
|
||||
xml_element.setAttribute("x", QString("%1").arg(scenePos().x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg(scenePos().y()));
|
||||
|
||||
// ecrit l'orientation de la borne
|
||||
xml_element.setAttribute("orientation", orientationToString(_orientation));
|
||||
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget permettant d'editer cette borne
|
||||
*/
|
||||
QWidget *PartTerminal::elementInformations() {
|
||||
return(informations);
|
||||
}
|
||||
|
||||
/**
|
||||
Dessine la borne
|
||||
@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 PartTerminal::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
p -> save();
|
||||
|
||||
// annulation des renderhints
|
||||
p -> setRenderHint(QPainter::Antialiasing, false);
|
||||
p -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
p -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
|
||||
QPen t;
|
||||
t.setWidthF(1.0);
|
||||
|
||||
// dessin de la borne en rouge
|
||||
t.setColor(isSelected() ? Terminal::couleur_neutre : Qt::red);
|
||||
p -> setPen(t);
|
||||
p -> drawLine(QPointF(0.0, 0.0), second_point);
|
||||
|
||||
// dessin du point d'amarrage au conducteur en bleu
|
||||
t.setColor(isSelected() ? Qt::red : Terminal::couleur_neutre);
|
||||
p -> setPen(t);
|
||||
p -> setBrush(Terminal::couleur_neutre);
|
||||
p -> drawPoint(QPointF(0.0, 0.0));
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartTerminal::boundingRect() const {
|
||||
QPointF p1, p2;
|
||||
if (second_point.x() <= 0.0 && second_point.y() <= 0.0) {
|
||||
p1 = second_point;
|
||||
p2 = QPointF(0.0, 0.0);
|
||||
} else {
|
||||
p1 = QPointF(0.0, 0.0);
|
||||
p2 = second_point;
|
||||
}
|
||||
QRectF br;
|
||||
br.setTopLeft (p1 - QPointF(2.0, 2.0));
|
||||
br.setBottomRight(p2 + QPointF(2.0, 2.0));
|
||||
return(br);
|
||||
}
|
||||
|
||||
/**
|
||||
@return L'orientation de la borne
|
||||
*/
|
||||
QET::Orientation PartTerminal::orientation() const {
|
||||
return(_orientation);
|
||||
}
|
||||
|
||||
/**
|
||||
Definit l'orientation de la borne
|
||||
@param ori la nouvelle orientation de la borne
|
||||
*/
|
||||
void PartTerminal::setOrientation(QET::Orientation ori) {
|
||||
prepareGeometryChange();
|
||||
_orientation = ori;
|
||||
updateSecondPoint();
|
||||
informations -> updateForm();
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee de la borne
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse de la borne
|
||||
* y : ordonnee de la borne
|
||||
* orientation : orientation de la borne
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartTerminal::setProperty(const QString &property, const QVariant &value) {
|
||||
if (property == "x") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(value.toDouble(), pos().y());
|
||||
} else if (property == "y") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(pos().x(), value.toDouble());
|
||||
} else if (property == "orientation") {
|
||||
if (!value.canConvert(QVariant::Int)) return;
|
||||
setOrientation(static_cast<QET::Orientation>(value.toInt()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee de la borne
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse de la borne
|
||||
* y : ordonnee de la borne
|
||||
* orientation : orientation de la borne
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartTerminal::property(const QString &property) {
|
||||
if (property == "x") {
|
||||
return(scenePos().x());
|
||||
} else if (property == "y") {
|
||||
return(scenePos().y());
|
||||
} else if (property == "orientation") {
|
||||
return(_orientation);
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartTerminal::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la position du second point en fonction de la position et de
|
||||
l'orientation de la borne.
|
||||
*/
|
||||
void PartTerminal::updateSecondPoint() {
|
||||
qreal ts = 4.0; // terminal size
|
||||
switch(_orientation) {
|
||||
case QET::North: second_point = QPointF(0.0, ts); break;
|
||||
case QET::East : second_point = QPointF(-ts, 0.0); break;
|
||||
case QET::South: second_point = QPointF(0.0, -ts); break;
|
||||
case QET::West : second_point = QPointF(ts, 0.0); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Une borne est toujours pertinente ; cette fonction renvoie donc
|
||||
toujours false
|
||||
*/
|
||||
bool PartTerminal::isUseless() const {
|
||||
return(false);
|
||||
}
|
||||
69
sources/editor/partterminal.h
Normal file
69
sources/editor/partterminal.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_TERMINAL_H
|
||||
#define PART_TERMINAL_H
|
||||
#include "customelementpart.h"
|
||||
#include "qet.h"
|
||||
#include <QtGui>
|
||||
class TerminalEditor;
|
||||
class QETElementEditor;
|
||||
/**
|
||||
Cette classe represente une borne pouvant etre utilisee pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartTerminal : public CustomElementPart, public QGraphicsItem {
|
||||
public:
|
||||
// constructeurs, destructeur
|
||||
PartTerminal(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartTerminal();
|
||||
private:
|
||||
PartTerminal(const PartTerminal &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QET::Orientation _orientation;
|
||||
QPointF second_point;
|
||||
TerminalEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1106 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartTerminal avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("borne")); }
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual QWidget *elementInformations();
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
virtual QRectF boundingRect() const;
|
||||
QET::Orientation orientation() const;
|
||||
void setOrientation(QET::Orientation);
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
|
||||
private:
|
||||
void updateSecondPoint();
|
||||
};
|
||||
#endif
|
||||
233
sources/editor/parttext.cpp
Normal file
233
sources/editor/parttext.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "parttext.h"
|
||||
#include "texteditor.h"
|
||||
#include "editorcommands.h"
|
||||
#include "elementscene.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de ce texte statique
|
||||
@param scene La scene sur laquelle figure ce texte statique
|
||||
*/
|
||||
PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent, ElementScene *scene) :
|
||||
QGraphicsTextItem(parent, scene),
|
||||
CustomElementPart(editor)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setPlainText(QObject::tr("T"));
|
||||
infos = new TextEditor(elementEditor(), this);
|
||||
infos -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
|
||||
/// Destructeur
|
||||
PartText::~PartText() {
|
||||
delete infos;
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'un texte statique depuis un element XML
|
||||
@param xml_element Element XML a lire
|
||||
*/
|
||||
void PartText::fromXml(const QDomElement &xml_element) {
|
||||
bool ok;
|
||||
int font_size = xml_element.attribute("size").toInt(&ok);
|
||||
if (!ok || font_size < 1) font_size = 20;
|
||||
|
||||
setFont(QFont(QString(QETApp::diagramTextsFont()), font_size));
|
||||
setPlainText(xml_element.attribute("text"));
|
||||
setPos(
|
||||
xml_element.attribute("x").toDouble(),
|
||||
xml_element.attribute("y").toDouble()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le texte statique en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant le texte statique
|
||||
*/
|
||||
const QDomElement PartText::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("text");
|
||||
xml_element.setAttribute("x", QString("%1").arg((scenePos() + margin()).x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg((scenePos() + margin()).y()));
|
||||
xml_element.setAttribute("text", toPlainText());
|
||||
xml_element.setAttribute("size", font().pointSize());
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget permettant d'editer ce texte statique
|
||||
*/
|
||||
QWidget *PartText::elementInformations() {
|
||||
return(infos);
|
||||
}
|
||||
|
||||
/**
|
||||
Retourne la position du texte, l'origine etant le point en bas a gauche du
|
||||
texte (et pas du cadre)
|
||||
@return la position du texte
|
||||
*/
|
||||
QPointF PartText::pos() const {
|
||||
return(QGraphicsTextItem::pos() + margin());
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la position du texte statique
|
||||
@param left_corner_pos Nouvelle position
|
||||
*/
|
||||
void PartText::setPos(const QPointF &left_corner_pos) {
|
||||
QGraphicsTextItem::setPos(left_corner_pos - margin());
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la position du texte statique
|
||||
@param x abscisse de la nouvelle position
|
||||
@param y ordonnee de la nouvelle position
|
||||
*/
|
||||
void PartText::setPos(qreal x, qreal y) {
|
||||
QGraphicsTextItem::setPos(QPointF(x, y) - margin());
|
||||
}
|
||||
|
||||
/**
|
||||
@return Les coordonnees du point situe en bas a gauche du texte.
|
||||
*/
|
||||
QPointF PartText::margin() const {
|
||||
QFont used_font = font();
|
||||
QFontMetrics qfm(used_font);
|
||||
QPointF margin(
|
||||
(boundingRect().width () - qfm.width(toPlainText())) / 2.0,
|
||||
((boundingRect().height() - used_font.pointSizeF()) / 3.0) + used_font.pointSizeF()
|
||||
);
|
||||
return(margin);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet a l'element texte de redevenir deplacable a la fin de l'edition de texte
|
||||
@param e Le QFocusEvent decrivant la perte de focus
|
||||
*/
|
||||
void PartText::focusOutEvent(QFocusEvent *e) {
|
||||
QGraphicsTextItem::focusOutEvent(e);
|
||||
if (previous_text != toPlainText()) {
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
TextEditor::tr("texte") + " " + name(),
|
||||
this,
|
||||
"text",
|
||||
previous_text,
|
||||
toPlainText()
|
||||
)
|
||||
);
|
||||
previous_text = toPlainText();
|
||||
}
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet a l'element texte de devenir editable lorsqu'on double-clique dessus
|
||||
@param e Le QGraphicsSceneMouseEvent qui decrit le double-clic
|
||||
*/
|
||||
void PartText::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
previous_text = toPlainText();
|
||||
QGraphicsTextItem::mouseDoubleClickEvent(e);
|
||||
setFocus(Qt::MouseFocusReason);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee du texte statique
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse de la position
|
||||
* y : ordonnee de la position
|
||||
* size : taille du texte
|
||||
* text : texte
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartText::setProperty(const QString &property, const QVariant &value) {
|
||||
if (property == "x") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(value.toDouble(), pos().y());
|
||||
} else if (property == "y") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(pos().x(), value.toDouble());
|
||||
} else if (property == "size") {
|
||||
if (!value.canConvert(QVariant::Int)) return;
|
||||
setFont(QFont(font().family(), value.toInt()));
|
||||
} else if (property == "text") {
|
||||
setPlainText(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee du texte statique
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse de la position
|
||||
* y : ordonnee de la position
|
||||
* size : taille du texte
|
||||
* text : texte
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartText::property(const QString &property) {
|
||||
if (property == "x") {
|
||||
return((scenePos() + margin()).x());
|
||||
} else if (property == "y") {
|
||||
return((scenePos() + margin()).y());
|
||||
} else if (property == "size") {
|
||||
return(font().pointSize());
|
||||
} else if (property == "text") {
|
||||
return(toPlainText());
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartText::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
infos -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsTextItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartText::boundingRect() const {
|
||||
QRectF r = QGraphicsTextItem::boundingRect();
|
||||
r.adjust(0.0, -2.0, 0.0, 0.0);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un texte statique n'est pas pertinent lorsque son texte est vide.
|
||||
*/
|
||||
bool PartText::isUseless() const {
|
||||
return(toPlainText().isEmpty());
|
||||
}
|
||||
68
sources/editor/parttext.h
Normal file
68
sources/editor/parttext.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_TEXT_H
|
||||
#define PART_TEXT_H
|
||||
#include <QtGui>
|
||||
#include "customelementpart.h"
|
||||
class TextEditor;
|
||||
/**
|
||||
Cette classe represente un texte pouvant etre utilise pour composer le
|
||||
dessin d'un element dans l'editeur d'element.
|
||||
*/
|
||||
class PartText : public QGraphicsTextItem, public CustomElementPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartText(QETElementEditor *, QGraphicsItem * = 0, ElementScene * = 0);
|
||||
virtual ~PartText();
|
||||
|
||||
private:
|
||||
PartText(const PartText &);
|
||||
|
||||
// attributs
|
||||
TextEditor *infos;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1107 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartText avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("texte")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
QWidget *elementInformations();
|
||||
QPointF pos() const;
|
||||
void setPos(const QPointF &);
|
||||
void setPos(qreal, qreal);
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
virtual void focusOutEvent(QFocusEvent *);
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
QRectF boundingRect() const;
|
||||
|
||||
private:
|
||||
QPointF margin() const;
|
||||
QString previous_text;
|
||||
};
|
||||
#endif
|
||||
258
sources/editor/parttextfield.cpp
Normal file
258
sources/editor/parttextfield.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "parttextfield.h"
|
||||
#include "textfieldeditor.h"
|
||||
#include "editorcommands.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param parent Le QGraphicsItem parent de ce champ de texte
|
||||
@param scene La scene sur laquelle figure ce champ de texte
|
||||
*/
|
||||
PartTextField::PartTextField(QETElementEditor *editor, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsTextItem(parent, scene),
|
||||
CustomElementPart(editor),
|
||||
follow_parent_rotations(true)
|
||||
{
|
||||
setDefaultTextColor(Qt::black);
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setPlainText(QObject::tr("_"));
|
||||
infos = new TextFieldEditor(elementEditor(), this);
|
||||
infos -> setElementTypeName(name());
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PartTextField::~PartTextField() {
|
||||
delete infos;
|
||||
}
|
||||
|
||||
/**
|
||||
Importe les proprietes d'un champ de texte depuis un element XML
|
||||
@param xml_element Element XML a lire
|
||||
*/
|
||||
void PartTextField::fromXml(const QDomElement &xml_element) {
|
||||
bool ok;
|
||||
int font_size = xml_element.attribute("size").toInt(&ok);
|
||||
if (!ok || font_size < 1) font_size = 20;
|
||||
|
||||
setFont(QFont(QString(QETApp::diagramTextsFont()), font_size));
|
||||
setPlainText(xml_element.attribute("text"));
|
||||
setPos(
|
||||
xml_element.attribute("x").toDouble(),
|
||||
xml_element.attribute("y").toDouble()
|
||||
);
|
||||
|
||||
follow_parent_rotations = (xml_element.attribute("rotate") == "true");
|
||||
}
|
||||
|
||||
/**
|
||||
Exporte le champ de texte en XML
|
||||
@param xml_document Document XML a utiliser pour creer l'element XML
|
||||
@return un element XML decrivant le champ de texte
|
||||
*/
|
||||
const QDomElement PartTextField::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("input");
|
||||
xml_element.setAttribute("x", QString("%1").arg((scenePos() + margin()).x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg((scenePos() + margin()).y()));
|
||||
xml_element.setAttribute("text", toPlainText());
|
||||
xml_element.setAttribute("size", font().pointSize());
|
||||
if (follow_parent_rotations) xml_element.setAttribute("rotate", "true");
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le widget permettant d'editer ce champ de texte
|
||||
*/
|
||||
QWidget *PartTextField::elementInformations() {
|
||||
return(infos);
|
||||
}
|
||||
|
||||
/**
|
||||
Retourne la position du texte, l'origine etant le point en bas a gauche du
|
||||
texte (et pas du cadre)
|
||||
@return la position du texte
|
||||
*/
|
||||
QPointF PartTextField::pos() const {
|
||||
return(QGraphicsTextItem::pos() + margin());
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la position du champ de texte
|
||||
@param left_corner_pos Nouvelle position
|
||||
*/
|
||||
void PartTextField::setPos(const QPointF &left_corner_pos) {
|
||||
QGraphicsTextItem::setPos(left_corner_pos - margin());
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la position du champ de texte
|
||||
@param x abscisse de la nouvelle position
|
||||
@param y ordonnee de la nouvelle position
|
||||
*/
|
||||
void PartTextField::setPos(qreal x, qreal y) {
|
||||
QGraphicsTextItem::setPos(QPointF(x, y) - margin());
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si le champ de texte suit les rotation de l'element, false
|
||||
sinon
|
||||
*/
|
||||
bool PartTextField::followParentRotations() {
|
||||
return(follow_parent_rotations);
|
||||
}
|
||||
|
||||
/**
|
||||
@param fpr true pour que le champ de texte suive les rotation de
|
||||
l'element, false sinon
|
||||
*/
|
||||
void PartTextField::setFollowParentRotations(bool fpr) {
|
||||
follow_parent_rotations = fpr;
|
||||
}
|
||||
|
||||
/**
|
||||
@return Les coordonnees du point situe en bas a gauche du texte.
|
||||
*/
|
||||
QPointF PartTextField::margin() const {
|
||||
QFont used_font = font();
|
||||
QFontMetrics qfm(used_font);
|
||||
QPointF margin(
|
||||
(boundingRect().width () - qfm.width(toPlainText())) / 2.0,
|
||||
((boundingRect().height() - used_font.pointSizeF()) / 3.0) + used_font.pointSizeF()
|
||||
);
|
||||
return(margin);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet a l'element texte de redevenir deplacable a la fin de l'edition de texte
|
||||
@param e Le QFocusEvent decrivant la perte de focus
|
||||
*/
|
||||
void PartTextField::focusOutEvent(QFocusEvent *e) {
|
||||
QGraphicsTextItem::focusOutEvent(e);
|
||||
if (previous_text != toPlainText()) {
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
TextFieldEditor::tr("texte") + " " + name(),
|
||||
this,
|
||||
"text",
|
||||
previous_text,
|
||||
toPlainText()
|
||||
)
|
||||
);
|
||||
previous_text = toPlainText();
|
||||
}
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet a l'element texte de devenir editable lorsqu'on double-clique dessus
|
||||
@param e Le QGraphicsSceneMouseEvent qui decrit le double-clic
|
||||
*/
|
||||
void PartTextField::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *e) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
previous_text = toPlainText();
|
||||
QGraphicsTextItem::mouseDoubleClickEvent(e);
|
||||
setFocus(Qt::MouseFocusReason);
|
||||
}
|
||||
|
||||
/**
|
||||
Specifie la valeur d'une propriete donnee du champ de texte
|
||||
@param property propriete a modifier. Valeurs acceptees :
|
||||
* x : abscisse de la position
|
||||
* y : ordonnee de la position
|
||||
* size : taille du texte
|
||||
* text : texte
|
||||
* rotate : suivi de la rotation de l'element parent
|
||||
@param value Valeur a attribuer a la propriete
|
||||
*/
|
||||
void PartTextField::setProperty(const QString &property, const QVariant &value) {
|
||||
if (property == "x") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(value.toDouble(), pos().y());
|
||||
} else if (property == "y") {
|
||||
if (!value.canConvert(QVariant::Double)) return;
|
||||
setPos(pos().x(), value.toDouble());
|
||||
} else if (property == "size") {
|
||||
if (!value.canConvert(QVariant::Int)) return;
|
||||
setFont(QFont(font().family(), value.toInt()));
|
||||
} else if (property == "text") {
|
||||
setPlainText(value.toString());
|
||||
} else if (property == "rotate") {
|
||||
follow_parent_rotations = value.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'acceder a la valeur d'une propriete donnee du champ de texte
|
||||
@param property propriete lue. Valeurs acceptees :
|
||||
* x : abscisse de la position
|
||||
* y : ordonnee de la position
|
||||
* size : taille du texte
|
||||
* text : texte
|
||||
* rotate : suivi de la rotation de l'element parent
|
||||
@return La valeur de la propriete property
|
||||
*/
|
||||
QVariant PartTextField::property(const QString &property) {
|
||||
if (property == "x") {
|
||||
return((scenePos() + margin()).x());
|
||||
} else if (property == "y") {
|
||||
return((scenePos() + margin()).y());
|
||||
} else if (property == "size") {
|
||||
return(font().pointSize());
|
||||
} else if (property == "text") {
|
||||
return(toPlainText());
|
||||
} else if (property == "rotate") {
|
||||
return(follow_parent_rotations);
|
||||
}
|
||||
return(QVariant());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les changements intervenant sur cette partie
|
||||
@param change Type de changement
|
||||
@param value Valeur numerique relative au changement
|
||||
*/
|
||||
QVariant PartTextField::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
infos -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsTextItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@return le rectangle delimitant cette partie.
|
||||
*/
|
||||
QRectF PartTextField::boundingRect() const {
|
||||
QRectF r = QGraphicsTextItem::boundingRect();
|
||||
r.adjust(0.0, -2.0, 0.0, 0.0);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si cette partie n'est pas pertinente et ne merite pas d'etre
|
||||
conservee / enregistree.
|
||||
Un champ de texte est toujours pertinent ; cette fonction renvoie donc
|
||||
toujours false
|
||||
*/
|
||||
bool PartTextField::isUseless() const {
|
||||
return(false);
|
||||
}
|
||||
74
sources/editor/parttextfield.h
Normal file
74
sources/editor/parttextfield.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2006-2007 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_TEXTFIELD_H
|
||||
#define PART_TEXTFIELD_H
|
||||
#include <QtGui>
|
||||
#include "customelementpart.h"
|
||||
class TextFieldEditor;
|
||||
class QETElementEditor;
|
||||
/**
|
||||
Cette classe represente un champ de texte editable pouvant etre utilise
|
||||
pour composer le dessin d'un element dans l'editeur d'element.
|
||||
L'utilisateur peut specifier un valeur par defaut. Le champ sera editable
|
||||
lorsque l'element sera pose sur un schema.
|
||||
*/
|
||||
class PartTextField : public QGraphicsTextItem, public CustomElementPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartTextField(QETElementEditor *, QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartTextField();
|
||||
|
||||
private:
|
||||
PartTextField(const PartTextField &);
|
||||
|
||||
// attributs
|
||||
TextFieldEditor *infos;
|
||||
bool follow_parent_rotations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
enum { Type = UserType + 1108 };
|
||||
/**
|
||||
permet de caster un QGraphicsItem en PartTextField avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
virtual QString name() const { return(QObject::tr("champ de texte")); }
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
QWidget *elementInformations();
|
||||
QPointF pos() const;
|
||||
void setPos(const QPointF &);
|
||||
void setPos(qreal, qreal);
|
||||
bool followParentRotations();
|
||||
void setFollowParentRotations(bool);
|
||||
virtual void setProperty(const QString &, const QVariant &);
|
||||
virtual QVariant property(const QString &);
|
||||
virtual bool isUseless() const;
|
||||
|
||||
protected:
|
||||
virtual void focusOutEvent(QFocusEvent *);
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
QRectF boundingRect() const;
|
||||
|
||||
private:
|
||||
QPointF margin() const;
|
||||
QString previous_text;
|
||||
};
|
||||
#endif
|
||||
155
sources/editor/polygoneditor.cpp
Normal file
155
sources/editor/polygoneditor.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "polygoneditor.h"
|
||||
#include "partpolygon.h"
|
||||
#include "elementscene.h"
|
||||
#include "editorcommands.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param p Le polygone a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
PolygonEditor::PolygonEditor(QETElementEditor *editor, PartPolygon *p, QWidget *parent) :
|
||||
ElementItemEditor(editor, parent),
|
||||
points_list(this),
|
||||
close_polygon(tr("Polygone ferm\351"), this)
|
||||
{
|
||||
part = p;
|
||||
// prepare la liste de points
|
||||
points_list.setColumnCount(2);
|
||||
QStringList headers;
|
||||
headers << tr("x") << tr("y");
|
||||
points_list.setHeaderLabels(headers);
|
||||
points_list.setRootIsDecorated(false);
|
||||
updateForm();
|
||||
|
||||
// layout
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout -> addWidget(new QLabel(tr("Points du polygone :")));
|
||||
layout -> addWidget(&points_list);
|
||||
layout -> addWidget(&close_polygon);
|
||||
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
PolygonEditor::~PolygonEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le polygone a partir des donnees du formulaire : points et etat ferme ou non
|
||||
*/
|
||||
void PolygonEditor::updatePolygon() {
|
||||
updatePolygonPoints();
|
||||
updatePolygonClosedState();
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour les points du polygone et cree un objet d'annulation
|
||||
*/
|
||||
void PolygonEditor::updatePolygonPoints() {
|
||||
QVector<QPointF> points = getPointsFromTree();
|
||||
if (points.count() < 2) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Erreur"),
|
||||
tr("Le polygone doit comporter au moins deux points.")
|
||||
);
|
||||
return;
|
||||
}
|
||||
undoStack().push(new ChangePolygonPointsCommand(part, part -> polygon(), points));
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour l'etat ferme ou non du polygone
|
||||
*/
|
||||
void PolygonEditor::updatePolygonClosedState() {
|
||||
undoStack().push(
|
||||
new ChangePartCommand(
|
||||
tr("fermeture du polygone"),
|
||||
part,
|
||||
"closed",
|
||||
QVariant(!close_polygon.isChecked()),
|
||||
QVariant(close_polygon.isChecked())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void PolygonEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
while(points_list.takeTopLevelItem(0)) {}
|
||||
foreach(QPointF point, part -> polygon()) {
|
||||
point = part -> mapToScene(point);
|
||||
QStringList qsl;
|
||||
qsl << QString("%1").arg(point.x()) << QString("%1").arg(point.y());
|
||||
QTreeWidgetItem *qtwi = new QTreeWidgetItem(qsl);
|
||||
qtwi -> setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
|
||||
points_list.addTopLevelItem(qtwi);
|
||||
}
|
||||
close_polygon.setChecked(part -> isClosed());
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Un vecteur contenant les points composant le polygone a partir du
|
||||
formulaire d'edition
|
||||
*/
|
||||
QVector<QPointF> PolygonEditor::getPointsFromTree() {
|
||||
QVector<QPointF> points;
|
||||
for(int i = 0 ; i < points_list.topLevelItemCount() ; ++ i) {
|
||||
QTreeWidgetItem *qtwi = points_list.topLevelItem(i);
|
||||
bool x_convert_ok, y_convert_ok;
|
||||
qreal x = qtwi -> text(0).toDouble(&x_convert_ok);
|
||||
qreal y = qtwi -> text(1).toDouble(&y_convert_ok);
|
||||
if (!x_convert_ok || !y_convert_ok) continue;
|
||||
points << part -> mapFromScene(QPointF(x, y));
|
||||
}
|
||||
return(points);
|
||||
}
|
||||
|
||||
/**
|
||||
@param qtwi QTreeWidgetItem a valider
|
||||
@param column Colonne exacte du QTreeWidgetItem a valider
|
||||
*/
|
||||
void PolygonEditor::validColumn(QTreeWidgetItem *qtwi, int column) {
|
||||
bool convert_ok;
|
||||
qtwi -> text(column).toDouble(&convert_ok);
|
||||
if (convert_ok) {
|
||||
points_list.closePersistentEditor(qtwi, column);
|
||||
updatePolygonPoints();
|
||||
} else points_list.openPersistentEditor(qtwi, column);
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive les connexionx signaux/slots entre les widgets internes.
|
||||
@param active true pour activer les connexions, false pour les desactiver
|
||||
*/
|
||||
void PolygonEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
|
||||
connect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
|
||||
} else {
|
||||
disconnect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
|
||||
disconnect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
|
||||
}
|
||||
}
|
||||
58
sources/editor/polygoneditor.h
Normal file
58
sources/editor/polygoneditor.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 POLYGON_EDITOR_H
|
||||
#define POLYGON_EDITOR_H
|
||||
#include "elementitemeditor.h"
|
||||
class PartPolygon;
|
||||
/**
|
||||
Cette classe represente le widget d'edition d'un polygone dans l'editeur
|
||||
d'element.
|
||||
*/
|
||||
class PolygonEditor : public ElementItemEditor {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PolygonEditor(QETElementEditor *, PartPolygon *, QWidget * = 0);
|
||||
virtual ~PolygonEditor();
|
||||
|
||||
private:
|
||||
PolygonEditor(const PolygonEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartPolygon *part;
|
||||
QTreeWidget points_list;
|
||||
QCheckBox close_polygon;
|
||||
|
||||
// methodes
|
||||
private:
|
||||
QVector<QPointF> getPointsFromTree();
|
||||
|
||||
public slots:
|
||||
void updatePolygon();
|
||||
void updatePolygonPoints();
|
||||
void updatePolygonClosedState();
|
||||
void updateForm();
|
||||
void validColumn(QTreeWidgetItem *qtwi, int column);
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
809
sources/editor/qetelementeditor.cpp
Normal file
809
sources/editor/qetelementeditor.cpp
Normal file
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "qetelementeditor.h"
|
||||
#include "qetapp.h"
|
||||
#include "elementscene.h"
|
||||
#include "elementview.h"
|
||||
#include "customelementpart.h"
|
||||
#include "newelementwizard.h"
|
||||
#include "elementitemeditor.h"
|
||||
#include "recentfiles.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
QETElementEditor::QETElementEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
read_only(false),
|
||||
min_title(tr("QElectroTech - \311diteur d'\351l\351ment")),
|
||||
_filename(QString())
|
||||
{
|
||||
setWindowTitle(min_title);
|
||||
setWindowIcon(QIcon(":/ico/qet.png"));
|
||||
|
||||
setupInterface();
|
||||
setupActions();
|
||||
setupMenus();
|
||||
|
||||
// la fenetre est maximisee par defaut
|
||||
setMinimumSize(QSize(500, 350));
|
||||
setWindowState(Qt::WindowMaximized);
|
||||
|
||||
// lecture des parametres
|
||||
readSettings();
|
||||
|
||||
// affichage
|
||||
show();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
QETElementEditor::~QETElementEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met en place les actions
|
||||
*/
|
||||
void QETElementEditor::setupActions() {
|
||||
new_element = new QAction(QIcon(":/ico/new.png"), tr("&Nouveau"), this);
|
||||
open = new QAction(QIcon(":/ico/open.png"), tr("&Ouvrir"), this);
|
||||
save = new QAction(QIcon(":/ico/save.png"), tr("&Enregistrer"), this);
|
||||
save_as = new QAction(QIcon(":/ico/saveas.png"), tr("Enregistrer sous"), 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);
|
||||
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);
|
||||
zoom_out = new QAction(QIcon(":/ico/viewmag-.png"), tr("Zoom arri\350re"), this);
|
||||
zoom_fit = new QAction(QIcon(":/ico/viewmagfit.png"), tr("Zoom adapt\351"), this);
|
||||
zoom_reset = new QAction(QIcon(":/ico/viewmag.png"), tr("Pas de zoom"), this);
|
||||
edit_size_hs = new QAction(QIcon(":/ico/hotspot.png"), tr("\311diter la taille et le point de saisie"), this);
|
||||
edit_names = new QAction(QIcon(":/ico/names.png"), tr("\311diter les noms"), this);
|
||||
edit_ori = new QAction(QIcon(":/ico/orientations.png"), tr("\311diter les orientations"), this);
|
||||
edit_raise = new QAction(QIcon(":/ico/raise.png"), tr("Rapprocher"), this);
|
||||
edit_lower = new QAction(QIcon(":/ico/lower.png"), tr("\311loigner"), this);
|
||||
edit_backward = new QAction(QIcon(":/ico/send_backward.png"),tr("Envoyer au fond"), this);
|
||||
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_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);
|
||||
add_text = new QAction(QIcon(":/ico/text.png"), tr("Ajouter du texte"), this);
|
||||
add_arc = new QAction(QIcon(":/ico/arc.png"), tr("Ajouter un arc de cercle"), this);
|
||||
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);
|
||||
|
||||
undo = ce_scene -> undoStack().createUndoAction(this, tr("Annuler"));
|
||||
redo = ce_scene -> undoStack().createRedoAction(this, tr("Refaire"));
|
||||
undo -> setIcon(QIcon(":/ico/undo.png"));
|
||||
redo -> setIcon(QIcon(":/ico/redo.png"));
|
||||
undo -> setShortcuts(QKeySequence::Undo);
|
||||
redo -> setShortcuts(QKeySequence::Redo);
|
||||
|
||||
new_element -> setShortcut(QKeySequence::New);
|
||||
open -> setShortcut(QKeySequence::Open);
|
||||
save -> setShortcut(QKeySequence::Save);
|
||||
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")));
|
||||
edit_delete -> setShortcut(QKeySequence(tr("Suppr")));
|
||||
|
||||
zoom_in -> setShortcut(QKeySequence::ZoomIn);
|
||||
zoom_out -> setShortcut(QKeySequence::ZoomOut);
|
||||
zoom_fit -> setShortcut(QKeySequence(tr("Ctrl+9")));
|
||||
zoom_reset -> setShortcut(QKeySequence(tr("Ctrl+0")));
|
||||
|
||||
edit_names -> setShortcut(QKeySequence(tr("Ctrl+E")));
|
||||
edit_size_hs -> setShortcut(QKeySequence(tr("Ctrl+R")));
|
||||
edit_ori -> setShortcut(QKeySequence(tr("Ctrl+T")));
|
||||
|
||||
edit_raise -> setShortcut(QKeySequence(tr("Ctrl+Shift+Up")));
|
||||
edit_lower -> setShortcut(QKeySequence(tr("Ctrl+Shift+Down")));
|
||||
edit_backward -> setShortcut(QKeySequence(tr("Ctrl+Shift+End")));
|
||||
edit_forward -> setShortcut(QKeySequence(tr("Ctrl+Shift+Home")));
|
||||
|
||||
connect(new_element, SIGNAL(triggered()), this, SLOT(slot_new()));
|
||||
connect(open, SIGNAL(triggered()), this, SLOT(slot_open()));
|
||||
connect(save, SIGNAL(triggered()), this, SLOT(slot_save()));
|
||||
connect(save_as, SIGNAL(triggered()), this, SLOT(slot_saveAs()));
|
||||
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(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()));
|
||||
connect(zoom_reset, SIGNAL(triggered()), ce_view, SLOT(zoomReset()));
|
||||
connect(edit_delete, SIGNAL(triggered()), ce_scene, SLOT(slot_delete()));
|
||||
connect(edit_size_hs, SIGNAL(triggered()), ce_scene, SLOT(slot_editSizeHotSpot()));
|
||||
connect(edit_names, SIGNAL(triggered()), ce_scene, SLOT(slot_editNames()));
|
||||
connect(edit_ori, SIGNAL(triggered()), ce_scene, SLOT(slot_editOrientations()));
|
||||
connect(edit_forward, SIGNAL(triggered()), ce_scene, SLOT(slot_bringForward()));
|
||||
connect(edit_raise, SIGNAL(triggered()), ce_scene, SLOT(slot_raise()));
|
||||
connect(edit_lower, SIGNAL(triggered()), ce_scene, SLOT(slot_lower()));
|
||||
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_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()));
|
||||
connect(add_text, SIGNAL(triggered()), ce_scene, SLOT(slot_addText()));
|
||||
connect(add_arc, SIGNAL(triggered()), ce_scene, SLOT(slot_addArc()));
|
||||
connect(add_terminal, SIGNAL(triggered()), ce_scene, SLOT(slot_addTerminal()));
|
||||
connect(add_textfield, SIGNAL(triggered()), ce_scene, SLOT(slot_addTextField()));
|
||||
|
||||
connect(move, SIGNAL(triggered()), this, SLOT(slot_setRubberBandToView()));
|
||||
connect(add_line, 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()));
|
||||
connect(add_text, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_arc, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_terminal, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
connect(add_textfield, SIGNAL(triggered()), this, SLOT(slot_setNoDragToView()));
|
||||
|
||||
connect(ce_scene, SIGNAL(needNormalMode()), this, SLOT(slot_setNormalMode()));
|
||||
|
||||
move -> setCheckable(true);
|
||||
add_line -> setCheckable(true);
|
||||
add_ellipse -> setCheckable(true);
|
||||
add_circle -> setCheckable(true);
|
||||
add_polygon -> setCheckable(true);
|
||||
add_text -> setCheckable(true);
|
||||
add_arc -> setCheckable(true);
|
||||
add_terminal -> setCheckable(true);
|
||||
add_textfield -> setCheckable(true);
|
||||
|
||||
parts = new QActionGroup(this);
|
||||
parts -> addAction(move);
|
||||
parts -> addAction(add_line);
|
||||
parts -> addAction(add_ellipse);
|
||||
parts -> addAction(add_circle);
|
||||
parts -> addAction(add_polygon);
|
||||
parts -> addAction(add_text);
|
||||
parts -> addAction(add_arc);
|
||||
parts -> addAction(add_textfield);
|
||||
parts -> addAction(add_terminal);
|
||||
parts -> setExclusive(true);
|
||||
|
||||
parts_toolbar = new QToolBar(tr("Parties"), this);
|
||||
parts_toolbar -> setObjectName("parts");
|
||||
foreach (QAction *action, parts -> actions()) parts_toolbar -> addAction(action);
|
||||
move -> setChecked(true);
|
||||
parts_toolbar -> setAllowedAreas(Qt::AllToolBarAreas);
|
||||
|
||||
/*
|
||||
QAction *xml_preview = new QAction(QIcon(":/ico/info.png"), tr("XML"), this);
|
||||
connect(xml_preview, SIGNAL(triggered()), this, SLOT(xmlPreview()));
|
||||
parts_toolbar -> addAction(xml_preview);
|
||||
*/
|
||||
|
||||
main_toolbar = new QToolBar(tr("Outils"), this);
|
||||
main_toolbar -> setObjectName("main_toolbar");
|
||||
view_toolbar = new QToolBar(tr("Affichage"), this);
|
||||
view_toolbar -> setObjectName("display");
|
||||
element_toolbar = new QToolBar(tr("\311l\351ment"), this);
|
||||
element_toolbar -> setObjectName("element_toolbar");
|
||||
depth_toolbar = new QToolBar(tr("Profondeur"), this);
|
||||
depth_toolbar -> setObjectName("depth_toolbar");
|
||||
|
||||
main_toolbar -> addAction(new_element);
|
||||
main_toolbar -> addAction(open);
|
||||
main_toolbar -> addAction(save);
|
||||
main_toolbar -> addAction(save_as);
|
||||
main_toolbar -> addAction(reload);
|
||||
main_toolbar -> addSeparator();
|
||||
main_toolbar -> addAction(undo);
|
||||
main_toolbar -> addAction(redo);
|
||||
main_toolbar -> addSeparator();
|
||||
main_toolbar -> addAction(edit_delete);
|
||||
view_toolbar -> addAction(zoom_in);
|
||||
view_toolbar -> addAction(zoom_out);
|
||||
view_toolbar -> addAction(zoom_fit);
|
||||
view_toolbar -> addAction(zoom_reset);
|
||||
element_toolbar -> addAction(edit_size_hs);
|
||||
element_toolbar -> addAction(edit_names);
|
||||
element_toolbar -> addAction(edit_ori);
|
||||
depth_toolbar -> addAction(edit_forward);
|
||||
depth_toolbar -> addAction(edit_raise);
|
||||
depth_toolbar -> addAction(edit_lower);
|
||||
depth_toolbar -> addAction(edit_backward);
|
||||
|
||||
addToolBar(Qt::TopToolBarArea, main_toolbar);
|
||||
addToolBar(Qt::TopToolBarArea, view_toolbar);
|
||||
addToolBar(Qt::TopToolBarArea, element_toolbar);
|
||||
addToolBar(Qt::TopToolBarArea, depth_toolbar);
|
||||
addToolBar(Qt::LeftToolBarArea, parts_toolbar);
|
||||
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()));
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), 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()));
|
||||
}
|
||||
|
||||
/**
|
||||
Met en place les menus.
|
||||
*/
|
||||
void QETElementEditor::setupMenus() {
|
||||
file_menu = new QMenu(tr("Fichier"), this);
|
||||
edit_menu = new QMenu(tr("\311dition"), this);
|
||||
display_menu = new QMenu(tr("Affichage"), this);
|
||||
tools_menu = new QMenu(tr("Outils"), this);
|
||||
help_menu = new QMenu(tr("Aide"), this);
|
||||
|
||||
file_menu -> setTearOffEnabled(true);
|
||||
edit_menu -> setTearOffEnabled(true);
|
||||
display_menu -> setTearOffEnabled(true);
|
||||
tools_menu -> setTearOffEnabled(true);
|
||||
help_menu -> setTearOffEnabled(true);
|
||||
|
||||
file_menu -> addAction(new_element);
|
||||
file_menu -> addAction(open);
|
||||
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 -> addSeparator();
|
||||
file_menu -> addAction(reload);
|
||||
file_menu -> addSeparator();
|
||||
file_menu -> addAction(quit);
|
||||
|
||||
edit_menu -> addAction(undo);
|
||||
edit_menu -> addAction(redo);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(selectall);
|
||||
edit_menu -> addAction(deselectall);
|
||||
edit_menu -> addAction(inv_select);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(edit_delete);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(edit_names);
|
||||
edit_menu -> addAction(edit_size_hs);
|
||||
edit_menu -> addAction(edit_ori);
|
||||
edit_menu -> addSeparator();
|
||||
edit_menu -> addAction(edit_forward);
|
||||
edit_menu -> addAction(edit_raise);
|
||||
edit_menu -> addAction(edit_lower);
|
||||
edit_menu -> addAction(edit_backward);
|
||||
|
||||
// menu Affichage > Afficher
|
||||
QMenu *display_toolbars = createPopupMenu();
|
||||
display_toolbars -> setTearOffEnabled(true);
|
||||
display_toolbars -> setTitle(tr("Afficher"));
|
||||
display_menu -> addMenu(display_toolbars);
|
||||
|
||||
menuBar() -> addMenu(file_menu);
|
||||
menuBar() -> addMenu(edit_menu);
|
||||
menuBar() -> addMenu(display_menu);
|
||||
|
||||
/*
|
||||
menuBar() -> addMenu(tools_menu);
|
||||
menuBar() -> addMenu(help_menu);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour les menus
|
||||
*/
|
||||
void QETElementEditor::slot_updateMenus() {
|
||||
bool selected_items = !ce_scene -> selectedItems().isEmpty();
|
||||
edit_delete -> setEnabled(selected_items);
|
||||
edit_forward -> setEnabled(selected_items);
|
||||
edit_raise -> setEnabled(selected_items);
|
||||
edit_lower -> setEnabled(selected_items);
|
||||
edit_backward -> setEnabled(selected_items);
|
||||
save -> setEnabled(!ce_scene -> undoStack().isClean());
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le titre de la fenetre
|
||||
*/
|
||||
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]");
|
||||
}
|
||||
setWindowTitle(title);
|
||||
}
|
||||
|
||||
/**
|
||||
Met en place l'interface
|
||||
*/
|
||||
void QETElementEditor::setupInterface() {
|
||||
// editeur
|
||||
ce_scene = new ElementScene(this, this);
|
||||
ce_scene -> slot_move();
|
||||
ce_view = new ElementView(ce_scene, this);
|
||||
slot_setRubberBandToView();
|
||||
setCentralWidget(ce_view);
|
||||
|
||||
// widget par defaut dans le QDockWidget
|
||||
default_informations = new QLabel();
|
||||
|
||||
// panel sur le cote pour editer les parties
|
||||
tools_dock = new QDockWidget(tr("Informations"), this);
|
||||
tools_dock -> setObjectName("informations");
|
||||
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
tools_dock -> setMinimumWidth(290);
|
||||
addDockWidget(Qt::RightDockWidgetArea, tools_dock);
|
||||
QWidget *info_widget = new QWidget();
|
||||
info_widget -> setLayout(new QVBoxLayout(info_widget));
|
||||
tools_dock -> setWidget(info_widget);
|
||||
|
||||
// panel sur le cote pour les annulations
|
||||
undo_dock = new QDockWidget(tr("Annulations"), this);
|
||||
undo_dock -> setObjectName("undo");
|
||||
undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
undo_dock -> setMinimumWidth(290);
|
||||
addDockWidget(Qt::RightDockWidgetArea, undo_dock);
|
||||
QUndoView* undo_view = new QUndoView(&(ce_scene -> undoStack()), this);
|
||||
undo_view -> setEmptyLabel(tr("Aucune modification"));
|
||||
undo_dock -> setWidget(undo_view);
|
||||
|
||||
// panel sur le cote pour la liste des parties
|
||||
parts_list = new QListWidget(this);
|
||||
parts_list -> setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
connect(ce_scene, SIGNAL(partsAdded()), this, SLOT(slot_createPartsList()));
|
||||
connect(ce_scene, SIGNAL(partsRemoved()), this, SLOT(slot_createPartsList()));
|
||||
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 -> setObjectName("parts_list");
|
||||
parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
parts_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
parts_dock -> setMinimumWidth(290);
|
||||
tabifyDockWidget(undo_dock, parts_dock);
|
||||
parts_dock -> setWidget(parts_list);
|
||||
|
||||
slot_updateInformations();
|
||||
slot_createPartsList();
|
||||
|
||||
// barre d'etat
|
||||
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments"));
|
||||
}
|
||||
|
||||
/**
|
||||
Passe l'editeur d'element en mode selection : le pointeur deplace les
|
||||
elements selectionnes et il est possible d'utiliser un rectangle de selection.
|
||||
*/
|
||||
void QETElementEditor::slot_setRubberBandToView() {
|
||||
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
|
||||
}
|
||||
|
||||
/**
|
||||
Passe l'editeur d'element en mode immobile (utilise pour la lecture seule)
|
||||
*/
|
||||
void QETElementEditor::slot_setNoDragToView() {
|
||||
ce_view -> setDragMode(QGraphicsView::NoDrag);
|
||||
}
|
||||
|
||||
/**
|
||||
Passe l'editeur en mode normal
|
||||
*/
|
||||
void QETElementEditor::slot_setNormalMode() {
|
||||
if (!move -> isChecked()) move -> setChecked(true);
|
||||
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
|
||||
ce_scene -> slot_move();
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la zone d'information et d'edition.
|
||||
Si plusieurs parties sont selectionnees, seul leur nombre est affiche.
|
||||
Sinon, le widget d'edition de la partie est insere.
|
||||
@see CustomElementPart::elementInformations()
|
||||
*/
|
||||
void QETElementEditor::slot_updateInformations() {
|
||||
QList<QGraphicsItem *> selected_qgis = ce_scene -> selectedItems();
|
||||
QList<CustomElementPart *> selected_parts;
|
||||
foreach(QGraphicsItem *qgi, selected_qgis) {
|
||||
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi)) {
|
||||
selected_parts.append(cep);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (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();
|
||||
} else {
|
||||
default_informations -> setText(
|
||||
selected_parts.size() ?
|
||||
QString("%1").arg(selected_parts.size()) + tr(" parties s\351lectionn\351es.") :
|
||||
tr("Aucune partie s\351lectionn\351e.")
|
||||
);
|
||||
layout -> addWidget(default_informations);
|
||||
default_informations -> show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Affiche le code XML correspondant a l'element dans son etat actuel dans
|
||||
une boite de dialogue.
|
||||
*/
|
||||
void QETElementEditor::xmlPreview() {
|
||||
QMessageBox::information(
|
||||
this,
|
||||
"Export XML",
|
||||
ce_scene -> toXml().toString(4)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Charge un fichier
|
||||
@param filepath Chemin du fichier a charger
|
||||
*/
|
||||
void QETElementEditor::fromFile(const QString &filepath) {
|
||||
bool state = true;
|
||||
QString error_message;
|
||||
|
||||
// le fichier doit exister
|
||||
QFileInfo infos_file(filepath);
|
||||
if (!infos_file.exists() || !infos_file.isFile()) {
|
||||
state = false;
|
||||
error_message = tr("Le fichier ") + filepath + tr(" n'existe pas.");
|
||||
}
|
||||
|
||||
// le fichier doit etre lisible
|
||||
QFile file(filepath);
|
||||
if (state) {
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
state = false;
|
||||
error_message = tr("Impossible d'ouvrir le fichier ") + filepath + ".";
|
||||
}
|
||||
}
|
||||
|
||||
// le fichier doit etre un document XML
|
||||
QDomDocument document_xml;
|
||||
if (state) {
|
||||
if (!document_xml.setContent(&file)) {
|
||||
state = false;
|
||||
error_message = tr("Ce fichier n'est pas un document XML valide");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
QMessageBox::critical(this, tr("Erreur"), error_message);
|
||||
return;
|
||||
}
|
||||
|
||||
// chargement de l'element
|
||||
ce_scene -> fromXml(document_xml);
|
||||
slot_createPartsList();
|
||||
|
||||
// gestion de la lecture seule
|
||||
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.")
|
||||
);
|
||||
setReadOnly(true);
|
||||
}
|
||||
|
||||
// memorise le fichier
|
||||
setFileName(filepath);
|
||||
QETApp::elementsRecentFiles() -> fileWasOpened(filepath);
|
||||
slot_updateMenus();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enregistre l'element vers un fichier
|
||||
@param fn Chemin du fichier a enregistrer
|
||||
@return true en cas de reussite, false sinon
|
||||
*/
|
||||
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"));
|
||||
return(false);
|
||||
}
|
||||
QTextStream out(&file);
|
||||
out.setCodec("UTF-8");
|
||||
out << ce_scene -> toXml().toString(4);
|
||||
file.close();
|
||||
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
|
||||
*/
|
||||
void QETElementEditor::setReadOnly(bool ro) {
|
||||
read_only = ro;
|
||||
// active / desactive les actions
|
||||
foreach (QAction *action, parts -> actions()) action -> setEnabled(!ro);
|
||||
|
||||
// active / desactive les interactions avec la scene
|
||||
ce_view -> setInteractive(!ro);
|
||||
|
||||
// active / desactive l'edition de la taille, du hotspot, des noms et des orientations
|
||||
selectall -> setEnabled(!ro);
|
||||
deselectall -> setEnabled(!ro);
|
||||
inv_select -> setEnabled(!ro);
|
||||
undo -> setEnabled(!ro);
|
||||
redo -> setEnabled(!ro);
|
||||
edit_delete -> setEnabled(!ro);
|
||||
edit_size_hs -> setEnabled(!ro);
|
||||
edit_names -> setEnabled(!ro);
|
||||
edit_ori -> setEnabled(!ro);
|
||||
parts_list -> setEnabled(!ro);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si l'editeur d'element est en mode lecture seule
|
||||
*/
|
||||
bool QETElementEditor::isReadOnly() const {
|
||||
return(read_only);
|
||||
}
|
||||
|
||||
/**
|
||||
Lance l'assistant de creation d'un nouvel element.
|
||||
*/
|
||||
void QETElementEditor::slot_new() {
|
||||
NewElementWizard new_element_wizard;
|
||||
new_element_wizard.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Demande un fichier a l'utilisateur et ouvre ce fichier
|
||||
*/
|
||||
void QETElementEditor::slot_open() {
|
||||
// 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 (*)")
|
||||
);
|
||||
openElement(user_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
Slot utilise pour ouvrir un fichier recent.
|
||||
Transfere filepath au slot openElement seulement si cet editeur est actif
|
||||
@param filepath Fichier a ouvrir
|
||||
@see openElement
|
||||
*/
|
||||
void QETElementEditor::openRecentFile(const QString &filepath) {
|
||||
if (qApp -> activeWindow() != this) return;
|
||||
openElement(filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
Ouvre un fichier element dans un nouvel editeur
|
||||
Cette methode ne controle pas si le fichier est deja ouvert
|
||||
@param filepath Fichier a ouvrir
|
||||
@see fromFile
|
||||
*/
|
||||
void QETElementEditor::openElement(const QString &filepath) {
|
||||
if (filepath.isEmpty()) return;
|
||||
QETElementEditor *cee = new QETElementEditor();
|
||||
cee -> fromFile(filepath);
|
||||
cee -> show();
|
||||
}
|
||||
|
||||
/**
|
||||
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 ?"),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
if (answer != QMessageBox::Yes) return;
|
||||
}
|
||||
|
||||
// recharge l'element
|
||||
ce_scene -> reset();
|
||||
fromFile(_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
Enregistre l'element en cours d'edition.
|
||||
Si le nom du fichier en cours n'est pas connu, cette methode equivaut a
|
||||
l'action "Enregistrer sous"
|
||||
@see slot_saveAs()
|
||||
*/
|
||||
bool QETElementEditor::slot_save() {
|
||||
// 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();
|
||||
return(result_save);
|
||||
}
|
||||
|
||||
/**
|
||||
Demande un nom de fichier a l'utilisateur et enregistre l'element
|
||||
*/
|
||||
bool QETElementEditor::slot_saveAs() {
|
||||
// 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)")
|
||||
);
|
||||
// si aucun nom n'est entre, renvoie faux.
|
||||
if (fn.isEmpty()) return(false);
|
||||
// si le nom ne se termine pas par l'extension .elmt, celle-ci est ajoutee
|
||||
if (!fn.endsWith(".elmt", Qt::CaseInsensitive)) fn += ".elmt";
|
||||
// tente d'enregistrer le fichier
|
||||
bool result_save = toFile(fn);
|
||||
// si l'enregistrement reussit, le nom du fichier est conserve
|
||||
if (result_save) {
|
||||
setFileName(fn);
|
||||
ce_scene -> undoStack().setClean();
|
||||
}
|
||||
// retourne un booleen representatif de la reussite de l'enregistrement
|
||||
return(result_save);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si l'element peut etre ferme.
|
||||
Un element peut etre ferme s'il ne comporte aucune modification.
|
||||
Si l'element comporte des modifications, la question est posee a
|
||||
l'utilisateur.
|
||||
*/
|
||||
bool QETElementEditor::canClose() {
|
||||
if (ce_scene -> undoStack().isClean()) return(true);
|
||||
// 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,
|
||||
QMessageBox::Cancel
|
||||
);
|
||||
bool result;
|
||||
switch(answer) {
|
||||
case QMessageBox::Cancel: result = false; break; // l'utilisateur annule : echec de la fermeture
|
||||
case QMessageBox::Yes: result = slot_save(); break; // l'utilisateur dit oui : la reussite depend de l'enregistrement
|
||||
default: result = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de quitter l'editeur lors de la fermeture de la fenetre principale
|
||||
@param qce Le QCloseEvent correspondant a l'evenement de fermeture
|
||||
*/
|
||||
void QETElementEditor::closeEvent(QCloseEvent *qce) {
|
||||
if (canClose()) {
|
||||
writeSettings();
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
qce -> accept();
|
||||
} else qce -> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
Remplit la liste des parties
|
||||
*/
|
||||
void QETElementEditor::slot_createPartsList() {
|
||||
parts_list -> blockSignals(true);
|
||||
parts_list -> clear();
|
||||
QList<QGraphicsItem *> qgis = ce_scene -> zItems(true);
|
||||
for (int j = qgis.count() - 1 ; j >= 0 ; -- j) {
|
||||
QGraphicsItem *qgi = qgis[j];
|
||||
if (CustomElementPart *cep = dynamic_cast<CustomElementPart *>(qgi)) {
|
||||
QString part_desc = cep -> name();
|
||||
QListWidgetItem *qlwi = new QListWidgetItem(part_desc);
|
||||
QVariant v;
|
||||
v.setValue<QGraphicsItem *>(qgi);
|
||||
qlwi -> setData(42, v);
|
||||
parts_list -> addItem(qlwi);
|
||||
qlwi -> setSelected(qgi -> isSelected());
|
||||
}
|
||||
}
|
||||
parts_list -> blockSignals(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la selection dans la liste des parties
|
||||
*/
|
||||
void QETElementEditor::slot_updatePartsList() {
|
||||
if (parts_list -> count() != ce_scene -> items().count()) {
|
||||
slot_createPartsList();
|
||||
} else {
|
||||
parts_list -> blockSignals(true);
|
||||
int i = 0;
|
||||
QList<QGraphicsItem *> items = ce_scene -> zItems(true);
|
||||
for (int j = items.count() - 1 ; j >= 0 ; -- j) {
|
||||
QGraphicsItem *qgi = items[j];
|
||||
QListWidgetItem *qlwi = parts_list -> item(i);
|
||||
if (qlwi) qlwi -> setSelected(qgi -> isSelected());
|
||||
++ i;
|
||||
}
|
||||
parts_list -> blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour la selection des parties de l'element a partir de la liste des
|
||||
parties
|
||||
*/
|
||||
void QETElementEditor::slot_updateSelectionFromPartsList() {
|
||||
ce_scene -> blockSignals(true);
|
||||
parts_list -> blockSignals(true);
|
||||
for (int i = 0 ; i < parts_list -> count() ; ++ i) {
|
||||
QListWidgetItem *qlwi = parts_list -> item(i);
|
||||
QGraphicsItem *qgi = qlwi -> data(42).value<QGraphicsItem *>();
|
||||
if (qgi) {
|
||||
qgi -> setSelected(qlwi -> isSelected());
|
||||
}
|
||||
}
|
||||
parts_list -> blockSignals(false);
|
||||
ce_scene -> blockSignals(false);
|
||||
slot_updateInformations();
|
||||
}
|
||||
|
||||
/// Lit les parametres de l'editeur d'element
|
||||
void QETElementEditor::readSettings() {
|
||||
QSettings &settings = QETApp::settings();
|
||||
|
||||
// dimensions et position de la fenetre
|
||||
QVariant geometry = settings.value("elementeditor/geometry");
|
||||
if (geometry.isValid()) restoreGeometry(geometry.toByteArray());
|
||||
|
||||
// etat de la fenetre (barres d'outils, docks...)
|
||||
QVariant state = settings.value("elementeditor/state");
|
||||
if (state.isValid()) restoreState(state.toByteArray());
|
||||
}
|
||||
|
||||
/// Enregistre les parametres de l'editeur d'element
|
||||
void QETElementEditor::writeSettings() {
|
||||
QSettings &settings = QETApp::settings();
|
||||
settings.setValue("elementeditor/geometry", saveGeometry());
|
||||
settings.setValue("elementeditor/state", saveState());
|
||||
}
|
||||
203
sources/editor/qetelementeditor.h
Normal file
203
sources/editor/qetelementeditor.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 CUSTOM_ELEMENT_EDITOR_H
|
||||
#define CUSTOM_ELEMENT_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementscene.h"
|
||||
#include "orientationset.h"
|
||||
class ElementView;
|
||||
/**
|
||||
Cette classe represente un editeur d'element. Elle permet a l'utilisateur
|
||||
de dessiner, modifier et parametrer un element electrique. Le dessin se
|
||||
fait par ajout de parties (Part).
|
||||
*/
|
||||
class QETElementEditor : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeur, destructeur
|
||||
public:
|
||||
QETElementEditor(QWidget * = 0);
|
||||
virtual ~QETElementEditor();
|
||||
private:
|
||||
QETElementEditor(const QETElementEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
/// booleen indiquant si l'editeur est en mode "lecture seule" ou non
|
||||
bool read_only;
|
||||
/// menus
|
||||
QMenu *file_menu, *edit_menu, *display_menu, *tools_menu, *help_menu;
|
||||
/// vue sur la scene d'edition
|
||||
ElementView *ce_view;
|
||||
/// scene d'edition
|
||||
ElementScene *ce_scene;
|
||||
/// container pour les widgets d'edition des parties
|
||||
QDockWidget *tools_dock;
|
||||
/// container pour la liste des annulations
|
||||
QDockWidget *undo_dock;
|
||||
/// Container pour la liste des parties
|
||||
QDockWidget *parts_dock;
|
||||
/// Liste des parties
|
||||
QListWidget *parts_list;
|
||||
/// actions du menu fichier
|
||||
QAction *new_element, *open, *save, *save_as, *reload, *quit;
|
||||
/// actions du menu edition
|
||||
QAction *selectall, *deselectall, *inv_select;
|
||||
QAction *undo, *redo;
|
||||
QAction *zoom_in, *zoom_out, *zoom_fit, *zoom_reset;
|
||||
QAction *edit_delete, *edit_size_hs, *edit_names, *edit_ori;
|
||||
QAction *edit_raise, *edit_lower, *edit_backward, *edit_forward;
|
||||
/// barres d'outils
|
||||
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 *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;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setSize(const QSize &);
|
||||
QSize size() const;
|
||||
void setHotspot(const QPoint &);
|
||||
QPoint hotspot() const;
|
||||
void setNames(const NamesList &);
|
||||
void setOrientations(const OrientationSet &orientation_set);
|
||||
OrientationSet orientations() const;
|
||||
void setFileName(const QString &);
|
||||
QString fileName() const;
|
||||
void setReadOnly(bool);
|
||||
bool isReadOnly() const;
|
||||
void fromFile(const QString &);
|
||||
bool toFile(const QString &);
|
||||
ElementScene *elementScene() const;
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
||||
private:
|
||||
void setupActions();
|
||||
void setupMenus();
|
||||
void setupInterface();
|
||||
bool canClose();
|
||||
|
||||
public slots:
|
||||
void slot_new();
|
||||
void slot_open();
|
||||
void openRecentFile(const QString &);
|
||||
void openElement(const QString &);
|
||||
void slot_reload();
|
||||
bool slot_save();
|
||||
bool slot_saveAs();
|
||||
void slot_setRubberBandToView();
|
||||
void slot_setNoDragToView();
|
||||
void slot_setNormalMode();
|
||||
void slot_updateInformations();
|
||||
void slot_updateMenus();
|
||||
void slot_updateTitle();
|
||||
void slot_createPartsList();
|
||||
void slot_updatePartsList();
|
||||
void slot_updateSelectionFromPartsList();
|
||||
void xmlPreview();
|
||||
};
|
||||
|
||||
/**
|
||||
@param siz La nouvelle taille de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setSize(const QSize &siz) {
|
||||
ce_scene -> setWidth(siz.width());
|
||||
ce_scene -> setHeight(siz.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@return la taille de l'element edite
|
||||
*/
|
||||
inline QSize QETElementEditor::size() const {
|
||||
return(
|
||||
QSize(
|
||||
ce_scene -> width(),
|
||||
ce_scene -> height()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@param hs Le nouveau point de saisie de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setHotspot(const QPoint &hs) {
|
||||
ce_scene -> setHotspot(hs);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le point de saisie de l'element edite
|
||||
*/
|
||||
inline QPoint QETElementEditor::hotspot() const {
|
||||
return(ce_scene -> hotspot());
|
||||
}
|
||||
|
||||
/**
|
||||
@param nameslist le nouvel ensemble de noms de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setNames(const NamesList &nameslist) {
|
||||
ce_scene -> setNames(nameslist);
|
||||
}
|
||||
|
||||
/**
|
||||
@param orientation_set le nouvel ensemble d'orientations de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setOrientations(const OrientationSet &orientation_set) {
|
||||
ce_scene -> setOrientations(orientation_set);
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nouvel ensemble d'orientations de l'element edite
|
||||
*/
|
||||
inline OrientationSet QETElementEditor::orientations() const {
|
||||
return(ce_scene -> orientations());
|
||||
}
|
||||
|
||||
/**
|
||||
@param fn Le nouveau nom de fichier de l'element edite
|
||||
*/
|
||||
inline void QETElementEditor::setFileName(const QString &fn) {
|
||||
_filename = fn;
|
||||
slot_updateTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
@return le nomde fichier de l'element edite
|
||||
*/
|
||||
inline QString QETElementEditor::fileName() const {
|
||||
return(_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
@return la scene d'edition de l'element
|
||||
*/
|
||||
inline ElementScene *QETElementEditor::elementScene() const {
|
||||
return(ce_scene);
|
||||
}
|
||||
|
||||
#endif
|
||||
180
sources/editor/styleeditor.cpp
Normal file
180
sources/editor/styleeditor.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "styleeditor.h"
|
||||
#include "customelementgraphicpart.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param p La partie a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
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);
|
||||
|
||||
// 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 -> 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// antialiasing
|
||||
antialiasing = new QCheckBox(tr("Antialiasing"));
|
||||
|
||||
updateForm();
|
||||
|
||||
main_layout = new QVBoxLayout();
|
||||
main_layout -> addWidget(antialiasing);
|
||||
|
||||
main_layout -> addWidget(new QLabel("<u>" + tr("Trait :") + "</u> "));
|
||||
|
||||
QHBoxLayout *color_layout = new QHBoxLayout();
|
||||
color_layout -> addWidget(new QLabel(tr("Couleur : ")));
|
||||
color_layout -> addWidget(black_color);
|
||||
color_layout -> addWidget(white_color);
|
||||
color_layout -> addStretch();
|
||||
main_layout -> addItem(color_layout);
|
||||
|
||||
QHBoxLayout *style_layout = new QHBoxLayout();
|
||||
style_layout -> addWidget(new QLabel(tr("Style : ")));
|
||||
style_layout -> addWidget(normal_style);
|
||||
style_layout -> addWidget(dashed_style);
|
||||
style_layout -> addStretch();
|
||||
main_layout -> addItem(style_layout);
|
||||
|
||||
QHBoxLayout *weight_layout = new QHBoxLayout();
|
||||
weight_layout -> addWidget(new QLabel(tr("\311paisseur : ")));
|
||||
weight_layout -> addWidget(none_weight);
|
||||
weight_layout -> addWidget(thin_weight);
|
||||
weight_layout -> addWidget(normal_weight);
|
||||
weight_layout -> addStretch();
|
||||
main_layout -> addItem(weight_layout);
|
||||
|
||||
main_layout -> addWidget(new QLabel("<u>" + tr("Remplissage :") + "</u> "));
|
||||
|
||||
QHBoxLayout *filling_layout = new QHBoxLayout();
|
||||
filling_layout -> addWidget(no_filling);
|
||||
filling_layout -> addWidget(black_filling);
|
||||
filling_layout -> addWidget(white_filling);
|
||||
filling_layout -> addStretch();
|
||||
main_layout -> addItem(filling_layout);
|
||||
|
||||
main_layout -> addStretch();
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
StyleEditor::~StyleEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le style de la partie a partir des donnees du formulaire
|
||||
*/
|
||||
void StyleEditor::updatePart() {
|
||||
// applique l'antialiasing
|
||||
part -> setAntialiased(antialiasing -> isChecked());
|
||||
|
||||
// applique la couleur
|
||||
part -> setColor(static_cast<CEGP::Color>(color -> checkedId()));
|
||||
|
||||
// applique le style
|
||||
part -> setLineStyle(static_cast<CEGP::LineStyle>(style -> checkedId()));
|
||||
|
||||
// applique l'epaisseur
|
||||
part -> setLineWeight(static_cast<CEGP::LineWeight>(weight -> checkedId()));
|
||||
|
||||
// applique le remplissage
|
||||
part -> setFilling(static_cast<CEGP::Filling>(filling -> checkedId()));
|
||||
}
|
||||
|
||||
/// Met a jour l'antialiasing et cree un objet d'annulation
|
||||
void StyleEditor::updatePartAntialiasing() { addChangePartCommand("style antialiasing", part, "antialias", antialiasing -> isChecked()); }
|
||||
/// Met a jour la couleur du trait et cree un objet d'annulation
|
||||
void StyleEditor::updatePartColor() { addChangePartCommand("style couleur", part, "color", color -> checkedId()); }
|
||||
/// Met a jour le style du trait et cree un objet d'annulation
|
||||
void StyleEditor::updatePartLineStyle() { addChangePartCommand("style ligne", part, "line-style", style -> checkedId()); }
|
||||
/// Met a jour l'epaisseur du trait et cree un objet d'annulation
|
||||
void StyleEditor::updatePartLineWeight() { addChangePartCommand("style epaisseur", part, "line-weight", weight -> checkedId()); }
|
||||
/// Met a jour la couleur de fond et cree un objet d'annulation
|
||||
void StyleEditor::updatePartFilling() { addChangePartCommand("style remplissage", part, "filling", filling -> checkedId()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void StyleEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
// lit l'antialiasing
|
||||
antialiasing -> setChecked(part -> antialiased());
|
||||
|
||||
// lit la couleur
|
||||
color -> button(part -> color()) -> setChecked(true);
|
||||
|
||||
// lit le style
|
||||
style -> button(part -> lineStyle()) -> setChecked(true);
|
||||
|
||||
// lit l'epaisseur
|
||||
weight -> button(part -> lineWeight()) -> setChecked(true);
|
||||
|
||||
// lit le remplissage
|
||||
filling -> button(part -> filling()) -> setChecked(true);
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute un widget en bas de l'editeur de style
|
||||
@param w Widget a inserer
|
||||
*/
|
||||
void StyleEditor::appendWidget(QWidget *w) {
|
||||
main_layout -> insertWidget(7, w);
|
||||
}
|
||||
|
||||
/**
|
||||
Active ou desactive les connexionx signaux/slots entre les widgets internes.
|
||||
@param active true pour activer les connexions, false pour les desactiver
|
||||
*/
|
||||
void StyleEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePartColor()));
|
||||
connect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineStyle()));
|
||||
connect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineWeight()));
|
||||
connect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePartFilling()));
|
||||
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePartAntialiasing()));
|
||||
} else {
|
||||
disconnect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePartColor()));
|
||||
disconnect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineStyle()));
|
||||
disconnect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePartLineWeight()));
|
||||
disconnect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePartFilling()));
|
||||
disconnect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePartAntialiasing()));
|
||||
}
|
||||
}
|
||||
65
sources/editor/styleeditor.h
Normal file
65
sources/editor/styleeditor.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 STYLE_EDITOR_H
|
||||
#define STYLE_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class CustomElementGraphicPart;
|
||||
/**
|
||||
Cette classe represente un widget d'edition des styles que peut comporter
|
||||
une partie d'elements (couleur, epaisseur et style du trait, remplissage,
|
||||
antialiasing). Elle peut accueillir un widget sous cette interface grace a
|
||||
la methode appendWidget.
|
||||
*/
|
||||
class StyleEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
StyleEditor(QETElementEditor *, CustomElementGraphicPart *, QWidget * = 0);
|
||||
virtual ~StyleEditor();
|
||||
|
||||
private:
|
||||
StyleEditor(const StyleEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
CustomElementGraphicPart *part;
|
||||
QVBoxLayout *main_layout;
|
||||
QButtonGroup *color, *style, *weight, *filling;
|
||||
QRadioButton *black_color, *white_color, *normal_style, *dashed_style;
|
||||
QRadioButton *none_weight, *thin_weight, *normal_weight, *no_filling;
|
||||
QRadioButton *black_filling, *white_filling;
|
||||
QCheckBox *antialiasing;
|
||||
|
||||
//methodes
|
||||
public:
|
||||
void appendWidget(QWidget *w);
|
||||
|
||||
public slots:
|
||||
void updatePart();
|
||||
void updateForm();
|
||||
void updatePartAntialiasing();
|
||||
void updatePartColor();
|
||||
void updatePartLineStyle();
|
||||
void updatePartLineWeight();
|
||||
void updatePartFilling();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
113
sources/editor/terminaleditor.cpp
Normal file
113
sources/editor/terminaleditor.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "terminaleditor.h"
|
||||
#include "partterminal.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param term La borne a editer
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
TerminalEditor::TerminalEditor(QETElementEditor *editor, PartTerminal *term, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
part = term;
|
||||
|
||||
qle_x = new QLineEdit();
|
||||
qle_y = new QLineEdit();
|
||||
|
||||
qle_x -> setValidator(new QDoubleValidator(qle_x));
|
||||
qle_y -> setValidator(new QDoubleValidator(qle_y));
|
||||
|
||||
orientation = new QComboBox();
|
||||
orientation -> addItem(QIcon(":/ico/north.png"), tr("Nord"), QET::North);
|
||||
orientation -> addItem(QIcon(":/ico/east.png"), tr("Est"), QET::East);
|
||||
orientation -> addItem(QIcon(":/ico/south.png"), tr("Sud"), QET::South);
|
||||
orientation -> addItem(QIcon(":/ico/west.png"), tr("Ouest"), QET::West);
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout();
|
||||
main_layout -> addWidget(new QLabel(tr("Position : ")));
|
||||
|
||||
QHBoxLayout *position = new QHBoxLayout();
|
||||
position -> addWidget(new QLabel(tr("x : ")));
|
||||
position -> addWidget(qle_x );
|
||||
position -> addWidget(new QLabel(tr("y : ")));
|
||||
position -> addWidget(qle_y );
|
||||
main_layout -> addLayout(position);
|
||||
|
||||
QHBoxLayout *ori = new QHBoxLayout();
|
||||
ori -> addWidget(new QLabel(tr("Orientation : ")));
|
||||
ori -> addWidget(orientation );
|
||||
main_layout -> addLayout(ori);
|
||||
main_layout -> addStretch();
|
||||
setLayout(main_layout);
|
||||
|
||||
activeConnections(true);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
TerminalEditor::~TerminalEditor() {
|
||||
};
|
||||
|
||||
/**
|
||||
Met a jour la borne a partir des donnees du formulaire
|
||||
*/
|
||||
void TerminalEditor::updateTerminal() {
|
||||
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
|
||||
part -> setOrientation(
|
||||
static_cast<QET::Orientation>(
|
||||
orientation -> itemData(
|
||||
orientation -> currentIndex()
|
||||
).toInt()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse de la position de la borne et cree un objet d'annulation
|
||||
void TerminalEditor::updateTerminalX() { addChangePartCommand(tr("abscisse"), part, "x", qle_x -> text().toDouble()); updateForm(); }
|
||||
/// Met a jour l'ordonnee de la position de la borne et cree un objet d'annulation
|
||||
void TerminalEditor::updateTerminalY() { addChangePartCommand(tr("ordonn\351e"), part, "y", qle_y -> text().toDouble()); updateForm(); }
|
||||
/// Met a jour l'orientation de la borne et cree un objet d'annulation
|
||||
void TerminalEditor::updateTerminalO() { addChangePartCommand(tr("orientation"), part, "orientation", orientation -> itemData(orientation -> currentIndex()).toInt()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void TerminalEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
qle_x -> setText(part -> property("x").toString());
|
||||
qle_y -> setText(part -> property("y").toString());
|
||||
orientation -> setCurrentIndex(static_cast<int>(part -> orientation()));
|
||||
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 TerminalEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTerminalX()));
|
||||
connect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTerminalY()));
|
||||
connect(orientation, SIGNAL(activated(int)), this, SLOT(updateTerminalO()));
|
||||
} else {
|
||||
disconnect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTerminalX()));
|
||||
disconnect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTerminalY()));
|
||||
disconnect(orientation, SIGNAL(activated(int)), this, SLOT(updateTerminalO()));
|
||||
}
|
||||
}
|
||||
54
sources/editor/terminaleditor.h
Normal file
54
sources/editor/terminaleditor.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 TERMINAL_EDITOR_H
|
||||
#define TERMINAL_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartTerminal;
|
||||
/**
|
||||
Cette classe represente un editeur de borne.
|
||||
Elle permet d'editer a travers une interface graphique les
|
||||
proprietes d'une borne d'element.
|
||||
*/
|
||||
class TerminalEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
TerminalEditor(QETElementEditor *, PartTerminal *, QWidget * = 0);
|
||||
virtual ~TerminalEditor();
|
||||
private:
|
||||
TerminalEditor(const TerminalEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartTerminal *part;
|
||||
QLineEdit *qle_x, *qle_y;
|
||||
QComboBox *orientation;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateTerminal();
|
||||
void updateTerminalX();
|
||||
void updateTerminalY();
|
||||
void updateTerminalO();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
112
sources/editor/texteditor.cpp
Normal file
112
sources/editor/texteditor.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "texteditor.h"
|
||||
#include "parttext.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param text Champ de texte a editer
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
TextEditor::TextEditor(QETElementEditor *editor, PartText *text, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
part = text;
|
||||
|
||||
qle_x = new QLineEdit();
|
||||
qle_y = new QLineEdit();
|
||||
qle_text = new QLineEdit();
|
||||
font_size = new QSpinBox();
|
||||
font_size -> setRange(0, 144);
|
||||
|
||||
qle_x -> setValidator(new QDoubleValidator(qle_x));
|
||||
qle_y -> setValidator(new QDoubleValidator(qle_y));
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout();
|
||||
main_layout -> addWidget(new QLabel(tr("Position : ")));
|
||||
|
||||
QHBoxLayout *position = new QHBoxLayout();
|
||||
position -> addWidget(new QLabel(tr("x : ")));
|
||||
position -> addWidget(qle_x );
|
||||
position -> addWidget(new QLabel(tr("y : ")));
|
||||
position -> addWidget(qle_y );
|
||||
main_layout -> addLayout(position);
|
||||
|
||||
QHBoxLayout *fs = new QHBoxLayout();
|
||||
fs -> addWidget(new QLabel(tr("Taille : ")));
|
||||
fs -> addWidget(font_size);
|
||||
main_layout -> addLayout(fs);
|
||||
|
||||
QHBoxLayout *t = new QHBoxLayout();
|
||||
t -> addWidget(new QLabel(tr("Texte : ")));
|
||||
t -> addWidget(qle_text);
|
||||
main_layout -> addLayout(t);
|
||||
main_layout -> addStretch();
|
||||
setLayout(main_layout);
|
||||
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
TextEditor::~TextEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le champ de texte a partir des donnees du formulaire
|
||||
*/
|
||||
void TextEditor::updateText() {
|
||||
part -> setProperty("size", font_size -> value());
|
||||
part -> setPlainText(qle_text -> text());
|
||||
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse de la position du texte et cree un objet d'annulation
|
||||
void TextEditor::updateTextX() { addChangePartCommand(tr("abscisse"), part, "x", qle_x -> text().toDouble()); updateForm(); }
|
||||
/// 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()); }
|
||||
/// Met a jour la taille du texte et cree un objet d'annulation
|
||||
void TextEditor::updateTextS() { addChangePartCommand(tr("taille"), part, "size", font_size -> value()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire a partir du champ de texte
|
||||
*/
|
||||
void TextEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
qle_x -> setText(part -> property("x").toString());
|
||||
qle_y -> setText(part -> property("y").toString());
|
||||
qle_text -> setText(part -> property("text").toString());
|
||||
font_size -> setValue(part -> property("size").toInt());
|
||||
activeConnections(true);
|
||||
}
|
||||
|
||||
void TextEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextX()));
|
||||
connect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextY()));
|
||||
connect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextT()));
|
||||
connect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextS()));
|
||||
} else {
|
||||
disconnect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextX()));
|
||||
disconnect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextY()));
|
||||
disconnect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextT()));
|
||||
disconnect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextS()));
|
||||
}
|
||||
}
|
||||
55
sources/editor/texteditor.h
Normal file
55
sources/editor/texteditor.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 TEXT_EDITOR_H
|
||||
#define TEXT_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartText;
|
||||
/**
|
||||
Cette classe represente un editeur de champ de texte non editable
|
||||
Elle permet d'editer a travers une interface graphique les
|
||||
proprietes d'un champ de texte non editable.
|
||||
*/
|
||||
class TextEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
TextEditor(QETElementEditor *, PartText *, QWidget * = 0);
|
||||
virtual ~TextEditor();
|
||||
private:
|
||||
TextEditor(const TextEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartText *part;
|
||||
QLineEdit *qle_x, *qle_y, *qle_text;
|
||||
QSpinBox *font_size;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateText();
|
||||
void updateTextX();
|
||||
void updateTextY();
|
||||
void updateTextT();
|
||||
void updateTextS();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
126
sources/editor/textfieldeditor.cpp
Normal file
126
sources/editor/textfieldeditor.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 "textfieldeditor.h"
|
||||
#include "parttextfield.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param editor L'editeur d'element concerne
|
||||
@param textfield Le champ de texte a editer
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
TextFieldEditor::TextFieldEditor(QETElementEditor *editor, PartTextField *textfield, QWidget *parent) : ElementItemEditor(editor, parent) {
|
||||
part = textfield;
|
||||
|
||||
qle_x = new QLineEdit();
|
||||
qle_y = new QLineEdit();
|
||||
qle_text = new QLineEdit();
|
||||
font_size = new QSpinBox();
|
||||
font_size -> setRange(0, 144);
|
||||
rotate = new QCheckBox(tr("Maintenir horizontal malgr\351\n les rotations de l'\351l\351ment"));
|
||||
rotate -> setChecked(true);
|
||||
|
||||
qle_x -> setValidator(new QDoubleValidator(qle_x));
|
||||
qle_y -> setValidator(new QDoubleValidator(qle_y));
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout();
|
||||
main_layout -> addWidget(new QLabel(tr("Position : ")));
|
||||
|
||||
QHBoxLayout *position = new QHBoxLayout();
|
||||
position -> addWidget(new QLabel(tr("x : ")));
|
||||
position -> addWidget(qle_x );
|
||||
position -> addWidget(new QLabel(tr("y : ")));
|
||||
position -> addWidget(qle_y );
|
||||
main_layout -> addLayout(position);
|
||||
|
||||
QHBoxLayout *fs = new QHBoxLayout();
|
||||
fs -> addWidget(new QLabel(tr("Taille : ")));
|
||||
fs -> addWidget(font_size);
|
||||
main_layout -> addLayout(fs);
|
||||
|
||||
QHBoxLayout *t = new QHBoxLayout();
|
||||
t -> addWidget(new QLabel(tr("Texte par d\351faut : ")));
|
||||
t -> addWidget(qle_text);
|
||||
main_layout -> addLayout(t);
|
||||
|
||||
QHBoxLayout *r = new QHBoxLayout();
|
||||
r -> addWidget(rotate);
|
||||
main_layout -> addLayout(r);
|
||||
|
||||
main_layout -> addStretch();
|
||||
setLayout(main_layout);
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
TextFieldEditor::~TextFieldEditor() {
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour le champ de texte a partir des donnees du formulaire
|
||||
*/
|
||||
void TextFieldEditor::updateTextField() {
|
||||
part -> setProperty("size", font_size -> value());
|
||||
part -> setPlainText(qle_text -> text());
|
||||
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
|
||||
part -> setFollowParentRotations(!rotate -> isChecked());
|
||||
}
|
||||
|
||||
/// Met a jour l'abscisse de la position du champ de texte et cree un objet d'annulation
|
||||
void TextFieldEditor::updateTextFieldX() { addChangePartCommand(tr("abscisse"), part, "x", qle_x -> text().toDouble()); updateForm(); }
|
||||
/// 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()); }
|
||||
/// 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
|
||||
void TextFieldEditor::updateTextFieldR() { addChangePartCommand(tr("propri\351t\351"), part, "rotate", !rotate -> isChecked()); }
|
||||
|
||||
/**
|
||||
Met a jour le formulaire d'edition
|
||||
*/
|
||||
void TextFieldEditor::updateForm() {
|
||||
activeConnections(false);
|
||||
qle_x -> setText(part -> property("x").toString());
|
||||
qle_y -> setText(part -> property("y").toString());
|
||||
qle_text -> setText(part -> property("text").toString());
|
||||
font_size -> setValue(part -> property("size").toInt());
|
||||
rotate -> setChecked(!part -> property("rotate").toBool());
|
||||
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 TextFieldEditor::activeConnections(bool active) {
|
||||
if (active) {
|
||||
connect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextFieldX()));
|
||||
connect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextFieldY()));
|
||||
connect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextFieldT()));
|
||||
connect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextFieldS()));
|
||||
connect(rotate, SIGNAL(stateChanged(int)), this, SLOT(updateTextFieldR()));
|
||||
} else {
|
||||
disconnect(qle_x, SIGNAL(editingFinished()), this, SLOT(updateTextFieldX()));
|
||||
disconnect(qle_y, SIGNAL(editingFinished()), this, SLOT(updateTextFieldY()));
|
||||
disconnect(qle_text, SIGNAL(editingFinished()), this, SLOT(updateTextFieldT()));
|
||||
disconnect(font_size, SIGNAL(editingFinished()), this, SLOT(updateTextFieldS()));
|
||||
disconnect(rotate, SIGNAL(stateChanged(int)), this, SLOT(updateTextFieldR()));
|
||||
}
|
||||
}
|
||||
58
sources/editor/textfieldeditor.h
Normal file
58
sources/editor/textfieldeditor.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2006-2007 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 TEXTFIELD_EDITOR_H
|
||||
#define TEXTFIELD_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "elementitemeditor.h"
|
||||
class PartTextField;
|
||||
/**
|
||||
Cette classe represente un editeur de champ de texte
|
||||
Elle permet d'editer a travers une interface graphique les
|
||||
proprietes d'un champ de texte : taille de la police, texte par
|
||||
defaut et position.
|
||||
*/
|
||||
class TextFieldEditor : public ElementItemEditor {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
TextFieldEditor(QETElementEditor *, PartTextField *, QWidget * = 0);
|
||||
virtual ~TextFieldEditor();
|
||||
private:
|
||||
TextFieldEditor(const TextFieldEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartTextField *part;
|
||||
QLineEdit *qle_x, *qle_y, *qle_text;
|
||||
QSpinBox *font_size;
|
||||
QCheckBox *rotate;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateTextField();
|
||||
void updateTextFieldX();
|
||||
void updateTextFieldY();
|
||||
void updateTextFieldT();
|
||||
void updateTextFieldS();
|
||||
void updateTextFieldR();
|
||||
void updateForm();
|
||||
|
||||
private:
|
||||
void activeConnections(bool);
|
||||
};
|
||||
#endif
|
||||
472
sources/element.cpp
Normal file
472
sources/element.cpp
Normal file
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "element.h"
|
||||
#include "qetapp.h"
|
||||
#include "diagram.h"
|
||||
#include "conductor.h"
|
||||
#include "elementtextitem.h"
|
||||
#include "diagramcommands.h"
|
||||
#include <QtDebug>
|
||||
|
||||
/**
|
||||
Constructeur pour un element sans scene ni parent
|
||||
*/
|
||||
Element::Element(QGraphicsItem *parent, Diagram *scene) :
|
||||
QObject(),
|
||||
QGraphicsItem(parent, scene),
|
||||
internal_connections(false)
|
||||
{
|
||||
setZValue(10);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
Element::~Element() {
|
||||
}
|
||||
|
||||
/**
|
||||
Methode principale de dessin de l'element
|
||||
@param painter Le QPainter utilise pour dessiner l'elment
|
||||
@param options Les options de style a prendre en compte
|
||||
@param widget Le widget sur lequel on dessine
|
||||
*/
|
||||
void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) {
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
// corrige un bug de rendu ne se produisant que lors du rendu sur QGraphicsScene sous X11 au zoom par defaut
|
||||
static bool must_correct_rendering_bug = QETApp::settings().value("correct-rendering", true).toBool();
|
||||
if (must_correct_rendering_bug) {
|
||||
Diagram *dia = diagram();
|
||||
if (dia && options -> levelOfDetail == 1.0 && widget) {
|
||||
// calcule la rotation qu'a subi l'element
|
||||
qreal applied_rotation = 90.0 * (ori.current() - ori.defaultOrientation());
|
||||
while (applied_rotation < 360.0) applied_rotation += 360.0;
|
||||
while (applied_rotation > 360.0) applied_rotation -= 360.0;
|
||||
if (applied_rotation == 90.0) painter -> translate(1.0, -1.0);
|
||||
else if (applied_rotation == 180.0) painter -> translate(-1.0, -1.0);
|
||||
else if (applied_rotation == 270.0) painter -> translate(-1.0, 1.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Dessin de l'element lui-meme
|
||||
paint(painter, options);
|
||||
|
||||
// Dessin du cadre de selection si necessaire
|
||||
if (isSelected()) drawSelection(painter, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le rectangle delimitant le contour de l'element
|
||||
*/
|
||||
QRectF Element::boundingRect() const {
|
||||
return(QRectF(QPointF(-hotspot_coord.x(), -hotspot_coord.y()), dimensions));
|
||||
}
|
||||
|
||||
/**
|
||||
Definit la taille de l'element sur le schema. Les tailles doivent etre
|
||||
des multiples de 10 ; si ce n'est pas le cas, les dimensions indiquees
|
||||
seront arrrondies aux dizaines superieures.
|
||||
@param wid Largeur de l'element
|
||||
@param hei Hauteur de l'element
|
||||
@return La taille finale de l'element
|
||||
*/
|
||||
QSize Element::setSize(int wid, int hei) {
|
||||
prepareGeometryChange();
|
||||
// chaque dimension indiquee est arrondie a la dizaine superieure
|
||||
while (wid % 10) ++ wid;
|
||||
while (hei % 10) ++ hei;
|
||||
// les dimensions finales sont conservees et retournees
|
||||
return(dimensions = QSize(wid, hei));
|
||||
}
|
||||
|
||||
/**
|
||||
Definit le hotspot de l'element par rapport au coin superieur gauche de son rectangle delimitant.
|
||||
Necessite que la taille ait deja ete definie
|
||||
@param hs Coordonnees du hotspot
|
||||
*/
|
||||
QPoint Element::setHotspot(QPoint hs) {
|
||||
// la taille doit avoir ete definie
|
||||
prepareGeometryChange();
|
||||
if (dimensions.isNull()) hotspot_coord = QPoint(0, 0);
|
||||
else {
|
||||
// les coordonnees indiquees ne doivent pas depasser les dimensions de l'element
|
||||
int hsx = qMin(hs.x(), dimensions.width());
|
||||
int hsy = qMin(hs.y(), dimensions.height());
|
||||
hotspot_coord = QPoint(hsx, hsy);
|
||||
}
|
||||
return(hotspot_coord);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le hotspot courant de l'element
|
||||
*/
|
||||
QPoint Element::hotspot() const {
|
||||
return(hotspot_coord);
|
||||
}
|
||||
|
||||
/**
|
||||
Selectionne l'element
|
||||
*/
|
||||
void Element::select() {
|
||||
setSelected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Deselectionne l'element
|
||||
*/
|
||||
void Element::deselect() {
|
||||
setSelected(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de specifier l'orientation de l'element
|
||||
@param o la nouvelle orientation de l'objet
|
||||
@return true si l'orientation a pu etre appliquee, false sinon
|
||||
*/
|
||||
bool Element::setOrientation(QET::Orientation o) {
|
||||
// verifie que l'orientation demandee est acceptee
|
||||
if (!ori.accept(o)) return(false);
|
||||
prepareGeometryChange();
|
||||
// rotation en consequence et rafraichissement de l'element graphique
|
||||
qreal rotation_value = 90.0 * (o - ori.current());
|
||||
rotate(rotation_value);
|
||||
ori.setCurrent(o);
|
||||
update();
|
||||
foreach(QGraphicsItem *qgi, childItems()) {
|
||||
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) p -> updateConductor();
|
||||
else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(qgi)) {
|
||||
// applique une rotation contraire si besoin
|
||||
if (!eti -> followParentRotations()) {
|
||||
QMatrix new_matrix = eti -> matrix();
|
||||
qreal dx = eti -> boundingRect().width() / 2.0;
|
||||
qreal dy = eti -> boundingRect().height() / 2.0;
|
||||
new_matrix.translate(dx, dy);
|
||||
new_matrix.rotate(-rotation_value);
|
||||
new_matrix.translate(-dx, -dy);
|
||||
eti -> setMatrix(new_matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*** Methodes protegees ***/
|
||||
|
||||
/**
|
||||
Dessine un petit repere (axes x et y) relatif a l'element
|
||||
@param painter Le QPainter a utiliser pour dessiner les axes
|
||||
@param options Les options de style a prendre en compte
|
||||
*/
|
||||
void Element::drawAxes(QPainter *painter, const QStyleOptionGraphicsItem *) {
|
||||
painter -> setPen(Qt::blue);
|
||||
painter -> drawLine(0, 0, 10, 0);
|
||||
painter -> drawLine(7,-3, 10, 0);
|
||||
painter -> drawLine(7, 3, 10, 0);
|
||||
painter -> setPen(Qt::red);
|
||||
painter -> drawLine(0, 0, 0, 10);
|
||||
painter -> drawLine(0, 10,-3, 7);
|
||||
painter -> drawLine(0, 10, 3, 7);
|
||||
}
|
||||
|
||||
/*** Methodes privees ***/
|
||||
|
||||
/**
|
||||
Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee.
|
||||
@param qp Le QPainter a utiliser pour dessiner les bornes.
|
||||
@param options Les options de style a prendre en compte
|
||||
*/
|
||||
void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *) {
|
||||
painter -> save();
|
||||
// Annulation des renderhints
|
||||
painter -> setRenderHint(QPainter::Antialiasing, false);
|
||||
painter -> setRenderHint(QPainter::TextAntialiasing, false);
|
||||
painter -> setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
// Dessin du cadre de selection en gris
|
||||
QPen t;
|
||||
t.setColor(Qt::gray);
|
||||
t.setStyle(Qt::DashDotLine);
|
||||
painter -> setPen(t);
|
||||
// Le dessin se fait a partir du rectangle delimitant
|
||||
painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10);
|
||||
painter -> restore();
|
||||
}
|
||||
|
||||
/**
|
||||
Fonction initialisant et dessinant la pixmap de l'element.
|
||||
*/
|
||||
void Element::updatePixmap() {
|
||||
// Pixmap transparente faisant la taille de base de l'element
|
||||
apercu = QPixmap(dimensions);
|
||||
apercu.fill(QColor(255, 255, 255, 0));
|
||||
// QPainter sur la pixmap, avec antialiasing
|
||||
QPainter p(&apercu);
|
||||
p.setRenderHint(QPainter::Antialiasing, true);
|
||||
p.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||
// Translation de l'origine du repere de la pixmap
|
||||
p.translate(hotspot_coord);
|
||||
// L'element se dessine sur la pixmap
|
||||
paint(&p, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position de l'element en veillant a ce que l'element
|
||||
reste sur la grille du Diagram auquel il appartient.
|
||||
@param p Nouvelles coordonnees de l'element
|
||||
*/
|
||||
void Element::setPos(const QPointF &p) {
|
||||
if (p == pos()) return;
|
||||
// pas la peine de positionner sur la grille si l'element n'est pas sur un Diagram
|
||||
if (scene()) {
|
||||
// arrondit l'abscisse a 10 px pres
|
||||
int p_x = qRound(p.x() / (Diagram::xGrid * 1.0)) * Diagram::xGrid;
|
||||
// arrondit l'ordonnee a 10 px pres
|
||||
int p_y = qRound(p.y() / (Diagram::yGrid * 1.0)) * Diagram::yGrid;
|
||||
QGraphicsItem::setPos(p_x, p_y);
|
||||
} else QGraphicsItem::setPos(p);
|
||||
}
|
||||
|
||||
/**
|
||||
Change la position de l'element en veillant a ce que l'element
|
||||
reste sur la grille du Diagram auquel il appartient.
|
||||
@param x Nouvelle abscisse de l'element
|
||||
@param y Nouvelle ordonnee de l'element
|
||||
*/
|
||||
void Element::setPos(qreal x, qreal y) {
|
||||
setPos(QPointF(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
Gere l'enfoncement d'un bouton de la souris
|
||||
*/
|
||||
void Element::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (!isSelected() && e -> modifiers() & Qt::ControlModifier) {
|
||||
setSelected(true);
|
||||
}
|
||||
QGraphicsItem::mousePressEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere les mouvements de souris lies a l'element
|
||||
*/
|
||||
void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (isSelected() && e -> buttons() & Qt::LeftButton) {
|
||||
QPointF oldPos = pos();
|
||||
setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton)));
|
||||
if (Diagram *diagram_ptr = diagram()) {
|
||||
diagram_ptr -> moveElements(pos() - oldPos, this);
|
||||
}
|
||||
} else e -> ignore();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le relachement de souris
|
||||
Cette methode a ete reimplementee pour tenir a jour la liste des elements
|
||||
et conducteurs a deplacer au niveau du schema.
|
||||
*/
|
||||
void Element::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
Diagram *diagram_ptr = diagram();
|
||||
if (diagram_ptr) {
|
||||
if (!diagram_ptr -> current_movement.isNull()) {
|
||||
diagram_ptr -> undoStack().push(
|
||||
new MoveElementsCommand(
|
||||
diagram_ptr,
|
||||
diagram_ptr -> selectedContent(),
|
||||
diagram_ptr -> current_movement
|
||||
)
|
||||
);
|
||||
diagram_ptr -> current_movement = QPointF();
|
||||
}
|
||||
diagram_ptr -> invalidateMovedElements();
|
||||
}
|
||||
QGraphicsItem::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si un element XML (QDomElement) represente bien un element
|
||||
@param e Le QDomElement a valide
|
||||
@return true si l'element XML est un Element, false sinon
|
||||
*/
|
||||
bool Element::valideXml(QDomElement &e) {
|
||||
// verifie le nom du tag
|
||||
if (e.tagName() != "element") return(false);
|
||||
|
||||
// verifie la presence des attributs minimaux
|
||||
if (!e.hasAttribute("type")) return(false);
|
||||
if (!e.hasAttribute("x")) return(false);
|
||||
if (!e.hasAttribute("y")) return(false);
|
||||
|
||||
bool conv_ok;
|
||||
// parse l'abscisse
|
||||
e.attribute("x").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
|
||||
// parse l'ordonnee
|
||||
e.attribute("y").toDouble(&conv_ok);
|
||||
if (!conv_ok) return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode d'import XML. Cette methode est appelee lors de l'import de contenu
|
||||
XML (coller, import, ouverture de fichier...) afin que l'element puisse
|
||||
gerer lui-meme l'importation de ses bornes. Ici, comme cette classe est
|
||||
caracterisee par un nombre fixe de bornes, l'implementation exige de
|
||||
retrouver exactement ses bornes dans le fichier XML.
|
||||
@param e L'element XML a analyser.
|
||||
@param table_id_adr Reference vers la table de correspondance entre les IDs
|
||||
du fichier XML et les adresses en memoire. Si l'import reussit, il faut y
|
||||
ajouter les bons couples (id, adresse).
|
||||
@return true si l'import a reussi, false sinon
|
||||
|
||||
*/
|
||||
bool Element::fromXml(QDomElement &e, QHash<int, Terminal *> &table_id_adr) {
|
||||
/*
|
||||
les bornes vont maintenant etre recensees pour associer leurs id a leur adresse reelle
|
||||
ce recensement servira lors de la mise en place des fils
|
||||
*/
|
||||
QList<QDomElement> liste_terminals;
|
||||
foreach(QDomElement qde, QET::findInDomElement(e, "terminals", "terminal")) {
|
||||
if (Terminal::valideXml(qde)) liste_terminals << qde;
|
||||
}
|
||||
|
||||
QHash<int, Terminal *> priv_id_adr;
|
||||
int terminals_non_trouvees = 0;
|
||||
foreach(QGraphicsItem *qgi, childItems()) {
|
||||
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) {
|
||||
bool terminal_trouvee = false;
|
||||
foreach(QDomElement qde, liste_terminals) {
|
||||
if (p -> fromXml(qde)) {
|
||||
priv_id_adr.insert(qde.attribute("id").toInt(), p);
|
||||
terminal_trouvee = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!terminal_trouvee) ++ terminals_non_trouvees;
|
||||
}
|
||||
}
|
||||
|
||||
if (terminals_non_trouvees > 0) {
|
||||
return(false);
|
||||
} else {
|
||||
// verifie que les associations id / adr n'entrent pas en conflit avec table_id_adr
|
||||
foreach(int id_trouve, priv_id_adr.keys()) {
|
||||
if (table_id_adr.contains(id_trouve)) {
|
||||
// cet element possede un id qui est deja reference (= conflit)
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
// copie des associations id / adr
|
||||
foreach(int id_trouve, priv_id_adr.keys()) {
|
||||
table_id_adr.insert(id_trouve, priv_id_adr.value(id_trouve));
|
||||
}
|
||||
}
|
||||
|
||||
// importe les valeurs des champs de texte
|
||||
QList<QDomElement> inputs = QET::findInDomElement(e, "inputs", "input");
|
||||
foreach(QGraphicsItem *qgi, childItems()) {
|
||||
if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(qgi)) {
|
||||
foreach(QDomElement input, inputs) eti -> fromXml(input);
|
||||
}
|
||||
}
|
||||
|
||||
// position, selection et orientation
|
||||
setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble());
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
bool conv_ok;
|
||||
int read_ori = e.attribute("orientation").toInt(&conv_ok);
|
||||
if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = ori.defaultOrientation();
|
||||
setOrientation((QET::Orientation)read_ori);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet d'exporter l'element en XML
|
||||
@param document Document XML a utiliser
|
||||
@param table_adr_id Table de correspondance entre les adresses des bornes
|
||||
et leur id dans la representation XML ; cette table completee par cette
|
||||
methode
|
||||
@return L'element XML representant cet element electrique
|
||||
*/
|
||||
QDomElement Element::toXml(QDomDocument &document, QHash<Terminal *, int> &table_adr_id) const {
|
||||
QDomElement element = document.createElement("element");
|
||||
|
||||
// type
|
||||
QString chemin_elmt = typeId();
|
||||
QString type_elmt = QETApp::symbolicPath(chemin_elmt);
|
||||
element.setAttribute("type", type_elmt);
|
||||
|
||||
// position, selection et orientation
|
||||
element.setAttribute("x", pos().x());
|
||||
element.setAttribute("y", pos().y());
|
||||
element.setAttribute("orientation", QString("%1").arg(ori.current()));
|
||||
|
||||
/* recupere le premier id a utiliser pour les bornes de cet element */
|
||||
int id_terminal = 0;
|
||||
if (!table_adr_id.isEmpty()) {
|
||||
// trouve le plus grand id
|
||||
int max_id_t = -1;
|
||||
foreach (int id_t, table_adr_id.values()) {
|
||||
if (id_t > max_id_t) max_id_t = id_t;
|
||||
}
|
||||
id_terminal = max_id_t + 1;
|
||||
}
|
||||
|
||||
// enregistrement des bornes de l'appareil
|
||||
QDomElement terminals = document.createElement("terminals");
|
||||
// pour chaque enfant de l'element
|
||||
foreach(QGraphicsItem *child, childItems()) {
|
||||
// si cet enfant est une borne
|
||||
if (Terminal *t = qgraphicsitem_cast<Terminal *>(child)) {
|
||||
// alors on enregistre la borne
|
||||
QDomElement terminal = t -> toXml(document);
|
||||
terminal.setAttribute("id", id_terminal);
|
||||
table_adr_id.insert(t, id_terminal ++);
|
||||
terminals.appendChild(terminal);
|
||||
}
|
||||
}
|
||||
element.appendChild(terminals);
|
||||
|
||||
// enregistrement des champ de texte de l'appareil
|
||||
QDomElement inputs = document.createElement("inputs");
|
||||
// pour chaque enfant de l'element
|
||||
foreach(QGraphicsItem *child, childItems()) {
|
||||
// si cet enfant est un champ de texte
|
||||
if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(child)) {
|
||||
// alors on enregistre le champ de texte
|
||||
inputs.appendChild(eti -> toXml(document));
|
||||
}
|
||||
}
|
||||
element.appendChild(inputs);
|
||||
|
||||
return(element);
|
||||
}
|
||||
|
||||
/// @return le Diagram auquel cet element appartient, ou 0 si cet element est independant
|
||||
Diagram *Element::diagram() const {
|
||||
return(qobject_cast<Diagram *>(scene()));
|
||||
}
|
||||
156
sources/element.h
Normal file
156
sources/element.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2006-2008 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_H
|
||||
#define ELEMENT_H
|
||||
#include <QtGui>
|
||||
#include "terminal.h"
|
||||
#include "orientationset.h"
|
||||
class Diagram;
|
||||
/**
|
||||
Cette classe abstraite represente un element electrique.
|
||||
*/
|
||||
class Element : public QObject, public QGraphicsItem {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
Element(QGraphicsItem * = 0, Diagram * = 0);
|
||||
virtual ~Element();
|
||||
|
||||
private:
|
||||
Element(const Element &);
|
||||
|
||||
// attributs
|
||||
public:
|
||||
enum { Type = UserType + 1000 };
|
||||
|
||||
protected:
|
||||
/**
|
||||
orientations de l'element :
|
||||
* autorisations
|
||||
* orientation en cours
|
||||
* orientation par defaut
|
||||
@see OrientationSet
|
||||
*/
|
||||
OrientationSet ori;
|
||||
|
||||
private:
|
||||
QSize dimensions;
|
||||
QPoint hotspot_coord;
|
||||
QPixmap apercu;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
/**
|
||||
permet de caster un QGraphicsItem en Element avec qgraphicsitem_cast
|
||||
@return le type de QGraphicsItem
|
||||
*/
|
||||
virtual int type() const { return Type; }
|
||||
|
||||
// methodes virtuelles pures a definir dans les classes enfants
|
||||
/// @return la liste des bornes de cet element
|
||||
virtual QList<Terminal *> terminals() const = 0;
|
||||
/// @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;
|
||||
/// @return le nombre de bornes minimum de cet element
|
||||
virtual int nbTerminalsMin() const = 0;
|
||||
/// @return le nombre de bornes maximum de cet element
|
||||
virtual int nbTerminalsMax() const = 0;
|
||||
/**
|
||||
Dessine l'element
|
||||
*/
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0;
|
||||
/// @return L'ID du type de l'element
|
||||
virtual QString typeId() const = 0;
|
||||
/// @return Le nom de l'element
|
||||
virtual QString nom() const = 0;
|
||||
Diagram *diagram() const;
|
||||
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
QRectF boundingRect() const;
|
||||
QSize setSize(int, int);
|
||||
QPixmap pixmap();
|
||||
|
||||
// methodes relatives au point de saisie
|
||||
QPoint setHotspot(QPoint);
|
||||
QPoint hotspot() const;
|
||||
|
||||
// methodes relatives a la selection
|
||||
void select();
|
||||
void deselect();
|
||||
|
||||
// methodes relatives a la position
|
||||
void setPos(const QPointF &);
|
||||
void setPos(qreal, qreal);
|
||||
|
||||
// methodes relatives aux connexions internes
|
||||
bool internalConnections();
|
||||
void setInternalConnections(bool);
|
||||
|
||||
// methodes relatives aux fichiers XML
|
||||
static bool valideXml(QDomElement &);
|
||||
virtual bool fromXml(QDomElement &, QHash<int, Terminal *> &);
|
||||
virtual QDomElement toXml(QDomDocument &, QHash<Terminal *, int> &) const;
|
||||
|
||||
// methodes d'acces aux possibilites d'orientation
|
||||
bool setOrientation(QET::Orientation o);
|
||||
const OrientationSet &orientation() const;
|
||||
|
||||
protected:
|
||||
void drawAxes(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
|
||||
|
||||
private:
|
||||
bool internal_connections;
|
||||
void drawSelection(QPainter *, const QStyleOptionGraphicsItem *);
|
||||
void updatePixmap();
|
||||
};
|
||||
|
||||
/**
|
||||
Permet de savoir si l'element accepte les connexions internes,
|
||||
c'est-a-dire que ses bornes peuvent etre reliees entre elles
|
||||
@return true si l'element accepte les connexions internes, false sinon
|
||||
*/
|
||||
inline bool Element::internalConnections() {
|
||||
return(internal_connections);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de specifier si l'element accepte les connexions internes,
|
||||
c'est-a-dire que ses bornes peuvent etre reliees entre elles
|
||||
@param ic true pour que l'element accepte les connexions internes, false pour
|
||||
qu'il les interdise
|
||||
*/
|
||||
inline void Element::setInternalConnections(bool ic) {
|
||||
internal_connections = ic;
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de connaitre l'orientation actuelle de l'element
|
||||
@return L'orientation actuelle de l'element
|
||||
*/
|
||||
inline const OrientationSet & Element::orientation() const {
|
||||
return(ori);
|
||||
}
|
||||
|
||||
#endif
|
||||
62
sources/elementdeleter.cpp
Normal file
62
sources/elementdeleter.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementdeleter.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param elmt_path Chemin du fichier representant l'element a supprimer
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ElementDeleter::ElementDeleter(const QString &elmt_path, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
element_path(elmt_path)
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
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() {
|
||||
// verifie l'existence de l'element
|
||||
QFile elmt_file(element_path);
|
||||
if (!elmt_file.exists()) return;
|
||||
|
||||
// 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
|
||||
);
|
||||
if (answer_1 != QMessageBox::Yes) return;
|
||||
|
||||
// supprime l'element
|
||||
if (!elmt_file.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(".")
|
||||
);
|
||||
}
|
||||
}
|
||||
44
sources/elementdeleter.h
Normal file
44
sources/elementdeleter.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2006-2008 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_DELETER_H
|
||||
#define ELEMENT_DELETER_H
|
||||
#include "elementscategory.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
|
||||
*/
|
||||
class ElementDeleter : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementDeleter(const QString &, QWidget * = 0);
|
||||
virtual ~ElementDeleter();
|
||||
private:
|
||||
ElementDeleter(const ElementsCategory &);
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void exec();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QString element_path;
|
||||
};
|
||||
#endif
|
||||
107
sources/elementscategorieslist.cpp
Normal file
107
sources/elementscategorieslist.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 <QtXml>
|
||||
#include "elementscategorieslist.h"
|
||||
#include "qetapp.h"
|
||||
#include "elementscategory.h"
|
||||
#include "qetdiagrameditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
ElementsCategoriesList::ElementsCategoriesList(QWidget *parent) : QTreeWidget(parent) {
|
||||
// selection unique
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
setColumnCount(1);
|
||||
header() -> hide();
|
||||
|
||||
// charge les categories
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsCategoriesList::~ElementsCategoriesList() {
|
||||
}
|
||||
|
||||
/**
|
||||
Recharge l'arbre des categories
|
||||
*/
|
||||
void ElementsCategoriesList::reload() {
|
||||
// vide l'arbre
|
||||
while (takeTopLevelItem(0)) {};
|
||||
|
||||
// chargement des elements de la collection commune si droits d'ecriture
|
||||
QFileInfo common_collection_info(QETApp::commonElementsDir());
|
||||
if (
|
||||
common_collection_info.exists() &&
|
||||
common_collection_info.isDir() &&
|
||||
common_collection_info.isWritable()
|
||||
) {
|
||||
addDir(invisibleRootItem(), QETApp::commonElementsDir(), tr("Collection QET"));
|
||||
}
|
||||
|
||||
// chargement des elements de la collection utilisateur
|
||||
addDir(invisibleRootItem(), QETApp::customElementsDir(), tr("Collection utilisateur"));
|
||||
}
|
||||
|
||||
/**
|
||||
Methode privee permettant d'ajouter un dossier au panel d'appareils
|
||||
@param qtwi_parent QTreeWidgetItem parent sous lequel sera insere l'element
|
||||
@param dossier Chemin absolu du dossier a inserer
|
||||
@param nom Parametre facultatif permettant de forcer le nom du dossier.
|
||||
S'il n'est pas precise, la fonction ouvre le fichier qet_directory situe
|
||||
dans le dossier et y lit le nom du dossier ; si ce fichier n'existe pas ou
|
||||
est invalide, la fonction utilise le nom du dossier.
|
||||
*/
|
||||
void ElementsCategoriesList::addDir(QTreeWidgetItem *qtwi_parent, QString adr_dossier, QString nom) {
|
||||
ElementsCategory category(adr_dossier);
|
||||
if (!category.exists()) return;
|
||||
|
||||
// recupere le nom de la categorie
|
||||
QString nom_categorie = (nom != QString()) ? nom : category.name();
|
||||
|
||||
// creation du QTreeWidgetItem representant le dossier
|
||||
QTreeWidgetItem *qtwi_dossier = new QTreeWidgetItem(qtwi_parent, QStringList(nom_categorie));
|
||||
qtwi_dossier -> setData(0, Qt::UserRole, category.absolutePath());
|
||||
qtwi_dossier -> setExpanded(true);
|
||||
|
||||
// ajout des sous-categories / sous-dossiers
|
||||
QStringList dossiers = category.entryList(QStringList(), QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::Name);
|
||||
foreach(QString dossier, dossiers) addDir(qtwi_dossier, adr_dossier + dossier + "/");
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le dossier de la categorie selectionnee
|
||||
*/
|
||||
QString ElementsCategoriesList::selectedCategoryPath() {
|
||||
QTreeWidgetItem *qtwi = currentItem();
|
||||
if (qtwi) return(qtwi -> data(0, Qt::UserRole).toString());
|
||||
else return(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@return Le nom de la categorie selecti onnee
|
||||
*/
|
||||
QString ElementsCategoriesList::selectedCategoryName() {
|
||||
QTreeWidgetItem *qtwi = currentItem();
|
||||
if (qtwi) return(qtwi -> data(0, Qt::DisplayRole).toString());
|
||||
else return(NULL);
|
||||
}
|
||||
48
sources/elementscategorieslist.h
Normal file
48
sources/elementscategorieslist.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_CATEGORIES_LIST_H
|
||||
#define ELEMENTS_CATEGORIES_LIST_H
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette classe fournit une liste graphique des categories d'elements de
|
||||
l'utilisateur.
|
||||
*/
|
||||
class ElementsCategoriesList : public QTreeWidget {
|
||||
Q_OBJECT
|
||||
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
ElementsCategoriesList(QWidget * = 0);
|
||||
virtual ~ElementsCategoriesList();
|
||||
|
||||
private:
|
||||
ElementsCategoriesList(const ElementsCategoriesList &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
QString selectedCategoryPath();
|
||||
QString selectedCategoryName();
|
||||
|
||||
private:
|
||||
void addDir(QTreeWidgetItem *, QString, QString = QString());
|
||||
QString categoryName(QDir &);
|
||||
|
||||
public slots:
|
||||
void reload();
|
||||
};
|
||||
#endif
|
||||
117
sources/elementscategorieswidget.cpp
Normal file
117
sources/elementscategorieswidget.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementscategorieswidget.h"
|
||||
#include "elementscategorieslist.h"
|
||||
#include "elementscategoryeditor.h"
|
||||
#include "elementscategorydeleter.h"
|
||||
#include "elementscategory.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent
|
||||
*/
|
||||
ElementsCategoriesWidget::ElementsCategoriesWidget(QWidget *parent) : QWidget(parent) {
|
||||
// initialise la liste des categories
|
||||
elementscategorieslist = new ElementsCategoriesList(this);
|
||||
|
||||
// actions
|
||||
action_reload = new QAction(QIcon(":/ico/reload.png"), tr("Recharger les cat\351gories"), this);
|
||||
action_new = new QAction(QIcon(":/ico/category_new.png"), tr("Nouvelle cat\351gorie"), this);
|
||||
action_open = new QAction(QIcon(":/ico/category_edit.png"), tr("\311diter la cat\351gorie"), this);
|
||||
action_delete = new QAction(QIcon(":/ico/category_delete.png"), tr("Supprimer la cat\351gorie"), this);
|
||||
|
||||
// initialise la barre d'outils
|
||||
toolbar = new QToolBar(this);
|
||||
toolbar -> setMovable(false);
|
||||
toolbar -> addAction(action_reload);
|
||||
toolbar -> addAction(action_new);
|
||||
toolbar -> addAction(action_open);
|
||||
toolbar -> addAction(action_delete);
|
||||
|
||||
connect(action_reload, SIGNAL(triggered()), elementscategorieslist, SLOT(reload()) );
|
||||
connect(action_new, SIGNAL(triggered()), this, SLOT(newCategory()) );
|
||||
connect(action_open, SIGNAL(triggered()), this, SLOT(editCategory()) );
|
||||
connect(action_delete, SIGNAL(triggered()), this, SLOT(removeCategory()));
|
||||
connect(elementscategorieslist, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons()) );
|
||||
|
||||
updateButtons();
|
||||
|
||||
// disposition verticale
|
||||
QVBoxLayout *vlayout = new QVBoxLayout(this);
|
||||
vlayout -> setMargin(0);
|
||||
vlayout -> setSpacing(0);
|
||||
vlayout -> addWidget(toolbar);
|
||||
vlayout -> addWidget(elementscategorieslist);
|
||||
vlayout -> setStretchFactor(elementscategorieslist, 75000);
|
||||
setLayout(vlayout);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsCategoriesWidget::~ElementsCategoriesWidget() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un editeur de categorie en mode "creation de categorie"
|
||||
*/
|
||||
void ElementsCategoriesWidget::newCategory() {
|
||||
QString s_c_path = elementscategorieslist -> selectedCategoryPath();
|
||||
if (s_c_path.isNull()) return;
|
||||
(new ElementsCategoryEditor(s_c_path, false, this)) -> exec();
|
||||
elementscategorieslist -> reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Lance un editeur de categorie en mode "edition de categorie"
|
||||
*/
|
||||
void ElementsCategoriesWidget::editCategory() {
|
||||
QString s_c_path = elementscategorieslist -> selectedCategoryPath();
|
||||
if (s_c_path.isNull()) return;
|
||||
(new ElementsCategoryEditor(s_c_path, true, this)) -> exec();
|
||||
elementscategorieslist -> reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime la categorie selectionnee
|
||||
*/
|
||||
void ElementsCategoriesWidget::removeCategory() {
|
||||
// recupere le chemin de la categorie
|
||||
QString s_c_path = elementscategorieslist -> selectedCategoryPath();
|
||||
|
||||
// supprime la categorie
|
||||
ElementsCategoryDeleter cat_deleter(s_c_path, this);
|
||||
cat_deleter.exec();
|
||||
|
||||
// recharge la liste des categories
|
||||
elementscategorieslist -> reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour l'etat (active / desactive) des boutons en fonction de ce qui
|
||||
est selectionne.
|
||||
*/
|
||||
void ElementsCategoriesWidget::updateButtons() {
|
||||
QList<QTreeWidgetItem *> sel_items = elementscategorieslist -> selectedItems();
|
||||
bool sel_items_empty = !sel_items.isEmpty();
|
||||
bool is_top_lvl_item = sel_items_empty && (elementscategorieslist -> indexOfTopLevelItem(sel_items.at(0)) != -1);
|
||||
action_new -> setEnabled(sel_items_empty);
|
||||
action_open -> setEnabled(sel_items_empty && !is_top_lvl_item);
|
||||
action_delete -> setEnabled(sel_items_empty && !is_top_lvl_item);
|
||||
}
|
||||
65
sources/elementscategorieswidget.h
Normal file
65
sources/elementscategorieswidget.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_CATEGORIES_WIDGET_H
|
||||
#define ELEMENTS_CATEGORIES_WIDGET_H
|
||||
#include <QtGui>
|
||||
class ElementsCategoriesList;
|
||||
/**
|
||||
Cette classe represente un widget integrant la liste des categories
|
||||
de l'utilisteur surplombee de boutons permettant d'ajouter, de modifier
|
||||
ou de supprimer des categories
|
||||
*/
|
||||
class ElementsCategoriesWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
ElementsCategoriesWidget(QWidget * = 0);
|
||||
virtual ~ElementsCategoriesWidget();
|
||||
|
||||
private:
|
||||
ElementsCategoriesWidget(const ElementsCategoriesWidget &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ElementsCategoriesList *elementscategorieslist;
|
||||
QToolBar *toolbar;
|
||||
QAction *action_reload;
|
||||
QAction *action_new;
|
||||
QAction *action_open;
|
||||
QAction *action_delete;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
ElementsCategoriesList &elementsCategoriesList() const;
|
||||
|
||||
public slots:
|
||||
void newCategory();
|
||||
void editCategory();
|
||||
void removeCategory();
|
||||
void updateButtons();
|
||||
};
|
||||
|
||||
/**
|
||||
@return La liste des categories d'elements du widget
|
||||
*/
|
||||
inline ElementsCategoriesList &ElementsCategoriesWidget::elementsCategoriesList() const {
|
||||
return(*elementscategorieslist);
|
||||
}
|
||||
|
||||
#endif
|
||||
171
sources/elementscategory.cpp
Normal file
171
sources/elementscategory.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementscategory.h"
|
||||
#include <QtXml>
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param path Chemin du dossier de la categorie
|
||||
*/
|
||||
ElementsCategory::ElementsCategory(const QString &path) : QDir(path) {
|
||||
if (path != QString()) loadNames();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsCategory::~ElementsCategory() {
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime un repertoire recursivement.
|
||||
@return true si la suppression a reussie, false sinon
|
||||
*/
|
||||
bool ElementsCategory::rmdir(const QString &path) const {
|
||||
QDir directory(path);
|
||||
|
||||
// supprime les dossiers, recursivement
|
||||
foreach (QString file, directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) {
|
||||
if (!rmdir(directory.absolutePath() + "/" + file)) return(false);
|
||||
}
|
||||
|
||||
// supprime les fichiers
|
||||
foreach (QString file, directory.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
|
||||
if (!directory.remove(file)) return(false);
|
||||
}
|
||||
|
||||
// supprime le dossier lui-meme
|
||||
return(directory.rmdir(path));
|
||||
}
|
||||
|
||||
/**
|
||||
Charge la liste des noms possibles pour la categorie
|
||||
*/
|
||||
void ElementsCategory::loadNames() {
|
||||
// repere le chemin du fichier de configuration de la categorie
|
||||
QFile directory_conf(canonicalPath() + "/qet_directory");
|
||||
|
||||
// verifie l'existence du fichier
|
||||
if (!directory_conf.exists()) return;
|
||||
|
||||
// ouvre le fichier
|
||||
if (!directory_conf.open(QIODevice::ReadOnly | QIODevice::Text)) return;
|
||||
|
||||
// lit le contenu du fichier dans un QDomDocument XML
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&directory_conf)) return;
|
||||
|
||||
// verifie la racine
|
||||
QDomElement root = document.documentElement();
|
||||
if (root.tagName() != "qet-directory") return;
|
||||
|
||||
category_names.fromXml(root);
|
||||
|
||||
// ferme le fichier
|
||||
directory_conf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
Methode permettant d'obtenir le nom affichable de cette categorie.
|
||||
@return Le nom affichable de la categorie
|
||||
*/
|
||||
QString ElementsCategory::name() const {
|
||||
return(category_names.name(dirName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return La liste des differents noms possibles pour la categorie
|
||||
*/
|
||||
NamesList ElementsCategory::categoryNames() const {
|
||||
return(category_names);
|
||||
}
|
||||
|
||||
/**
|
||||
Vide la liste des noms de la categorie
|
||||
*/
|
||||
void ElementsCategory::clearNames() {
|
||||
category_names.clearNames();
|
||||
}
|
||||
|
||||
/**
|
||||
Ajoute un nom a la categorie.
|
||||
Si la langue existe deja, le nom pour cette langue est remplace.
|
||||
@param lang La langue pour laquelle le nom est utilisable
|
||||
@param value Le nom
|
||||
*/
|
||||
void ElementsCategory::addName(const QString &lang, const QString &value) {
|
||||
category_names.addName(lang, value);
|
||||
}
|
||||
|
||||
/**
|
||||
Cree la categorie
|
||||
@return true si la creation a reussi, false sinon
|
||||
*/
|
||||
bool ElementsCategory::write() const {
|
||||
|
||||
// cree le dossier de la categorie
|
||||
if (!mkpath(path())) return(false);
|
||||
|
||||
// prepare la structure XML
|
||||
QDomDocument document;
|
||||
QDomElement root = document.createElement("qet-directory");
|
||||
document.appendChild(root);
|
||||
root.appendChild(category_names.toXml(document));
|
||||
|
||||
// repere le chemin du fichier de configuration de la categorie
|
||||
QFile directory_conf(canonicalPath() + "/qet_directory");
|
||||
|
||||
// ouvre le fichier
|
||||
if (!directory_conf.open(QIODevice::Text | QIODevice::WriteOnly)) return(false);
|
||||
|
||||
// ecrit le fichier
|
||||
QTextStream out(&directory_conf);
|
||||
out.setCodec("UTF-8");
|
||||
out << document.toString(4);
|
||||
|
||||
// ferme le fichier
|
||||
directory_conf.close();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime la categorie
|
||||
@return true si la suppression a reussie, false sinon
|
||||
*/
|
||||
bool ElementsCategory::remove() const {
|
||||
return(rmdir(absolutePath()));
|
||||
}
|
||||
|
||||
/**
|
||||
@return true s'il est possible d'ecrire le fichier qet_directory dans la
|
||||
categorie
|
||||
*/
|
||||
bool ElementsCategory::isWritable() const {
|
||||
// informations sur le dossier de la categorie
|
||||
QFileInfo category(canonicalPath());
|
||||
QFileInfo qet_directory(canonicalPath() + "/.qet_directory");
|
||||
/*
|
||||
soit .qet_directory n'existe pas et le dossier est accessible en ecriture,
|
||||
soit .qet_directory existe et est accessible en ecriture
|
||||
*/
|
||||
return(
|
||||
(!qet_directory.exists() && category.isWritable()) ||\
|
||||
(qet_directory.exists() && qet_directory.isWritable())
|
||||
);
|
||||
}
|
||||
55
sources/elementscategory.h
Normal file
55
sources/elementscategory.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_CATEGORY_H
|
||||
#define ELEMENTS_CATEGORY_H
|
||||
#include <QtCore>
|
||||
#include "nameslist.h"
|
||||
/**
|
||||
Cette classe represente une categorie d'elements.
|
||||
Une categorie d'elements est en fait un dossier avec un fichier
|
||||
qet_directory contenant ses caracteristiques (pour le moment : ses noms).
|
||||
*/
|
||||
class ElementsCategory : public QDir {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementsCategory(const QString & = QString());
|
||||
virtual ~ElementsCategory();
|
||||
|
||||
private:
|
||||
ElementsCategory(const ElementsCategory &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
NamesList category_names;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
QString name() const;
|
||||
NamesList categoryNames() const;
|
||||
void clearNames();
|
||||
void addName(const QString &, const QString &);
|
||||
bool write() const;
|
||||
bool remove() const;
|
||||
bool isWritable() const;
|
||||
//bool move(const QString &new_parent);
|
||||
|
||||
private:
|
||||
bool rmdir(const QString &) const;
|
||||
void loadNames();
|
||||
};
|
||||
#endif
|
||||
81
sources/elementscategorydeleter.cpp
Normal file
81
sources/elementscategorydeleter.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementscategorydeleter.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param category_path Chemin du dossier representant la categorie a supprimer
|
||||
@param parent QWidget parent
|
||||
*/
|
||||
ElementsCategoryDeleter::ElementsCategoryDeleter(const QString &category_path, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
cat(category_path),
|
||||
empty_category_path(category_path.isNull())
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ElementsCategoryDeleter::~ElementsCategoryDeleter() {
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime la categorie et ses elements : verifie l'existence du dossier,
|
||||
demande deux fois confirmation a l'utilisateur et avertit ce dernier si la
|
||||
suppression a echoue.
|
||||
*/
|
||||
void ElementsCategoryDeleter::exec() {
|
||||
// verifie l'existence de la categorie
|
||||
if (!cat.exists() || empty_category_path) return;
|
||||
|
||||
QString cat_name(cat.name().replace("<", "<").replace(">", ">"));
|
||||
|
||||
// confirmation #1
|
||||
QMessageBox::StandardButton answer_1 = QMessageBox::question(
|
||||
this,
|
||||
tr("Supprimer la cat\351gorie ?"),
|
||||
tr("\312tes-vous s\373r de vouloir supprimer la cat\351gorie <b>") +
|
||||
cat_name
|
||||
+ tr("</b> ?\n"
|
||||
"Tous les \351l\351ments et les cat\351gories contenus dans cette "
|
||||
"cat\351gorie seront supprim\351s"),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel
|
||||
);
|
||||
if (answer_1 != QMessageBox::Yes) return;
|
||||
|
||||
// confirmation #2
|
||||
QMessageBox::StandardButton answer_2 = QMessageBox::question(
|
||||
this,
|
||||
tr("Supprimer la cat\351gorie ?"),
|
||||
tr("\312tes-vous vraiment s\373r de vouloir supprimer cette "
|
||||
"cat\351gorie (<b>") +
|
||||
cat_name
|
||||
+ tr("</b>) ?\nLes changements seront d\351finitifs."),
|
||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel
|
||||
);
|
||||
if (answer_2 != QMessageBox::Yes) return;
|
||||
|
||||
// supprime la categorie
|
||||
if (!cat.remove()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("Suppression de la cat\351gorie"),
|
||||
tr("La suppression de la cat\351gorie a \351chou\351.\n"
|
||||
"V\351rifiez vos droits sur le dossier ") + cat.absolutePath() + tr(".")
|
||||
);
|
||||
}
|
||||
}
|
||||
45
sources/elementscategorydeleter.h
Normal file
45
sources/elementscategorydeleter.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_CATEGORY_DELETER_H
|
||||
#define ELEMENTS_CATEGORY_DELETER_H
|
||||
#include "elementscategory.h"
|
||||
#include <QtGui>
|
||||
/**
|
||||
Cette ckasse represente une couche d'abstraction pour supprimer
|
||||
une categorie d'elements et les elements qu'elle contient.
|
||||
Elle demande notamment confirmation a l'utilisateur par deux fois.
|
||||
*/
|
||||
class ElementsCategoryDeleter : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementsCategoryDeleter(const QString &, QWidget * = 0);
|
||||
virtual ~ElementsCategoryDeleter();
|
||||
private:
|
||||
ElementsCategoryDeleter(const ElementsCategory &);
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void exec();
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ElementsCategory cat;
|
||||
bool empty_category_path;
|
||||
};
|
||||
#endif
|
||||
132
sources/elementscategoryeditor.cpp
Normal file
132
sources/elementscategoryeditor.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementscategoryeditor.h"
|
||||
#include "elementscategory.h"
|
||||
#include "nameslistwidget.h"
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
Constructeur fournissant un dialogue d'edition de categorie.
|
||||
@param category_path Chemin de la categorie a editer ou de la categorie parente en cas de creation
|
||||
@param edit booleen a true pour le mode edition, a false pour le mode creation
|
||||
@param parent QWidget parent du dialogue
|
||||
*/
|
||||
ElementsCategoryEditor::ElementsCategoryEditor(const QString &category_path, bool edit, QWidget *parent) : QDialog(parent) {
|
||||
mode_edit = edit;
|
||||
// dialogue basique
|
||||
buildDialog();
|
||||
category = new ElementsCategory(category_path);
|
||||
if (mode_edit) {
|
||||
setWindowTitle(tr("\311diter une cat\351gorie"));
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(acceptUpdate()));
|
||||
|
||||
// edition de categorie = affichage des noms deja existants
|
||||
names_list -> setNames(category -> categoryNames());
|
||||
} else {
|
||||
setWindowTitle(tr("Cr\351er une nouvelle cat\351gorie"));
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(acceptCreation()));
|
||||
|
||||
// nouvelle categorie = une ligne pre-machee
|
||||
NamesList cat_names;
|
||||
cat_names.addName(QLocale::system().name().left(2), tr("Nom de la nouvelle cat\351gorie"));
|
||||
names_list -> setNames(cat_names);
|
||||
//names_list -> openPersistentEditor(qtwi, 1);
|
||||
}
|
||||
|
||||
// gestion de la lecture seule
|
||||
if (!category -> isWritable()) {
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
tr("\311dition en lecture seule"),
|
||||
tr("Vous n'avez pas les privil\350ges n\351cessaires pour modifier cette cat\351gorie. Elle sera donc ouverte en lecture seule.")
|
||||
);
|
||||
names_list -> setReadOnly(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsCategoryEditor::~ElementsCategoryEditor() {
|
||||
delete category;
|
||||
}
|
||||
|
||||
/**
|
||||
Bases du dialogue de creation / edition
|
||||
*/
|
||||
void ElementsCategoryEditor::buildDialog() {
|
||||
QVBoxLayout *editor_layout = new QVBoxLayout();
|
||||
setLayout(editor_layout);
|
||||
|
||||
names_list = new NamesListWidget();
|
||||
|
||||
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
editor_layout -> addWidget(new QLabel(tr("Vous pouvez sp\351cifier un nom par langue pour la cat\351gorie.")));
|
||||
editor_layout -> addWidget(names_list);
|
||||
editor_layout -> addWidget(buttons);
|
||||
}
|
||||
|
||||
/**
|
||||
Valide les donnees entrees par l'utilisateur lors d'une creation de
|
||||
categorie
|
||||
*/
|
||||
void ElementsCategoryEditor::acceptCreation() {
|
||||
if (!category -> isWritable()) QDialog::accept();
|
||||
|
||||
// il doit y avoir au moins un nom
|
||||
if (!names_list -> checkOneName()) return;
|
||||
|
||||
// chargement des noms
|
||||
category -> clearNames();
|
||||
NamesList names = names_list -> names();
|
||||
foreach(QString lang, names.langs()) {
|
||||
category -> addName(lang, names[lang]);
|
||||
}
|
||||
|
||||
// cree un nom de dossier a partir du 1er nom de la categorie
|
||||
QString dirname = names[names.langs().first()].toLower().replace(" ", "_");
|
||||
foreach(QChar c, QET::forbiddenCharacters()) dirname = dirname.replace(c, "_");
|
||||
category -> setPath(category -> path() + "/" + dirname);
|
||||
category -> write();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
/**
|
||||
Valide les donnees entrees par l'utilisateur lors d'une modification de
|
||||
categorie
|
||||
*/
|
||||
void ElementsCategoryEditor::acceptUpdate() {
|
||||
if (!category -> isWritable()) QDialog::accept();
|
||||
|
||||
// il doit y avoir au moins un nom
|
||||
if (!names_list -> checkOneName()) return;
|
||||
|
||||
// chargement des noms
|
||||
category -> clearNames();
|
||||
NamesList names = names_list -> names();
|
||||
foreach(QString lang, names.langs()) {
|
||||
category -> addName(lang, names[lang]);
|
||||
}
|
||||
|
||||
category -> write();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
53
sources/elementscategoryeditor.h
Normal file
53
sources/elementscategoryeditor.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_CATEGORY_EDITOR_H
|
||||
#define ELEMENTS_CATEGORY_EDITOR_H
|
||||
#include <QtGui>
|
||||
class ElementsCategory;
|
||||
class NamesListWidget;
|
||||
/**
|
||||
Cette classe permet d'editer une categorie existante ou de creer une
|
||||
categorie.
|
||||
*/
|
||||
class ElementsCategoryEditor : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementsCategoryEditor(const QString &, bool = true, QWidget * = 0);
|
||||
virtual ~ElementsCategoryEditor();
|
||||
|
||||
private:
|
||||
ElementsCategoryEditor(const ElementsCategoryEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ElementsCategory *category;
|
||||
QDialogButtonBox *buttons;
|
||||
NamesListWidget *names_list;
|
||||
bool mode_edit;
|
||||
|
||||
// methodes
|
||||
private:
|
||||
void buildDialog();
|
||||
|
||||
public slots:
|
||||
void acceptCreation();
|
||||
void acceptUpdate();
|
||||
};
|
||||
#endif
|
||||
379
sources/elementspanel.cpp
Normal file
379
sources/elementspanel.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementspanel.h"
|
||||
#include "qetapp.h"
|
||||
#include "elementscategory.h"
|
||||
#include "elementscategoryeditor.h"
|
||||
#include "elementscategorydeleter.h"
|
||||
#include "elementdeleter.h"
|
||||
#include "customelement.h"
|
||||
#include "qetelementeditor.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent du panel d'appareils
|
||||
*/
|
||||
ElementsPanel::ElementsPanel(QWidget *parent) : QTreeWidget(parent) {
|
||||
|
||||
// selection unique
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
setColumnCount(1);
|
||||
header() -> hide();
|
||||
|
||||
// drag'n drop autorise
|
||||
setDragEnabled(true);
|
||||
setAcceptDrops(false);
|
||||
setDropIndicatorShown(false);
|
||||
|
||||
// taille des elements
|
||||
setIconSize(QSize(50, 50));
|
||||
|
||||
// charge les collections
|
||||
reload();
|
||||
|
||||
// la premiere fois, etend le premier niveau des collections
|
||||
QList<QTreeWidgetItem *> items = findItems("*", Qt::MatchWildcard);
|
||||
if (items.count() == 2) {
|
||||
items[0] -> setExpanded(true);
|
||||
items[1] -> setExpanded(true);
|
||||
}
|
||||
|
||||
// force du noir sur une alternance de blanc (comme le schema) et de gris
|
||||
// clair, avec du blanc sur bleu pas trop fonce pour la selection
|
||||
QPalette qp = palette();
|
||||
qp.setColor(QPalette::Text, Qt::black);
|
||||
qp.setColor(QPalette::Base, Qt::white);
|
||||
qp.setColor(QPalette::AlternateBase, QColor("#e8e8e8"));
|
||||
qp.setColor(QPalette::Highlight, QColor("#678db2"));
|
||||
qp.setColor(QPalette::HighlightedText, Qt::white);
|
||||
setPalette(qp);
|
||||
|
||||
// double-cliquer sur un element permet de l'editer
|
||||
connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slot_doubleClick(QTreeWidgetItem *, int)));
|
||||
|
||||
// emet un signal au lieu de gerer son menu contextuel
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsPanel::~ElementsPanel() {
|
||||
}
|
||||
|
||||
/// @return true si un element est selectionne, false sinon
|
||||
bool ElementsPanel::selectedItemIsAnElement() const {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists()) return(false);
|
||||
return(infos_file.isFile());
|
||||
}
|
||||
|
||||
/// @return true si une categorie est selectionnee, false sinon
|
||||
bool ElementsPanel::selectedItemIsACategory() const {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists()) return(false);
|
||||
return(infos_file.isDir());
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le mouvement lors d'un drag'n drop
|
||||
*/
|
||||
void ElementsPanel::dragMoveEvent(QDragMoveEvent */*e*/) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le depot lors d'un drag'n drop
|
||||
*/
|
||||
void ElementsPanel::dropEvent(QDropEvent */*e*/) {
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le debut des drag'n drop
|
||||
@param supportedActions Les actions supportees
|
||||
*/
|
||||
void ElementsPanel::startDrag(Qt::DropActions) {
|
||||
// recupere le nom du fichier decrivant l'element
|
||||
QString nom_fichier = currentItem() -> data(0, 42).toString();
|
||||
if (nom_fichier.isEmpty()) return;
|
||||
|
||||
// objet QDrag pour realiser le drag'n drop
|
||||
QDrag *drag = new QDrag(this);
|
||||
|
||||
// donnees qui seront transmises par le drag'n drop
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
|
||||
// appareil temporaire pour fournir un apercu
|
||||
int etat;
|
||||
Element *appar = new CustomElement(nom_fichier, 0, 0, &etat);
|
||||
if (etat != 0) {
|
||||
delete appar;
|
||||
return;
|
||||
}
|
||||
|
||||
mimeData -> setText(nom_fichier);
|
||||
drag -> setMimeData(mimeData);
|
||||
|
||||
// accrochage d'une pixmap representant l'appareil au pointeur
|
||||
drag -> setPixmap(appar -> pixmap());
|
||||
drag -> setHotSpot(appar -> hotspot());
|
||||
|
||||
// realisation du drag'n drop
|
||||
drag -> start(Qt::CopyAction);
|
||||
|
||||
// suppression de l'appareil temporaire
|
||||
delete appar;
|
||||
}
|
||||
|
||||
/**
|
||||
Methode privee permettant d'ajouter un dossier au panel d'appareils
|
||||
@param qtwi_parent QTreeWidgetItem parent sous lequel sera insere l'element
|
||||
@param dossier Chemin absolu du dossier a inserer
|
||||
@param nom Parametre facultatif permettant de forcer le nom du dossier.
|
||||
S'il n'est pas precise, la fonction ouvre le fichier qet_directory situe
|
||||
dans le dossier et y lit le nom du dossier ; si ce fichier n'existe pas ou
|
||||
est invalide, la fonction utilise le nom du dossier.
|
||||
*/
|
||||
void ElementsPanel::addDir(QTreeWidgetItem *qtwi_parent, QString adr_dossier, QString nom) {
|
||||
ElementsCategory category(adr_dossier);
|
||||
if (!category.exists()) return;
|
||||
|
||||
// recupere le nom de la categorie
|
||||
QString nom_categorie = (nom != QString()) ? nom : category.name();
|
||||
|
||||
// creation du QTreeWidgetItem representant le dossier
|
||||
QTreeWidgetItem *qtwi_dossier = new QTreeWidgetItem(qtwi_parent, QStringList(nom_categorie));
|
||||
qtwi_dossier -> setIcon(0, QIcon(":/ico/folder.png"));
|
||||
QLinearGradient t(0, 0, 200, 0);
|
||||
t.setColorAt(0, QColor("#e8e8e8"));
|
||||
t.setColorAt(1, QColor("#ffffff"));
|
||||
qtwi_dossier -> setBackground(0, QBrush(t));
|
||||
qtwi_dossier -> setData(0, 42, adr_dossier);
|
||||
|
||||
// reduit le dossier si besoin
|
||||
qtwi_dossier -> setExpanded(expanded_directories.contains(adr_dossier));
|
||||
|
||||
// ajout des sous-categories / sous-dossiers
|
||||
QStringList dossiers = category.entryList(QStringList(), QDir::AllDirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::Name);
|
||||
foreach(QString dossier, dossiers) addDir(qtwi_dossier, adr_dossier + dossier + "/");
|
||||
|
||||
// ajout des elements / fichiers
|
||||
QStringList fichiers = category.entryList(QStringList("*.elmt"), QDir::Files, QDir::Name);
|
||||
foreach(QString fichier, fichiers) addFile(qtwi_dossier, adr_dossier + fichier);
|
||||
}
|
||||
|
||||
/**
|
||||
Methode privee permettant d'ajouter un element au panel d'appareils
|
||||
@param qtwi_parent QTreeWidgetItem parent sous lequel sera insere l'element
|
||||
@param fichier Chemin absolu du fichier XML decrivant l'element a inserer
|
||||
*/
|
||||
void ElementsPanel::addFile(QTreeWidgetItem *qtwi_parent, QString fichier) {
|
||||
QString whats_this = tr("Ceci est un \351l\351ment que vous pouvez ins\351rer dans votre sch\351ma par cliquer-d\351placer");
|
||||
QString tool_tip = tr("Cliquer-d\351posez cet \351l\351ment sur le sch\351ma pour ins\351rer un \351l\351ment ");
|
||||
int etat;
|
||||
CustomElement elmt_perso(fichier, 0, 0, &etat);
|
||||
if (etat != 0) {
|
||||
qDebug() << "Le chargement du composant" << fichier << "a echoue avec le code d'erreur" << etat;
|
||||
return;
|
||||
}
|
||||
QTreeWidgetItem *qtwi = new QTreeWidgetItem(qtwi_parent, QStringList(elmt_perso.nom()));
|
||||
qtwi -> setStatusTip(0, tool_tip + "\253 " + elmt_perso.nom() + " \273");
|
||||
qtwi -> setToolTip(0, elmt_perso.nom());
|
||||
qtwi -> setWhatsThis(0, whats_this);
|
||||
qtwi -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
|
||||
qtwi -> setIcon(0, QIcon(elmt_perso.pixmap()));
|
||||
qtwi -> setData(0, 42, fichier);
|
||||
}
|
||||
|
||||
/**
|
||||
Recharge l'arbre des elements
|
||||
*/
|
||||
void ElementsPanel::reload() {
|
||||
// sauvegarde la liste des repertoires reduits
|
||||
saveExpandedCategories();
|
||||
|
||||
// vide l'arbre
|
||||
clear();
|
||||
|
||||
// chargement des elements de la collection QET
|
||||
addDir(invisibleRootItem(), QETApp::commonElementsDir(), tr("Collection QET"));
|
||||
|
||||
// chargement des elements de la collection utilisateur
|
||||
addDir(invisibleRootItem(), QETApp::customElementsDir(), tr("Collection utilisateur"));
|
||||
|
||||
// icones
|
||||
QList<QTreeWidgetItem *> items = findItems("*", Qt::MatchWildcard);
|
||||
if (items.count() == 2) {
|
||||
items[0] -> setIcon(0, QIcon(":/ico/qet-16.png"));
|
||||
items[1] -> setIcon(0, QIcon(":/ico/folder_home.png"));
|
||||
}
|
||||
|
||||
// reselectionne le dernier element selectionne
|
||||
if (!last_selected_item.isNull()) {
|
||||
QTreeWidgetItem *qtwi = findFile(last_selected_item);
|
||||
if (qtwi) setCurrentItem(qtwi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Edite la categorie selectionnee
|
||||
*/
|
||||
void ElementsPanel::editCategory() {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists() || !infos_file.isDir()) return;
|
||||
launchCategoryEditor(infos_file.absoluteFilePath());
|
||||
}
|
||||
|
||||
/**
|
||||
Edite l'element selectionne
|
||||
*/
|
||||
void ElementsPanel::editElement() {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists() || !infos_file.isFile()) return;
|
||||
launchElementEditor(infos_file.absoluteFilePath());
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime la categorie selectionnee
|
||||
*/
|
||||
void ElementsPanel::deleteCategory() {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists() || !infos_file.isDir()) return;
|
||||
|
||||
// supprime la categorie
|
||||
ElementsCategoryDeleter cat_deleter(infos_file.absoluteFilePath(), this);
|
||||
cat_deleter.exec();
|
||||
|
||||
// recharge la liste des categories
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Supprime l'element selectionne
|
||||
*/
|
||||
void ElementsPanel::deleteElement() {
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists() || !infos_file.isFile()) return;
|
||||
|
||||
// supprime l'element
|
||||
ElementDeleter elmt_deleter(infos_file.absoluteFilePath(), this);
|
||||
elmt_deleter.exec();
|
||||
|
||||
// recharge la liste des categories
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le double-clic sur un element. Permet de lancer l'editeur de
|
||||
categorie ou d'element.
|
||||
*/
|
||||
void ElementsPanel::slot_doubleClick(QTreeWidgetItem *, int) {
|
||||
// le fichier doit exister
|
||||
QFileInfo infos_file = selectedFile();
|
||||
if (!infos_file.exists()) return;
|
||||
|
||||
if (infos_file.isFile()) {
|
||||
// il s'agit d'un element
|
||||
launchElementEditor(infos_file.absoluteFilePath());
|
||||
} else if (infos_file.isDir()) {
|
||||
// il s'agit d'une categorie
|
||||
launchCategoryEditor(infos_file.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
/// @return un QFileInfo decrivant le fichier ou le dossier correspondant au QTreeWidgetItem selectionne
|
||||
QFileInfo ElementsPanel::selectedFile() const {
|
||||
QTreeWidgetItem *current_qtwi = currentItem();
|
||||
if(!current_qtwi) return(QFileInfo());
|
||||
return(QFileInfo(currentItem() -> data(0, 42).toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
Lance l'editeur d'element pour l'element filename
|
||||
@param filename Chemin du fichier representant l'element
|
||||
*/
|
||||
void ElementsPanel::launchElementEditor(const QString &filename) {
|
||||
QETElementEditor *editor = new QETElementEditor();
|
||||
editor -> fromFile(filename);
|
||||
editor -> show();
|
||||
}
|
||||
|
||||
/**
|
||||
Lance l'editeur de categorie pour la categorie filename
|
||||
@param filename Chemin du dossier representant la categorie
|
||||
*/
|
||||
void ElementsPanel::launchCategoryEditor(const QString &filename) {
|
||||
ElementsCategoryEditor ece(filename, true);
|
||||
if (ece.exec() == QDialog::Accepted) reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Enregistre la liste des categories repliees ainsi que le dernier element
|
||||
selectionne
|
||||
*/
|
||||
void ElementsPanel::saveExpandedCategories() {
|
||||
expanded_directories.clear();
|
||||
QList<QTreeWidgetItem *> items = findItems("*", Qt::MatchRecursive|Qt::MatchWildcard);
|
||||
foreach(QTreeWidgetItem *item, items) {
|
||||
QString file = item -> data(0, 42).toString();
|
||||
if (!file.endsWith(".elmt") && item -> isExpanded()) {
|
||||
expanded_directories << file;
|
||||
}
|
||||
}
|
||||
|
||||
// sauvegarde egalement le dernier element selectionne
|
||||
QTreeWidgetItem *current_item = currentItem();
|
||||
if (current_item) last_selected_item = current_item -> data(0, 42).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@param file fichier ou dossier a retrouver dans l'arborescence
|
||||
@return le QTreeWidgetItem correspondant au fichier file ou 0 si celui-ci n'est pas trouve
|
||||
*/
|
||||
QTreeWidgetItem *ElementsPanel::findFile(const QString &file) const {
|
||||
QList<QTreeWidgetItem *> items = findItems("*", Qt::MatchRecursive|Qt::MatchWildcard);
|
||||
foreach(QTreeWidgetItem *item, items) {
|
||||
if (item -> data(0, 42).toString() == file) return(item);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
N'affiche que les elements contenant une chaine donnee
|
||||
@param m Chaine a filtrer
|
||||
*/
|
||||
void ElementsPanel::filter(const QString &m) {
|
||||
QList<QTreeWidgetItem *> items = findItems("*", Qt::MatchRecursive | Qt::MatchWildcard);
|
||||
if (m.isEmpty()) {
|
||||
foreach(QTreeWidgetItem *item, items) item -> setHidden(false);
|
||||
} else {
|
||||
foreach(QTreeWidgetItem *item, items) {
|
||||
QString file = item -> data(0, 42).toString();
|
||||
bool item_matches = item -> text(0).contains(m, Qt::CaseInsensitive);
|
||||
item -> setHidden(!item_matches);
|
||||
if (item_matches) {
|
||||
// remonte l'arborescence pour afficher les categories contenant l'element
|
||||
QTreeWidgetItem *parent_qtwi = item -> parent();
|
||||
while(parent_qtwi && (parent_qtwi -> isHidden() || !parent_qtwi -> isExpanded())) {
|
||||
parent_qtwi -> setHidden(false);
|
||||
parent_qtwi -> setExpanded(true);
|
||||
parent_qtwi = parent_qtwi -> parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
sources/elementspanel.h
Normal file
66
sources/elementspanel.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 PANELAPPAREILS_H
|
||||
#define PANELAPPAREILS_H
|
||||
#include <QtGui>
|
||||
#include "qetdiagrameditor.h"
|
||||
/**
|
||||
Cette classe represente le panel d'appareils (en tant qu'element
|
||||
graphique) dans lequel l'utilisateur choisit les composants de
|
||||
son choix et les depose sur le schema par drag'n drop.
|
||||
*/
|
||||
class ElementsPanel : public QTreeWidget {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementsPanel(QWidget * = 0);
|
||||
virtual ~ElementsPanel();
|
||||
|
||||
private:
|
||||
ElementsPanel(const ElementsPanel &);
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool selectedItemIsAnElement() const;
|
||||
bool selectedItemIsACategory() const;
|
||||
|
||||
private:
|
||||
void addFile(QTreeWidgetItem *, QString);
|
||||
void addDir(QTreeWidgetItem *, QString, QString = QString());
|
||||
QFileInfo selectedFile() const;
|
||||
void launchElementEditor(const QString &);
|
||||
void launchCategoryEditor(const QString &);
|
||||
void saveExpandedCategories();
|
||||
QTreeWidgetItem *findFile(const QString &) const;
|
||||
QStringList expanded_directories;
|
||||
QString last_selected_item;
|
||||
|
||||
public slots:
|
||||
void slot_doubleClick(QTreeWidgetItem *, int);
|
||||
void dragMoveEvent(QDragMoveEvent *);
|
||||
void dropEvent(QDropEvent *);
|
||||
void startDrag(Qt::DropActions);
|
||||
void reload();
|
||||
void editCategory();
|
||||
void editElement();
|
||||
void deleteCategory();
|
||||
void deleteElement();
|
||||
void filter(const QString &);
|
||||
};
|
||||
#endif
|
||||
178
sources/elementspanelwidget.cpp
Normal file
178
sources/elementspanelwidget.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementspanelwidget.h"
|
||||
#include "newelementwizard.h"
|
||||
#include "elementscategorieswidget.h"
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QWidget parent de ce widget
|
||||
*/
|
||||
ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) {
|
||||
// initalise le panel d'elements
|
||||
elements_panel = new ElementsPanel(this);
|
||||
|
||||
// initialise les actions
|
||||
reload = new QAction(QIcon(":/ico/reload.png"), tr("Recharger les collections"), this);
|
||||
new_category = new QAction(QIcon(":/ico/category_new.png"), tr("Nouvelle cat\351gorie"), this);
|
||||
edit_category = new QAction(QIcon(":/ico/category_edit.png"), tr("\311diter la cat\351gorie"), this);
|
||||
delete_category = new QAction(QIcon(":/ico/category_delete.png"), tr("Supprimer la cat\351gorie"), this);
|
||||
new_element = new QAction(QIcon(":/ico/new.png"), tr("Nouvel \351l\351ment"), this);
|
||||
edit_element = new QAction(QIcon(":/ico/edit.png"), tr("\311diter l'\351l\351ment"), this);
|
||||
delete_element = new QAction(QIcon(":/ico/delete.png"), tr("Supprimer l'\351l\351ment"), this);
|
||||
erase_textfield = new QAction(QIcon(":/ico/erase.png"), tr("Effacer le filtre"), this);
|
||||
|
||||
// initialise le champ de texte pour filtrer avec une disposition horizontale
|
||||
QLabel *filter_label = new QLabel(tr("Filtrer : "), this);
|
||||
filter_textfield = new QLineEdit(this);
|
||||
filter_toolbar = new QToolBar("filter");
|
||||
filter_toolbar -> addAction(erase_textfield);
|
||||
filter_toolbar -> addWidget(filter_label);
|
||||
filter_toolbar -> addWidget(filter_textfield);
|
||||
|
||||
context_menu = new QMenu(this);
|
||||
|
||||
connect(reload, SIGNAL(triggered()), this, SLOT(reloadAndFilter()));
|
||||
connect(new_category, SIGNAL(triggered()), this, SLOT(newCategory()));
|
||||
connect(edit_category, SIGNAL(triggered()), elements_panel, SLOT(editCategory()));
|
||||
connect(delete_category, SIGNAL(triggered()), elements_panel, SLOT(deleteCategory()));
|
||||
connect(new_element, SIGNAL(triggered()), this, SLOT(newElement()));
|
||||
connect(edit_element, SIGNAL(triggered()), elements_panel, SLOT(editElement()));
|
||||
connect(delete_element, SIGNAL(triggered()), elements_panel, SLOT(deleteElement()));
|
||||
|
||||
connect(erase_textfield, SIGNAL(triggered()), filter_textfield, SLOT(clear()));
|
||||
connect(erase_textfield, SIGNAL(triggered()), filter_textfield, SLOT(setFocus()));
|
||||
connect(filter_textfield, SIGNAL(textEdited(const QString &)), elements_panel, SLOT(filter(const QString &)));
|
||||
|
||||
connect(elements_panel, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(updateButtons()));
|
||||
connect(elements_panel, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(handleContextMenu(const QPoint &)));
|
||||
|
||||
// initialise la barre d'outils
|
||||
toolbar = new QToolBar(this);
|
||||
toolbar -> setMovable(false);
|
||||
toolbar -> addAction(reload);
|
||||
toolbar -> addSeparator();
|
||||
toolbar -> addAction(new_category);
|
||||
toolbar -> addAction(edit_category);
|
||||
toolbar -> addAction(delete_category);
|
||||
toolbar -> addSeparator();
|
||||
toolbar -> addAction(new_element);
|
||||
toolbar -> addAction(edit_element);
|
||||
toolbar -> addAction(delete_element);
|
||||
|
||||
// disposition verticale
|
||||
QVBoxLayout *vlayout = new QVBoxLayout(this);
|
||||
vlayout -> setMargin(0);
|
||||
vlayout -> setSpacing(0);
|
||||
vlayout -> addWidget(toolbar);
|
||||
vlayout -> addWidget(filter_toolbar);
|
||||
vlayout -> addWidget(elements_panel);
|
||||
vlayout -> setStretchFactor(elements_panel, 75000);
|
||||
setLayout(vlayout);
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
ElementsPanelWidget::~ElementsPanelWidget() {
|
||||
}
|
||||
|
||||
/**
|
||||
Recharge le panel d'elements
|
||||
*/
|
||||
void ElementsPanelWidget::reloadAndFilter() {
|
||||
// recharge tous les elements
|
||||
elements_panel -> reload();
|
||||
|
||||
// reapplique le filtre
|
||||
elements_panel -> filter(filter_textfield -> text());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Appelle l'assistant de creation de nouvel element
|
||||
*/
|
||||
void ElementsPanelWidget::newElement() {
|
||||
NewElementWizard new_element_wizard;
|
||||
new_element_wizard.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
Lance le gestionnaire de categories
|
||||
*/
|
||||
void ElementsPanelWidget::newCategory() {
|
||||
QDialog new_category_dialog;
|
||||
new_category_dialog.setMinimumSize(480, 280);
|
||||
new_category_dialog.setWindowTitle(tr("Gestionnaire de cat\351gories"));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(&new_category_dialog);
|
||||
QLabel *explication = new QLabel(tr("Vous pouvez utiliser ce gestionnaire pour ajouter, supprimer ou modifier les cat\351gories."));
|
||||
explication -> setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
|
||||
explication -> setWordWrap(true);
|
||||
layout -> addWidget(explication);
|
||||
|
||||
layout -> addWidget(new ElementsCategoriesWidget());
|
||||
|
||||
QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
connect(buttons, SIGNAL(rejected()), &new_category_dialog, SLOT(accept()));
|
||||
layout -> addWidget(buttons);
|
||||
|
||||
new_category_dialog.exec();
|
||||
elements_panel -> reload();
|
||||
}
|
||||
|
||||
/**
|
||||
Met a jour les boutons afin d'assurer la coherence de l'interface
|
||||
*/
|
||||
void ElementsPanelWidget::updateButtons() {
|
||||
bool category_selected = elements_panel -> selectedItemIsACategory();
|
||||
bool element_selected = elements_panel -> selectedItemIsAnElement();
|
||||
edit_category -> setEnabled(category_selected);
|
||||
delete_category -> setEnabled(category_selected);
|
||||
edit_element -> setEnabled(element_selected);
|
||||
delete_element -> setEnabled(element_selected);
|
||||
}
|
||||
|
||||
/**
|
||||
Gere le menu contextuel du panel d'elements
|
||||
@param pos Position ou le menu contextuel a ete demande
|
||||
*/
|
||||
void ElementsPanelWidget::handleContextMenu(const QPoint &pos) {
|
||||
// recupere l'item concerne par l'evenement ainsi que son chemin
|
||||
QTreeWidgetItem *item = elements_panel -> itemAt(pos);
|
||||
if (!item) return;
|
||||
|
||||
// recupere le fichier associe a l'item
|
||||
QString item_file = item -> data(0, 42).toString();
|
||||
QFileInfo item_file_infos(item_file);
|
||||
if (item_file.isNull() || !item_file_infos.exists()) return;
|
||||
|
||||
// remplit le menu differemment selon qu'il s'agit d'un element ou d'une categorie
|
||||
context_menu -> clear();
|
||||
if (item_file_infos.isDir()) {
|
||||
context_menu -> addAction(new_category);
|
||||
context_menu -> addAction(edit_category);
|
||||
context_menu -> addAction(delete_category);
|
||||
context_menu -> addAction(new_element);
|
||||
} else {
|
||||
context_menu -> addAction(edit_element);
|
||||
context_menu -> addAction(delete_element);
|
||||
}
|
||||
|
||||
// affiche le menu
|
||||
context_menu -> popup(mapToGlobal(elements_panel -> mapTo(this, pos)));
|
||||
}
|
||||
68
sources/elementspanelwidget.h
Normal file
68
sources/elementspanelwidget.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 ELEMENTS_PANEL_WIDGET_H
|
||||
#define ELEMENTS_PANEL_WIDGET_H
|
||||
#include <QtGui>
|
||||
#include "elementspanel.h"
|
||||
|
||||
/**
|
||||
Cette classe est un widget qui contient le panel d'elements surplombe d'une
|
||||
barre d'outils avec differentes actions pour gerer les elements.
|
||||
*/
|
||||
class ElementsPanelWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
ElementsPanelWidget(QWidget * = 0);
|
||||
virtual ~ElementsPanelWidget();
|
||||
|
||||
private:
|
||||
ElementsPanelWidget(const ElementsPanelWidget &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
ElementsPanel *elements_panel;
|
||||
QToolBar *toolbar, *filter_toolbar;
|
||||
QAction *reload;
|
||||
QAction *new_category, *edit_category, *delete_category;
|
||||
QAction *new_element, *edit_element, *delete_element;
|
||||
QMenu *context_menu;
|
||||
QAction *erase_textfield;
|
||||
QLineEdit *filter_textfield;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
inline ElementsPanel &elementsPanel() const;
|
||||
|
||||
public slots:
|
||||
void reloadAndFilter();
|
||||
void newElement();
|
||||
void newCategory();
|
||||
void updateButtons();
|
||||
void handleContextMenu(const QPoint &);
|
||||
};
|
||||
|
||||
/**
|
||||
@return Le panel d'elements imbrique dans ce widget
|
||||
*/
|
||||
inline ElementsPanel &ElementsPanelWidget::elementsPanel() const {
|
||||
return(*elements_panel);
|
||||
}
|
||||
|
||||
#endif
|
||||
120
sources/elementtextitem.cpp
Normal file
120
sources/elementtextitem.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
Copyright 2006-2008 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 "elementtextitem.h"
|
||||
#include "diagram.h"
|
||||
#include "diagramcommands.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QGraphicsItem parent du champ de texte
|
||||
@param scene La scene a laquelle appartient le champ de texte
|
||||
*/
|
||||
ElementTextItem::ElementTextItem(QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
DiagramTextItem(parent, scene),
|
||||
follow_parent_rotations(false)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsSelectable);
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param parent Le QGraphicsItem parent du champ de texte
|
||||
@param scene La scene a laquelle appartient le champ de texte
|
||||
@param text Le texte affiche par le champ de texte
|
||||
*/
|
||||
ElementTextItem::ElementTextItem(const QString &text, QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
DiagramTextItem(text, parent, scene),
|
||||
follow_parent_rotations(false)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsSelectable);
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
ElementTextItem::~ElementTextItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
Modifie la position du champ de texte
|
||||
@param pos La nouvelle position du champ de texte
|
||||
*/
|
||||
void ElementTextItem::setPos(const QPointF &pos) {
|
||||
QPointF actual_pos = pos;
|
||||
actual_pos -= QPointF(0.0, boundingRect().height() / 2.0);
|
||||
DiagramTextItem::setPos(actual_pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Modifie la position du champ de texte
|
||||
@param x La nouvelle abscisse du champ de texte
|
||||
@param y La nouvelle ordonnee du champ de texte
|
||||
*/
|
||||
void ElementTextItem::setPos(qreal x, qreal y) {
|
||||
setPos(QPointF(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
@return La position (bidouillee) du champ de texte
|
||||
*/
|
||||
QPointF ElementTextItem::pos() const {
|
||||
QPointF actual_pos = DiagramTextItem::pos();
|
||||
actual_pos += QPointF(0.0, boundingRect().height() / 2.0);
|
||||
return(actual_pos);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de lire le texte a mettre dans le champ a partir d'un element XML.
|
||||
Cette methode se base sur la position du champ pour assigner ou non la
|
||||
valeur a ce champ.
|
||||
@param e L'element XML representant le champ de texte
|
||||
*/
|
||||
void ElementTextItem::fromXml(const QDomElement &e) {
|
||||
QPointF _pos = pos();
|
||||
if (e.attribute("x").toDouble() == _pos.x() && e.attribute("y").toDouble() == _pos.y()) {
|
||||
setPlainText(e.attribute("text"));
|
||||
previous_text = e.attribute("text");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param document Le document XML a utiliser
|
||||
@return L'element XML representant ce champ de texte
|
||||
*/
|
||||
QDomElement ElementTextItem::toXml(QDomDocument &document) const {
|
||||
QDomElement result = document.createElement("input");
|
||||
result.setAttribute("x", originalPos().x());
|
||||
result.setAttribute("y", originalPos().y());
|
||||
result.setAttribute("text", toPlainText());
|
||||
return(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@param p Position originale / de reference pour ce champ
|
||||
Cette position est utilisee lors de l'export en XML
|
||||
*/
|
||||
void ElementTextItem::setOriginalPos(const QPointF &p) {
|
||||
original_position = p;
|
||||
}
|
||||
|
||||
/**
|
||||
@return la position originale / de reference pour ce champ
|
||||
*/
|
||||
QPointF ElementTextItem::originalPos() const {
|
||||
return(original_position);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user