mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-12-23 02:10:52 +01:00
Ajout de l'editeur d'elements
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@94 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
56
editor/circleeditor.cpp
Normal file
56
editor/circleeditor.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "circleeditor.h"
|
||||
#include "partcircle.h"
|
||||
|
||||
CircleEditor::CircleEditor(PartCircle *circle, QWidget *parent) : QWidget(parent) {
|
||||
|
||||
part = circle;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
r = new QLineEdit();
|
||||
|
||||
// QDoubleValidator *format = new QDoubleValidator(-1000.0, -1000.0, 4, this);
|
||||
// x -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
|
||||
// y -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
|
||||
// h -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
|
||||
|
||||
|
||||
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);
|
||||
|
||||
updateForm();
|
||||
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
|
||||
connect(r, SIGNAL(editingFinished()), this, SLOT(updateCircle()));
|
||||
}
|
||||
|
||||
CircleEditor::~CircleEditor() {
|
||||
qDebug() << "~CircleEditor()";
|
||||
}
|
||||
|
||||
void CircleEditor::updateCircle() {
|
||||
qreal _x = x -> text().toDouble();
|
||||
qreal _y = y -> text().toDouble();
|
||||
qreal _d = r -> text().toDouble();
|
||||
part -> setRect(
|
||||
QRectF(
|
||||
part -> mapFromScene(QPointF(_x - _d / 2.0, _y - _d / 2.0)),
|
||||
QSizeF(_d, _d)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void CircleEditor::updateForm() {
|
||||
qreal _d = part -> rect().width();
|
||||
QPointF top_left(part -> sceneTopLeft());
|
||||
x -> setText(QString("%1").arg(top_left.x() + _d / 2.0));
|
||||
y -> setText(QString("%1").arg(top_left.y() + _d / 2.0));
|
||||
r -> setText(QString("%1").arg(_d));
|
||||
}
|
||||
29
editor/circleeditor.h
Normal file
29
editor/circleeditor.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef CIRCLE_EDITOR_H
|
||||
#define CIRCLE_EDITOR_H
|
||||
#include <QtGui>
|
||||
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 QWidget {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
CircleEditor(PartCircle *, QWidget * = 0);
|
||||
virtual ~CircleEditor();
|
||||
private:
|
||||
CircleEditor(const CircleEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartCircle *part;
|
||||
QLineEdit *x, *y, *r;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateCircle();
|
||||
void updateForm();
|
||||
};
|
||||
#endif
|
||||
447
editor/customelementeditor.cpp
Normal file
447
editor/customelementeditor.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
#include "customelementeditor.h"
|
||||
#include "editorscene.h"
|
||||
#include "customelementpart.h"
|
||||
#include "newelementwizard.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
CustomElementEditor::CustomElementEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
read_only(false),
|
||||
min_title(tr("QElectroTech - \311diteur d'\351l\351ment")),
|
||||
_filename(QString())
|
||||
{
|
||||
setMinimumWidth(700);
|
||||
setMinimumHeight(450);
|
||||
setWindowTitle(min_title);
|
||||
setWindowIcon(QIcon(":/ico/qet.png"));
|
||||
|
||||
setupInterface();
|
||||
setupActions();
|
||||
setupMenus();
|
||||
}
|
||||
|
||||
CustomElementEditor::~CustomElementEditor() {
|
||||
qDebug() << "~CustomElementEditor()";
|
||||
// recupere le layout
|
||||
// QLayout *layout = tools_dock -> widget() -> layout();
|
||||
//
|
||||
// // enleve les widgets deja presents
|
||||
// QLayoutItem *qli;
|
||||
// while ((qli = layout -> takeAt(0)) != 0) {
|
||||
// if (qli -> widget()) {
|
||||
// layout -> removeWidget(qli -> widget());
|
||||
// qli -> widget() -> setParent(0);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CustomElementEditor::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);
|
||||
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);
|
||||
edit_size = new QAction( tr("Modifier la taille"), this);
|
||||
edit_hotspot = new QAction( tr("Modifier le point de saisie"), this);
|
||||
edit_names = new QAction( tr("\311diter les noms"), this);
|
||||
edit_ori = new QAction(QIcon(":/ico/orientations.png"), tr("\311diter les orientations"), 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);
|
||||
|
||||
edit_delete -> setEnabled(false);
|
||||
edit_size -> setEnabled(false);
|
||||
edit_hotspot -> setEnabled(false);
|
||||
|
||||
selectall -> setShortcut(QKeySequence::SelectAll);
|
||||
deselectall -> setShortcut(QKeySequence(tr("Ctrl+Shift+A")));
|
||||
inv_select -> setShortcut(QKeySequence(tr("Ctrl+I")));
|
||||
edit_delete -> setShortcut(QKeySequence(tr("Ctrl+Suppr")));
|
||||
|
||||
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(quit, SIGNAL(triggered()), this, SLOT(slot_quit()));
|
||||
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(edit_delete, SIGNAL(triggered()), ce_scene, SLOT(slot_delete()));
|
||||
connect(edit_size, SIGNAL(triggered()), ce_scene, SLOT(slot_editSize()));
|
||||
connect(edit_hotspot, SIGNAL(triggered()), ce_scene, SLOT(slot_editHotSpot()));
|
||||
connect(edit_names, SIGNAL(triggered()), ce_scene, SLOT(slot_editNames()));
|
||||
connect(edit_ori, SIGNAL(triggered()), ce_scene, SLOT(slot_editOrientations()));
|
||||
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);
|
||||
foreach (QAction *action, parts -> actions()) parts_toolbar -> addAction(action);
|
||||
move -> setChecked(true);
|
||||
parts_toolbar -> setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
|
||||
|
||||
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);
|
||||
|
||||
addToolBar(Qt::LeftToolBarArea, parts_toolbar);
|
||||
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()));
|
||||
connect(ce_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateMenus()));
|
||||
}
|
||||
|
||||
void CustomElementEditor::setupMenus() {
|
||||
file_menu = new QMenu(tr("Fichier"));
|
||||
edit_menu = new QMenu(tr("\311dition"));
|
||||
display_menu = new QMenu(tr("Affichage"));
|
||||
tools_menu = new QMenu(tr("Outils"));
|
||||
help_menu = new QMenu(tr("Aide"));
|
||||
|
||||
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 -> addAction(save);
|
||||
file_menu -> addAction(save_as);
|
||||
file_menu -> addSeparator();
|
||||
file_menu -> addAction(quit);
|
||||
|
||||
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);
|
||||
edit_menu -> addAction(edit_hotspot);
|
||||
edit_menu -> addAction(edit_ori);
|
||||
|
||||
menuBar() -> addMenu(file_menu);
|
||||
menuBar() -> addMenu(edit_menu);
|
||||
menuBar() -> addMenu(display_menu);
|
||||
menuBar() -> addMenu(tools_menu);
|
||||
menuBar() -> addMenu(help_menu);
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_updateMenus() {
|
||||
edit_delete -> setEnabled(!ce_scene -> selectedItems().isEmpty());
|
||||
}
|
||||
|
||||
void CustomElementEditor::setupInterface() {
|
||||
// editeur
|
||||
ce_scene = new EditorScene(this);
|
||||
ce_scene -> slot_move();
|
||||
ce_view = new QGraphicsView(ce_scene, this);
|
||||
ce_view -> setInteractive(true);
|
||||
ce_view -> setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
//ce_view -> setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
ce_view -> setResizeAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
//ce_view -> setSceneRect(QRectF(0.0, 0.0, 50.0, 200.0));
|
||||
ce_view -> scale(4.0, 4.0);
|
||||
slot_setRubberBandToView();
|
||||
setCentralWidget(ce_view);
|
||||
|
||||
// widget par defaut dans le QDockWidget
|
||||
default_informations = new QLabel();
|
||||
|
||||
// panel sur le cote
|
||||
tools_dock = new QDockWidget(tr("Informations"), this);
|
||||
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
tools_dock -> setMinimumWidth(285);
|
||||
addDockWidget(Qt::RightDockWidgetArea, tools_dock);
|
||||
QWidget *info_widget = new QWidget();
|
||||
info_widget -> setLayout(new QVBoxLayout(info_widget));
|
||||
tools_dock -> setWidget(info_widget);
|
||||
slot_updateInformations();
|
||||
|
||||
// barre d'etat
|
||||
statusBar() -> showMessage(tr("\311diteur d'\351l\351ments"));
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_setRubberBandToView() {
|
||||
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_setNoDragToView() {
|
||||
ce_view -> setDragMode(QGraphicsView::NoDrag);
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_setNormalMode() {
|
||||
if (!move -> isChecked()) move -> setChecked(true);
|
||||
ce_view -> setDragMode(QGraphicsView::RubberBandDrag);
|
||||
ce_scene -> slot_move();
|
||||
}
|
||||
|
||||
void CustomElementEditor::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 (qli -> widget()) {
|
||||
layout -> removeWidget(qli -> widget());
|
||||
qli -> widget() -> setParent(0);
|
||||
}
|
||||
}
|
||||
if (selected_parts.size() == 1) {
|
||||
// recupere le premier CustomElementPart et en ajoute le widget d'edition
|
||||
layout -> addWidget(selected_parts.first() -> elementInformations());
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomElementEditor::xmlPreview() {
|
||||
QMessageBox::information(
|
||||
this,
|
||||
"Export XML",
|
||||
ce_scene -> toXml().toString(4)
|
||||
);
|
||||
}
|
||||
|
||||
void CustomElementEditor::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);
|
||||
|
||||
// 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
|
||||
_filename = filepath;
|
||||
|
||||
// modifie le titre de la fenetre
|
||||
QString new_title = min_title + " - " + ce_scene -> names().name();
|
||||
if (isReadOnly()) new_title += tr(" [lecture seule]");
|
||||
setWindowTitle(new_title);
|
||||
}
|
||||
|
||||
bool CustomElementEditor::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 CustomElementEditor::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
|
||||
edit_size -> setEnabled(!ro);
|
||||
edit_hotspot -> setEnabled(!ro);
|
||||
edit_names -> setEnabled(!ro);
|
||||
edit_ori -> setEnabled(!ro);
|
||||
}
|
||||
|
||||
/**
|
||||
@return true si l'editeur d'element est en mode lecture seule
|
||||
*/
|
||||
bool CustomElementEditor::isReadOnly() const {
|
||||
return(read_only);
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_new() {
|
||||
NewElementWizard new_element_wizard;
|
||||
new_element_wizard.exec();
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_open() {
|
||||
// demande un nom de fichier a ouvrir a l'utilisateur
|
||||
QString user_filename = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
tr("Ouvrir un fichier"),
|
||||
QETApp::customElementsDir(),
|
||||
tr("\311l\351ments QElectroTech (*.elmt);;Fichiers XML (*.xml);;Tous les fichiers (*)")
|
||||
);
|
||||
if (user_filename == "") return;
|
||||
CustomElementEditor *cee = new CustomElementEditor();
|
||||
cee -> fromFile(user_filename);
|
||||
cee -> show();
|
||||
}
|
||||
|
||||
bool CustomElementEditor::slot_save() {
|
||||
// si on ne connait pas le nom du fichier en cours, enregistrer revient a enregistrer sous
|
||||
if (_filename == QString()) return(slot_saveAs());
|
||||
// sinon on enregistre dans le nom de fichier connu
|
||||
return(toFile(_filename));
|
||||
}
|
||||
|
||||
bool CustomElementEditor::slot_saveAs() {
|
||||
// demande un nom de fichier a l'utilisateur pour enregistrer l'element
|
||||
QString fn = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
tr("Enregistrer sous"),
|
||||
QETApp::customElementsDir(),
|
||||
tr("\311l\351ments QElectroTech (*.elmt)")
|
||||
);
|
||||
// si aucun nom n'est entre, renvoie faux.
|
||||
if (fn == "") 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);
|
||||
// retourne un booleen representatif de la reussite de l'enregistrement
|
||||
return(result_save);
|
||||
}
|
||||
|
||||
void CustomElementEditor::slot_quit(QCloseEvent *event) {
|
||||
if (close()) {
|
||||
if (event != NULL) event -> accept();
|
||||
delete(this);
|
||||
} else if (event != NULL) event -> ignore();
|
||||
}
|
||||
|
||||
bool CustomElementEditor::close() {
|
||||
// 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 CustomElementEditor::closeEvent(QCloseEvent *qce) {
|
||||
slot_quit(qce);
|
||||
}
|
||||
128
editor/customelementeditor.h
Normal file
128
editor/customelementeditor.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#ifndef CUSTOM_ELEMENT_EDITOR_H
|
||||
#define CUSTOM_ELEMENT_EDITOR_H
|
||||
#include <QtGui>
|
||||
#include "editorscene.h"
|
||||
#include "orientationset.h"
|
||||
class CustomElementEditor : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
// constructeur, destructeur
|
||||
public:
|
||||
CustomElementEditor(QWidget * = 0);
|
||||
virtual ~CustomElementEditor();
|
||||
private:
|
||||
CustomElementEditor(const CustomElementEditor &);
|
||||
|
||||
// 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
|
||||
QGraphicsView *ce_view;
|
||||
/// scene d'edition
|
||||
EditorScene *ce_scene;
|
||||
/// container pour les widgets d'edition des parties
|
||||
QDockWidget *tools_dock;
|
||||
/// actions du menu fichier
|
||||
QAction *new_element, *open, *save, *save_as, *quit;
|
||||
/// actions du menu edition
|
||||
QAction *selectall, *deselectall, *inv_select;
|
||||
QAction *edit_delete, *edit_size, *edit_hotspot, *edit_names, *edit_ori;
|
||||
/// barre d'outils
|
||||
QToolBar *parts_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 &);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
||||
private:
|
||||
void setupActions();
|
||||
void setupMenus();
|
||||
void setupInterface();
|
||||
bool close();
|
||||
|
||||
public slots:
|
||||
void slot_new();
|
||||
void slot_open();
|
||||
bool slot_save();
|
||||
bool slot_saveAs();
|
||||
void slot_quit(QCloseEvent * = NULL);
|
||||
void slot_setRubberBandToView();
|
||||
void slot_setNoDragToView();
|
||||
void slot_setNormalMode();
|
||||
void slot_updateInformations();
|
||||
void slot_updateMenus();
|
||||
void xmlPreview();
|
||||
};
|
||||
|
||||
inline void CustomElementEditor::setSize(const QSize &siz) {
|
||||
ce_scene -> setWidth(siz.width());
|
||||
ce_scene -> setHeight(siz.height());
|
||||
}
|
||||
|
||||
inline QSize CustomElementEditor::size() const {
|
||||
return(
|
||||
QSize(
|
||||
ce_scene -> width(),
|
||||
ce_scene -> height()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline void CustomElementEditor::setHotspot(const QPoint &hs) {
|
||||
ce_scene -> setHotspot(hs);
|
||||
}
|
||||
|
||||
inline QPoint CustomElementEditor::hotspot() const {
|
||||
return(ce_scene -> hotspot());
|
||||
}
|
||||
|
||||
inline void CustomElementEditor::setNames(const NamesList &nameslist) {
|
||||
ce_scene -> setNames(nameslist);
|
||||
}
|
||||
|
||||
inline void CustomElementEditor::setOrientations(const OrientationSet &orientation_set) {
|
||||
ce_scene -> setOrientations(orientation_set);
|
||||
}
|
||||
|
||||
inline OrientationSet CustomElementEditor::orientations() const {
|
||||
return(ce_scene -> orientations());
|
||||
}
|
||||
|
||||
inline void CustomElementEditor::setFileName(const QString &fn) {
|
||||
setWindowTitle(min_title + " - " + fn);
|
||||
_filename = fn;
|
||||
}
|
||||
|
||||
inline QString CustomElementEditor::fileName() const {
|
||||
return(_filename);
|
||||
}
|
||||
|
||||
#endif
|
||||
133
editor/customelementgraphicpart.cpp
Normal file
133
editor/customelementgraphicpart.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#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);
|
||||
}
|
||||
145
editor/customelementgraphicpart.h
Normal file
145
editor/customelementgraphicpart.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef CUSTOM_ELEMENT_GRAPHIC_PART_H
|
||||
#define CUSTOM_ELEMENT_GRAPHIC_PART_H
|
||||
#include <QPainter>
|
||||
#include "customelementpart.h"
|
||||
#include "styleeditor.h"
|
||||
/**
|
||||
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
|
||||
*/
|
||||
typedef CustomElementGraphicPart CEGP;
|
||||
class CustomElementGraphicPart : public CustomElementPart {
|
||||
public:
|
||||
enum LineStyle { NormalStyle, DashedStyle };
|
||||
enum LineWeight { NormalWeight, ThinWeight, NoneWeight };
|
||||
enum Filling { NoneFilling, BlackFilling, WhiteFilling };
|
||||
enum Color { BlackColor, WhiteColor };
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
CustomElementGraphicPart() :
|
||||
_linestyle(NormalStyle),
|
||||
_lineweight(NormalWeight),
|
||||
_filling(NoneFilling),
|
||||
_color(BlackColor),
|
||||
_antialiased(false)
|
||||
{
|
||||
style_editor = new StyleEditor(this);
|
||||
};
|
||||
|
||||
virtual ~CustomElementGraphicPart() {
|
||||
qDebug() << "~CustomElementGraphicPart()";
|
||||
delete style_editor;
|
||||
};
|
||||
|
||||
// attributs
|
||||
private:
|
||||
LineStyle _linestyle;
|
||||
LineWeight _lineweight;
|
||||
Filling _filling ;
|
||||
Color _color;
|
||||
bool _antialiased;
|
||||
|
||||
protected:
|
||||
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();
|
||||
|
||||
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
|
||||
6
editor/customelementpart.cpp
Normal file
6
editor/customelementpart.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "customelementpart.h"
|
||||
#include "customelement.h"
|
||||
|
||||
QPicture *CustomElementPart::getCustomElementQPicture(CustomElement &ce) const {
|
||||
return(&(ce.dessin));
|
||||
}
|
||||
39
editor/customelementpart.h
Normal file
39
editor/customelementpart.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef CUSTOM_ELEMENT_PART_H
|
||||
#define CUSTOM_ELEMENT_PART_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include <QImage>
|
||||
class CustomElement;
|
||||
/**
|
||||
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:
|
||||
CustomElementPart() {};
|
||||
virtual ~CustomElementPart() {
|
||||
qDebug() << "~CustomElementPart()";
|
||||
};
|
||||
private:
|
||||
CustomElementPart(const CustomElementPart &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void fromXml(const QDomElement &) = 0;
|
||||
virtual const QDomElement toXml(QDomDocument &) const = 0;
|
||||
virtual QWidget *elementInformations() = 0;
|
||||
//virtual void renderToCustomElement(CustomElement &) const = 0;
|
||||
//virtual void toEditorPart(const EditorPart &);
|
||||
//virtual void fromEditorPart(const EditorPart &) = 0;
|
||||
protected:
|
||||
QPicture *getCustomElementQPicture(CustomElement &ce) const;
|
||||
};
|
||||
#endif
|
||||
447
editor/editorscene.cpp
Normal file
447
editor/editorscene.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
#include "editorscene.h"
|
||||
#include <cmath>
|
||||
#include "partline.h"
|
||||
#include "partellipse.h"
|
||||
#include "partcircle.h"
|
||||
#include "partpolygon.h"
|
||||
#include "partterminal.h"
|
||||
#include "parttext.h"
|
||||
#define GRILLE_X 10
|
||||
#define GRILLE_Y 10
|
||||
|
||||
EditorScene::EditorScene(QObject *parent) :
|
||||
QGraphicsScene(parent),
|
||||
_width(3),
|
||||
_height(7),
|
||||
_hotspot(15, 35)
|
||||
{
|
||||
current_polygon = NULL;
|
||||
connect(this, SIGNAL(changed(const QList<QRectF> &)), this, SLOT(slot_checkSelectionChanged()));
|
||||
}
|
||||
|
||||
EditorScene::~EditorScene() {
|
||||
qDebug() << "~EditorScene()";
|
||||
}
|
||||
|
||||
void EditorScene::slot_move() {
|
||||
behavior = Normal;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addLine() {
|
||||
behavior = Line;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addCircle() {
|
||||
behavior = Circle;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addEllipse() {
|
||||
behavior = Ellipse;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addPolygon() {
|
||||
behavior = Polygon;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addText() {
|
||||
behavior = Text;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addTerminal() {
|
||||
behavior = Terminal;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addArc() {
|
||||
behavior = Arc;
|
||||
}
|
||||
|
||||
void EditorScene::slot_addTextField() {
|
||||
behavior = TextField;
|
||||
}
|
||||
|
||||
void EditorScene::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 Normal:
|
||||
QGraphicsScene::mouseMoveEvent(e);
|
||||
break;
|
||||
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 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;
|
||||
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);
|
||||
}
|
||||
|
||||
void EditorScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
QPolygonF temp_polygon;
|
||||
if (e -> button() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Normal:
|
||||
QGraphicsScene::mousePressEvent(e);
|
||||
break;
|
||||
case Line:
|
||||
current_line = new PartLine(0, this);
|
||||
current_line -> setLine(QLineF(e -> scenePos(), e -> scenePos()));
|
||||
break;
|
||||
case Ellipse:
|
||||
current_ellipse = new PartEllipse(0, this);
|
||||
current_ellipse -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
||||
break;
|
||||
case Circle:
|
||||
current_circle = new PartCircle(0, this);
|
||||
current_circle -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
||||
break;
|
||||
case Polygon:
|
||||
if (current_polygon == NULL) {
|
||||
current_polygon = new PartPolygon(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;
|
||||
default:
|
||||
QGraphicsScene::mousePressEvent(e);
|
||||
}
|
||||
} else QGraphicsScene::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void EditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
PartTerminal *terminal;
|
||||
PartText *text;
|
||||
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
||||
if (e -> button() & Qt::LeftButton) {
|
||||
switch(behavior) {
|
||||
case Normal:
|
||||
QGraphicsScene::mouseReleaseEvent(e);
|
||||
break;
|
||||
case Line:
|
||||
break;
|
||||
case Ellipse:
|
||||
current_ellipse -> setRect(current_ellipse -> rect().normalized());
|
||||
break;
|
||||
case Circle:
|
||||
current_circle -> setRect(current_circle -> rect().normalized());
|
||||
break;
|
||||
case Terminal:
|
||||
terminal = new PartTerminal(0, this);
|
||||
terminal -> setPos(e -> scenePos());
|
||||
break;
|
||||
case Text:
|
||||
text = new PartText(0, this);
|
||||
text -> setPos(e -> scenePos());
|
||||
break;
|
||||
default:
|
||||
QGraphicsScene::mouseReleaseEvent(e);
|
||||
}
|
||||
} else if (e -> button() & Qt::RightButton) {
|
||||
if (behavior == Polygon) {
|
||||
behavior = Normal;
|
||||
current_polygon = NULL;
|
||||
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 EditorScene::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 % GRILLE_X) ++ g_x;
|
||||
int g_y = (int)ceil(r.y());
|
||||
while (g_y % GRILLE_Y) ++ g_y;
|
||||
|
||||
for (int gx = g_x ; gx < limite_x ; gx += GRILLE_X) {
|
||||
for (int gy = g_y ; gy < limite_y ; gy += GRILLE_Y) {
|
||||
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 EditorScene::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();
|
||||
}
|
||||
|
||||
const QDomDocument EditorScene::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());
|
||||
|
||||
// noms de l'element
|
||||
root.appendChild(_names.toXml(xml_document));
|
||||
|
||||
QDomElement description = xml_document.createElement("description");
|
||||
// description de l'element
|
||||
foreach(QGraphicsItem *qgi, items()) {
|
||||
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
|
||||
description.appendChild(ce -> toXml(xml_document));
|
||||
}
|
||||
}
|
||||
root.appendChild(description);
|
||||
|
||||
xml_document.appendChild(root);
|
||||
return(xml_document);
|
||||
}
|
||||
|
||||
void EditorScene::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
|
||||
if (state) {
|
||||
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 (0, this);
|
||||
else if (qde.tagName() == "ellipse") cep = new PartEllipse (0, this);
|
||||
else if (qde.tagName() == "circle") cep = new PartCircle (0, this);
|
||||
else if (qde.tagName() == "polygon") cep = new PartPolygon (0, this);
|
||||
else if (qde.tagName() == "terminal") cep = new PartTerminal(0, this);
|
||||
else if (qde.tagName() == "text") cep = new PartText (0, this);
|
||||
else continue;
|
||||
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) qgi -> setZValue(z++);
|
||||
cep -> fromXml(qde);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorScene::slot_checkSelectionChanged() {
|
||||
static QList<QGraphicsItem *> cache_selecteditems = QList<QGraphicsItem *>();
|
||||
QList<QGraphicsItem *> selecteditems = selectedItems();
|
||||
if (cache_selecteditems != selecteditems) emit(selectionChanged());
|
||||
cache_selecteditems = selecteditems;
|
||||
}
|
||||
|
||||
void EditorScene::slot_selectAll() {
|
||||
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
|
||||
}
|
||||
|
||||
void EditorScene::slot_deselectAll() {
|
||||
clearSelection();
|
||||
}
|
||||
|
||||
void EditorScene::slot_invertSelection() {
|
||||
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(!qgi -> isSelected());
|
||||
}
|
||||
|
||||
void EditorScene::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
|
||||
foreach(QGraphicsItem *qgi, selected_items) {
|
||||
removeItem(qgi);
|
||||
delete qgi;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorScene::slot_editSize() {
|
||||
|
||||
}
|
||||
|
||||
void EditorScene::slot_editHotSpot() {
|
||||
|
||||
}
|
||||
|
||||
void EditorScene::slot_editOrientations() {
|
||||
|
||||
// cree un dialogue
|
||||
QDialog dialog_ori;
|
||||
dialog_ori.setModal(true);
|
||||
dialog_ori.setFixedSize(400, 230);
|
||||
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 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) ori = ori_widget -> orientationSet();
|
||||
}
|
||||
|
||||
void EditorScene::slot_editNames() {
|
||||
|
||||
// cree un dialogue
|
||||
QDialog dialog;
|
||||
dialog.setModal(true);
|
||||
dialog.setFixedSize(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) _names = names_widget -> names();
|
||||
}
|
||||
|
||||
136
editor/editorscene.h
Normal file
136
editor/editorscene.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef EDITOR_SCNE_H
|
||||
#define EDITOR_SCNE_H
|
||||
#include <QtGui>
|
||||
#include <QtXml>
|
||||
#include "nameslistwidget.h"
|
||||
#include "orientationsetwidget.h"
|
||||
class PartLine;
|
||||
class PartEllipse;
|
||||
class PartCircle;
|
||||
class PartPolygon;
|
||||
class EditorScene : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
|
||||
// enum
|
||||
enum Behavior { Normal, Line, Circle, Ellipse, Polygon, Text, Terminal, Arc, TextField };
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
EditorScene(QObject * = 0);
|
||||
virtual ~EditorScene();
|
||||
|
||||
private:
|
||||
EditorScene(const EditorScene &);
|
||||
|
||||
// attributs
|
||||
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;
|
||||
|
||||
/// 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;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void setWidth(const uint& theValue);
|
||||
uint width() const;
|
||||
void setHeight(const uint& theValue);
|
||||
uint height() const;
|
||||
void setHotspot(const QPoint &);
|
||||
QPoint hotspot() const;
|
||||
void setNames(const NamesList);
|
||||
NamesList names() const;
|
||||
OrientationSet orientations();
|
||||
void setOrientations(const OrientationSet &);
|
||||
virtual const QDomDocument toXml() const;
|
||||
virtual void fromXml(const QDomDocument &);
|
||||
|
||||
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_checkSelectionChanged();
|
||||
void slot_selectAll();
|
||||
void slot_deselectAll();
|
||||
void slot_invertSelection();
|
||||
void slot_delete();
|
||||
void slot_editSize();
|
||||
void slot_editHotSpot();
|
||||
void slot_editNames();
|
||||
void slot_editOrientations();
|
||||
|
||||
signals:
|
||||
void selectionChanged();
|
||||
void needNormalMode();
|
||||
};
|
||||
|
||||
inline void EditorScene::setWidth(const uint &wid) {
|
||||
_width = wid;
|
||||
while (_width % 10) ++ _width;
|
||||
_width /= 10;
|
||||
}
|
||||
|
||||
inline uint EditorScene::width() const {
|
||||
return(_width * 10);
|
||||
}
|
||||
|
||||
inline void EditorScene::setHeight(const uint &hei) {
|
||||
_height = hei;
|
||||
while (_height % 10) ++ _height;
|
||||
_height /= 10;
|
||||
}
|
||||
|
||||
inline uint EditorScene::height() const {
|
||||
return(_height * 10);
|
||||
}
|
||||
|
||||
inline void EditorScene::setHotspot(const QPoint &hs) {
|
||||
_hotspot = hs;
|
||||
}
|
||||
|
||||
inline QPoint EditorScene::hotspot() const {
|
||||
return(_hotspot);
|
||||
}
|
||||
|
||||
inline void EditorScene::setNames(const NamesList nameslist) {
|
||||
_names = nameslist;
|
||||
}
|
||||
|
||||
inline NamesList EditorScene::names() const {
|
||||
return(_names);
|
||||
}
|
||||
|
||||
inline OrientationSet EditorScene::orientations() {
|
||||
return(ori);
|
||||
}
|
||||
|
||||
inline void EditorScene::setOrientations(const OrientationSet &orientation_set) {
|
||||
ori = orientation_set;
|
||||
}
|
||||
|
||||
#endif
|
||||
66
editor/ellipseeditor.cpp
Normal file
66
editor/ellipseeditor.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "ellipseeditor.h"
|
||||
#include "partellipse.h"
|
||||
|
||||
EllipseEditor::EllipseEditor(PartEllipse *ellipse, QWidget *parent) : QWidget(parent) {
|
||||
|
||||
part = ellipse;
|
||||
|
||||
x = new QLineEdit();
|
||||
y = new QLineEdit();
|
||||
h = new QLineEdit();
|
||||
v = new QLineEdit();
|
||||
|
||||
// QDoubleValidator *format = new QDoubleValidator(-1000.0, -1000.0, 4, this);
|
||||
// x -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
|
||||
// y -> setValidator(new QDoubleValidator(-1000.0, 1000.0, 4, this));
|
||||
// h -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
|
||||
// v -> setValidator(new QDoubleValidator(0.0, 1000.0, 4, this));
|
||||
|
||||
|
||||
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);
|
||||
|
||||
updateForm();
|
||||
|
||||
connect(x, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
|
||||
connect(y, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
|
||||
connect(h, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
|
||||
connect(v, SIGNAL(editingFinished()), this, SLOT(updateEllipse()));
|
||||
}
|
||||
|
||||
EllipseEditor::~EllipseEditor() {
|
||||
qDebug() << "~EllipseEditor()";
|
||||
}
|
||||
|
||||
void EllipseEditor::updateEllipse() {
|
||||
qreal _x = x -> text().toDouble();
|
||||
qreal _y = y -> text().toDouble();
|
||||
qreal _h = h -> text().toDouble();
|
||||
qreal _v = v -> text().toDouble();
|
||||
_v = _v < 0 ? -_v : _v;
|
||||
part -> setRect(
|
||||
QRectF(
|
||||
part -> mapFromScene(QPointF(_x - (_h / 2.0), _y - (_v / 2.0))),
|
||||
QSizeF(_h, _v)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void EllipseEditor::updateForm() {
|
||||
qreal _h = part -> rect().width();
|
||||
qreal _v = part -> rect().height();
|
||||
QPointF top_left(part -> sceneTopLeft());
|
||||
x -> setText(QString("%1").arg(top_left.x() + (_h / 2.0)));
|
||||
y -> setText(QString("%1").arg(top_left.y() + (_v / 2.0)));
|
||||
h -> setText(QString("%1").arg(_h));
|
||||
v -> setText(QString("%1").arg(_v));
|
||||
}
|
||||
24
editor/ellipseeditor.h
Normal file
24
editor/ellipseeditor.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef ELLIPSE_EDITOR_H
|
||||
#define ELLIPSE_EDITOR_H
|
||||
#include <QtGui>
|
||||
class PartEllipse;
|
||||
class EllipseEditor : public QWidget {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
EllipseEditor(PartEllipse *, QWidget * = 0);
|
||||
~EllipseEditor();
|
||||
private:
|
||||
EllipseEditor(const EllipseEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartEllipse *part;
|
||||
QLineEdit *x, *y, *h, *v;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateEllipse();
|
||||
void updateForm();
|
||||
};
|
||||
#endif
|
||||
57
editor/lineeditor.cpp
Normal file
57
editor/lineeditor.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "lineeditor.h"
|
||||
#include "partline.h"
|
||||
|
||||
LineEditor::LineEditor(PartLine *line, QWidget *parent) : QWidget(parent) {
|
||||
|
||||
part = line;
|
||||
|
||||
x1 = new QLineEdit();
|
||||
y1 = new QLineEdit();
|
||||
x2 = new QLineEdit();
|
||||
y2 = new QLineEdit();
|
||||
|
||||
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();
|
||||
|
||||
connect(x1, SIGNAL(editingFinished()), this, SLOT(updateLine()));
|
||||
connect(y1, SIGNAL(editingFinished()), this, SLOT(updateLine()));
|
||||
connect(x2, SIGNAL(editingFinished()), this, SLOT(updateLine()));
|
||||
connect(y2, SIGNAL(editingFinished()), this, SLOT(updateLine()));
|
||||
}
|
||||
|
||||
LineEditor::~LineEditor() {
|
||||
qDebug() << "~LineEditor()";
|
||||
}
|
||||
|
||||
void LineEditor::updateLine() {
|
||||
part -> setLine(
|
||||
QLineF(
|
||||
part -> mapFromScene(
|
||||
x1 -> text().toDouble(),
|
||||
y1 -> text().toDouble()
|
||||
),
|
||||
part -> mapFromScene(
|
||||
x2 -> text().toDouble(),
|
||||
y2 -> text().toDouble()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void LineEditor::updateForm() {
|
||||
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()));
|
||||
}
|
||||
24
editor/lineeditor.h
Normal file
24
editor/lineeditor.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef LINE_EDITOR_H
|
||||
#define LINE_EDITOR_H
|
||||
#include <QtGui>
|
||||
class PartLine;
|
||||
class LineEditor : public QWidget {
|
||||
Q_OBJECT
|
||||
//constructeurs, destructeur
|
||||
public:
|
||||
LineEditor(PartLine *, QWidget * = 0);
|
||||
~LineEditor();
|
||||
private:
|
||||
LineEditor(const LineEditor &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
PartLine *part;
|
||||
QLineEdit *x1, *y1, *x2, *y2;
|
||||
|
||||
// methodes
|
||||
public slots:
|
||||
void updateLine();
|
||||
void updateForm();
|
||||
};
|
||||
#endif
|
||||
77
editor/partcircle.cpp
Normal file
77
editor/partcircle.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "partcircle.h"
|
||||
#include "circleeditor.h"
|
||||
|
||||
PartCircle::PartCircle(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart() {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new CircleEditor(this);
|
||||
style_editor -> appendWidget(informations);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
QVariant PartCircle::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsEllipseItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
QPointF PartCircle::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
|
||||
QPointF PartCircle::sceneCenter() const {
|
||||
return(mapToScene(rect().center()));
|
||||
}
|
||||
|
||||
QRectF PartCircle::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsEllipseItem::boundingRect());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
33
editor/partcircle.h
Normal file
33
editor/partcircle.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef PART_CIRCLE_H
|
||||
#define PART_CIRCLE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class CircleEditor;
|
||||
class PartCircle : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartCircle(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartCircle() {
|
||||
qDebug() << "~PartCircle()";
|
||||
}
|
||||
|
||||
private:
|
||||
PartCircle(const PartCircle &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
CircleEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
virtual QRectF boundingRect() const;
|
||||
QPointF sceneCenter() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
#endif
|
||||
66
editor/partellipse.cpp
Normal file
66
editor/partellipse.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "partellipse.h"
|
||||
#include "ellipseeditor.h"
|
||||
|
||||
PartEllipse::PartEllipse(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsEllipseItem(parent, scene), CustomElementGraphicPart() {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new EllipseEditor(this);
|
||||
style_editor -> appendWidget(informations);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
QVariant PartEllipse::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsEllipseItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
QPointF PartEllipse::sceneTopLeft() const {
|
||||
return(mapToScene(rect().topLeft()));
|
||||
}
|
||||
31
editor/partellipse.h
Normal file
31
editor/partellipse.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef PART_ELLIPSE_H
|
||||
#define PART_ELLIPSE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class EllipseEditor;
|
||||
class PartEllipse : public QGraphicsEllipseItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartEllipse(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartEllipse() {
|
||||
qDebug() << "~PartEllipse()";
|
||||
}
|
||||
|
||||
private:
|
||||
PartEllipse(const PartEllipse &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
EllipseEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
virtual const QDomElement toXml(QDomDocument &) const;
|
||||
virtual void fromXml(const QDomElement &);
|
||||
virtual QPointF sceneTopLeft() const;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
};
|
||||
#endif
|
||||
143
editor/partline.cpp
Normal file
143
editor/partline.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "partline.h"
|
||||
#include "lineeditor.h"
|
||||
#include <cmath>
|
||||
|
||||
PartLine::PartLine(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsLineItem(parent, scene), CustomElementGraphicPart() {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new LineEditor(this);
|
||||
style_editor -> appendWidget(informations);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
const QDomElement PartLine::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("line");
|
||||
QPointF p1(sceneP1());
|
||||
QPointF p2(sceneP2());
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
QVariant PartLine::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsLineItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
QPointF PartLine::sceneP1() const {
|
||||
return(mapToScene(line().p1()));
|
||||
}
|
||||
|
||||
QPointF PartLine::sceneP2() const {
|
||||
return(mapToScene(line().p2()));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
QRectF PartLine::boundingRect() const {
|
||||
QList<QPointF> points = fourShapePoints();
|
||||
qreal min_x = points.first().x();
|
||||
qreal max_x = points.first().x();
|
||||
qreal min_y = points.first().y();
|
||||
qreal max_y = points.first().y();
|
||||
foreach(QPointF p, points) {
|
||||
if (p.x() > max_x) max_x = p.x();
|
||||
if (p.x() < min_x) min_x = p.x();
|
||||
if (p.y() > max_y) max_y = p.y();
|
||||
if (p.y() < min_y) min_y = p.y();
|
||||
}
|
||||
QRectF r;
|
||||
r.setCoords(min_x, min_y, max_x, max_y);
|
||||
return(r);
|
||||
}
|
||||
*/
|
||||
/**
|
||||
@return une liste contenant les deux points de la droite + les 4 points entourant ces deux points
|
||||
*/
|
||||
QList<QPointF> PartLine::fourShapePoints() const {
|
||||
// on a donc A(xa , ya) et B(xb, yb)
|
||||
QPointF a = line().p1();
|
||||
QPointF b = line().p2();
|
||||
|
||||
// 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 * 2.0;
|
||||
|
||||
// on définit le vecteur v(-b , a) qui est perpendiculaire à 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
|
||||
|
||||
QList<QPointF> result;
|
||||
result << h << i << j << k;
|
||||
return(result);
|
||||
}
|
||||
|
||||
QRectF PartLine::boundingRect() const {
|
||||
qreal adjust = 1.5;
|
||||
QRectF r(QGraphicsLineItem::boundingRect());
|
||||
r.adjust(-adjust, -adjust, adjust, adjust);
|
||||
return(r);
|
||||
}
|
||||
37
editor/partline.h
Normal file
37
editor/partline.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef PART_LINE_H
|
||||
#define PART_LINE_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class LineEditor;
|
||||
class PartLine : public QGraphicsLineItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartLine(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartLine() {
|
||||
qDebug() << "~PartLine()";
|
||||
}
|
||||
|
||||
private:
|
||||
PartLine(const PartLine &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
LineEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0);
|
||||
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;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
|
||||
private:
|
||||
QList<QPointF> fourShapePoints() const;
|
||||
};
|
||||
#endif
|
||||
69
editor/partpolygon.cpp
Normal file
69
editor/partpolygon.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "partpolygon.h"
|
||||
#include "qet.h"
|
||||
#include "polygoneditor.h"
|
||||
PartPolygon::PartPolygon(QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
QGraphicsPolygonItem(parent, scene),
|
||||
CustomElementGraphicPart(),
|
||||
closed(false)
|
||||
{
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
informations = new PolygonEditor(this);
|
||||
style_editor -> appendWidget(informations);
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("polygon");
|
||||
int i = 1;
|
||||
foreach(QPointF point, polygon()) {
|
||||
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);
|
||||
}
|
||||
|
||||
void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem */*q*/, QWidget */*w*/) {
|
||||
applyStylesToQPainter(*painter);
|
||||
QPen t = painter -> pen();
|
||||
if (isSelected()) {
|
||||
t.setColor(Qt::red);
|
||||
painter -> setPen(t);
|
||||
}
|
||||
if (closed) painter -> drawPolygon(polygon());
|
||||
else painter -> drawPolyline(polygon());
|
||||
}
|
||||
|
||||
QVariant PartPolygon::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsPolygonItem::itemChange(change, value));
|
||||
}
|
||||
61
editor/partpolygon.h
Normal file
61
editor/partpolygon.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef PART_POLYGON_H
|
||||
#define PART_POLYGON_H
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class PolygonEditor;
|
||||
class PartPolygon : public QGraphicsPolygonItem, public CustomElementGraphicPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartPolygon(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartPolygon() {
|
||||
qDebug() << "~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:
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
|
||||
void setClosed(bool c);
|
||||
bool isClosed() 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
|
||||
117
editor/partterminal.cpp
Normal file
117
editor/partterminal.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "partterminal.h"
|
||||
#include "terminal.h"
|
||||
#include "terminaleditor.h"
|
||||
|
||||
PartTerminal::PartTerminal(QGraphicsItem *parent, QGraphicsScene *scene) :
|
||||
CustomElementPart(),
|
||||
QGraphicsItem(parent, scene),
|
||||
_orientation(QET::North)
|
||||
{
|
||||
informations = new TerminalEditor(this);
|
||||
updateSecondPoint();
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setZValue(100000);
|
||||
}
|
||||
|
||||
PartTerminal::~PartTerminal() {
|
||||
qDebug() << "~PartTerminal()";
|
||||
delete informations;
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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(pos().x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg(pos().y()));
|
||||
|
||||
// ecrit l'orientation de la borne
|
||||
xml_element.setAttribute("orientation", orientationToString(_orientation));
|
||||
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
QWidget *PartTerminal::elementInformations() {
|
||||
return(informations);
|
||||
}
|
||||
|
||||
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(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(Terminal::couleur_neutre);
|
||||
p -> setPen(t);
|
||||
p -> setBrush(Terminal::couleur_neutre);
|
||||
p -> drawPoint(QPointF(0.0, 0.0));
|
||||
p -> restore();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
QET::Orientation PartTerminal::orientation() const {
|
||||
return(_orientation);
|
||||
}
|
||||
|
||||
void PartTerminal::setOrientation(QET::Orientation ori) {
|
||||
prepareGeometryChange();
|
||||
_orientation = ori;
|
||||
updateSecondPoint();
|
||||
informations -> updateForm();
|
||||
}
|
||||
|
||||
QVariant PartTerminal::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene()) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
informations -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
37
editor/partterminal.h
Normal file
37
editor/partterminal.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef PART_TERMINAL_H
|
||||
#define PART_TERMINAL_H
|
||||
#include "customelementpart.h"
|
||||
#include "qet.h"
|
||||
#include <QtGui>
|
||||
class TerminalEditor;
|
||||
class PartTerminal : public CustomElementPart, public QGraphicsItem {
|
||||
public:
|
||||
// constructeurs, destructeur
|
||||
PartTerminal(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartTerminal();
|
||||
private:
|
||||
PartTerminal(const PartTerminal &);
|
||||
|
||||
// attributs
|
||||
private:
|
||||
QET::Orientation _orientation;
|
||||
QPointF second_point;
|
||||
TerminalEditor *informations;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
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);
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
|
||||
private:
|
||||
void updateSecondPoint();
|
||||
};
|
||||
#endif
|
||||
104
editor/parttext.cpp
Normal file
104
editor/parttext.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
#include "parttext.h"
|
||||
#include "texteditor.h"
|
||||
|
||||
PartText::PartText(QGraphicsItem *parent, QGraphicsScene *scene) : QGraphicsTextItem(parent, scene), CustomElementPart(), can_check_changes(true) {
|
||||
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
||||
setPlainText(tr("T"));
|
||||
infos = new TextEditor(this);
|
||||
}
|
||||
|
||||
PartText::~PartText() {
|
||||
qDebug() << "~PartText()";
|
||||
delete infos;
|
||||
}
|
||||
|
||||
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("Sans Serif"), font_size));
|
||||
setPlainText(xml_element.attribute("text"));
|
||||
setPos(
|
||||
xml_element.attribute("x").toDouble(),
|
||||
xml_element.attribute("y").toDouble()
|
||||
);
|
||||
}
|
||||
|
||||
const QDomElement PartText::toXml(QDomDocument &xml_document) const {
|
||||
QDomElement xml_element = xml_document.createElement("text");
|
||||
xml_element.setAttribute("x", QString("%1").arg(pos().x()));
|
||||
xml_element.setAttribute("y", QString("%1").arg(pos().y()));
|
||||
xml_element.setAttribute("text", toPlainText());
|
||||
xml_element.setAttribute("size", font().pointSize());
|
||||
return(xml_element);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
void PartText::setPos(const QPointF &left_corner_pos) {
|
||||
QGraphicsTextItem::setPos(left_corner_pos - margin());
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
QGraphicsTextItem::mouseDoubleClickEvent(e);
|
||||
setFocus(Qt::MouseFocusReason);
|
||||
}
|
||||
|
||||
QVariant PartText::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (scene() && can_check_changes) {
|
||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) {
|
||||
infos -> updateForm();
|
||||
}
|
||||
}
|
||||
return(QGraphicsTextItem::itemChange(change, value));
|
||||
}
|
||||
|
||||
QRectF PartText::boundingRect() const {
|
||||
QRectF r = QGraphicsTextItem::boundingRect();
|
||||
r.adjust(0.0, -2.0, 0.0, 0.0);
|
||||
return(r);
|
||||
}
|
||||
39
editor/parttext.h
Normal file
39
editor/parttext.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef PART_TEXT
|
||||
#define PART_TEXT
|
||||
#include <QtGui>
|
||||
#include "customelementgraphicpart.h"
|
||||
class TextEditor;
|
||||
class PartText : public QGraphicsTextItem, public CustomElementPart {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PartText(QGraphicsItem * = 0, QGraphicsScene * = 0);
|
||||
virtual ~PartText();
|
||||
|
||||
private:
|
||||
PartText(const PartText &);
|
||||
|
||||
// attributs
|
||||
TextEditor *infos;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
void fromXml(const QDomElement &);
|
||||
const QDomElement toXml(QDomDocument &) const;
|
||||
QWidget *elementInformations();
|
||||
QPointF pos() const;
|
||||
void setPos(const QPointF &);
|
||||
void setPos(qreal, qreal);
|
||||
|
||||
protected:
|
||||
virtual void focusOutEvent(QFocusEvent *);
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *);
|
||||
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
|
||||
QRectF boundingRect() const;
|
||||
|
||||
public:
|
||||
bool can_check_changes;
|
||||
|
||||
private:
|
||||
QPointF margin() const;
|
||||
};
|
||||
#endif
|
||||
89
editor/polygoneditor.cpp
Normal file
89
editor/polygoneditor.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "polygoneditor.h"
|
||||
#include "partpolygon.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param p Le polygone a editer
|
||||
@param parent le Widget parent
|
||||
*/
|
||||
PolygonEditor::PolygonEditor(PartPolygon *p, QWidget *parent) :
|
||||
QWidget(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);
|
||||
|
||||
// connexions signaux/slots
|
||||
connect(&close_polygon, SIGNAL(stateChanged(int)), this, SLOT(updatePolygonClosedState()));
|
||||
connect(&points_list, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(validColumn(QTreeWidgetItem *, int)));
|
||||
}
|
||||
|
||||
void PolygonEditor::updatePolygon() {
|
||||
updatePolygonPoints();
|
||||
updatePolygonClosedState();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
part -> setPolygon(points);
|
||||
}
|
||||
|
||||
void PolygonEditor::updatePolygonClosedState() {
|
||||
part -> setClosed(close_polygon.isChecked());
|
||||
}
|
||||
|
||||
void PolygonEditor::updateForm() {
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
35
editor/polygoneditor.h
Normal file
35
editor/polygoneditor.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef POLYGON_EDITOR_H
|
||||
#define POLYGON_EDITOR_H
|
||||
#include <QtGui>
|
||||
class PartPolygon;
|
||||
class PolygonEditor : public QWidget {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
PolygonEditor(PartPolygon *, QWidget * = 0);
|
||||
~PolygonEditor() {
|
||||
qDebug() << "~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);
|
||||
};
|
||||
#endif
|
||||
125
editor/qet.cpp
Normal file
125
editor/qet.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "qet.h"
|
||||
|
||||
/**
|
||||
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
|
||||
en orientation. Si la chaine fait plusieurs caracteres, seul le
|
||||
premier est pris en compte. En cas d'incoherence, QET::North est
|
||||
retourne.
|
||||
@param s Chaine de caractere cense representer une orientation
|
||||
@return l'orientation designee par la chaine de caractere
|
||||
*/
|
||||
QET::Orientation QET::orientationFromString(const QString &s) {
|
||||
QChar c = s[0];
|
||||
if (c == 'e') return(QET::East);
|
||||
else if (c == 's') return(QET::South);
|
||||
else if (c == 'w') return (QET::West);
|
||||
else return(QET::North);
|
||||
}
|
||||
|
||||
/**
|
||||
@param o une orientation
|
||||
@return une chaine de caractere representant l'orientation
|
||||
*/
|
||||
QString QET::orientationToString(QET::Orientation o) {
|
||||
QString ret;
|
||||
switch(o) {
|
||||
case QET::North: ret = "n"; break;
|
||||
case QET::East : ret = "e"; break;
|
||||
case QET::South: ret = "s"; break;
|
||||
case QET::West : ret = "w"; break;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal).
|
||||
@param a La premiere orientation de Borne
|
||||
@param b La seconde orientation de Borne
|
||||
@return Un booleen a true si les deux orientations de bornes sont sur le meme axe
|
||||
*/
|
||||
bool QET::surLeMemeAxe(QET::Orientation a, QET::Orientation b) {
|
||||
if ((a == QET::North || a == QET::South) && (b == QET::North || b == QET::South)) return(true);
|
||||
else if ((a == QET::East || a == QET::West) && (b == QET::East || b == QET::West)) return(true);
|
||||
else return(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si une orientation de borne est horizontale (Est / Ouest).
|
||||
@param a L'orientation de borne
|
||||
@return True si l'orientation de borne est horizontale, false sinon
|
||||
*/
|
||||
bool QET::estHorizontale(QET::Orientation a) {
|
||||
return(a == QET::East || a == QET::West);
|
||||
}
|
||||
|
||||
/**
|
||||
Indique si une orientation de borne est verticale (Nord / Sud).
|
||||
@param a L'orientation de borne
|
||||
@return True si l'orientation de borne est verticale, false sinon
|
||||
*/
|
||||
bool QET::estVerticale(QET::Orientation a) {
|
||||
return(a == QET::North || a == QET::South);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de connaitre l'orientation suivante apres celle donnee en parametre.
|
||||
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
|
||||
Est, Sud, Ouest.
|
||||
@param o une orientation
|
||||
@return l'orientation suivante
|
||||
*/
|
||||
QET::Orientation QET::nextOrientation(QET::Orientation o) {
|
||||
if (o < 0 || o > 2) return(QET::North);
|
||||
return((QET::Orientation)(o + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de connaitre l'orientation precedant celle donnee en parametre.
|
||||
Les orientations sont generalement presentees dans l'ordre suivant : Nord,
|
||||
Est, Sud, Ouest.
|
||||
@param o une orientation
|
||||
@return l'orientation precedente
|
||||
*/
|
||||
QET::Orientation QET::previousOrientation(QET::Orientation o) {
|
||||
if (o < 0 || o > 3) return(QET::North);
|
||||
if (o == QET::North) return(QET::West);
|
||||
return((QET::Orientation)(o - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
|
||||
entier. Si oui, sa valeur est copiee dans entier.
|
||||
@param e Element XML
|
||||
@param nom_attribut Nom de l'attribut a analyser
|
||||
@param entier Pointeur facultatif vers un entier
|
||||
@return true si l'attribut est bien un entier, false sinon
|
||||
*/
|
||||
bool QET::attributeIsAnInteger(const QDomElement &e, QString nom_attribut, int *entier) {
|
||||
// verifie la presence de l'attribut
|
||||
if (!e.hasAttribute(nom_attribut)) return(false);
|
||||
// verifie la validite de l'attribut
|
||||
bool ok;
|
||||
int tmp = e.attribute(nom_attribut).toInt(&ok);
|
||||
if (!ok) return(false);
|
||||
if (entier != NULL) *entier = tmp;
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de savoir si l'attribut nom_attribut d'un element XML e est bien un
|
||||
reel. Si oui, sa valeur est copiee dans reel.
|
||||
@param e Element XML
|
||||
@param nom_attribut Nom de l'attribut a analyser
|
||||
@param reel Pointeur facultatif vers un double
|
||||
@return true si l'attribut est bien un reel, false sinon
|
||||
*/
|
||||
bool QET::attributeIsAReal(const QDomElement &e, QString nom_attribut, double *reel) {
|
||||
// verifie la presence de l'attribut
|
||||
if (!e.hasAttribute(nom_attribut)) return(false);
|
||||
// verifie la validite de l'attribut
|
||||
bool ok;
|
||||
qreal tmp = e.attribute(nom_attribut).toDouble(&ok);
|
||||
if (!ok) return(false);
|
||||
if (reel != NULL) *reel = tmp;
|
||||
return(true);
|
||||
}
|
||||
121
editor/styleeditor.cpp
Normal file
121
editor/styleeditor.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "styleeditor.h"
|
||||
#include "customelementgraphicpart.h"
|
||||
|
||||
StyleEditor::StyleEditor(CustomElementGraphicPart *p, QWidget *parent) : QWidget(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);
|
||||
connect(color, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
|
||||
|
||||
// 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);
|
||||
connect(style, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
|
||||
|
||||
// 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);
|
||||
connect(weight, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
|
||||
|
||||
// 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);
|
||||
connect(filling, SIGNAL(buttonClicked(int)), this, SLOT(updatePart()));
|
||||
|
||||
// antialiasing
|
||||
antialiasing = new QCheckBox(tr("Antialiasing"));
|
||||
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
StyleEditor::~StyleEditor() {
|
||||
qDebug() << "~StyleEditor()";
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
void StyleEditor::updateForm() {
|
||||
// lit l'antialiasing : deconnexion du slot pour eviter l'appel a updatePart()
|
||||
disconnect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
|
||||
antialiasing -> setChecked(part -> antialiased());
|
||||
connect(antialiasing, SIGNAL(stateChanged(int)), this, SLOT(updatePart()));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void StyleEditor::appendWidget(QWidget *w) {
|
||||
main_layout -> insertWidget(7, w);
|
||||
}
|
||||
33
editor/styleeditor.h
Normal file
33
editor/styleeditor.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef STYLE_EDITOR_H
|
||||
#define STYLE_EDITOR_H
|
||||
#include <QtGui>
|
||||
class CustomElementGraphicPart;
|
||||
class StyleEditor : public QWidget {
|
||||
Q_OBJECT
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
StyleEditor(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();
|
||||
};
|
||||
#endif
|
||||
67
editor/terminaleditor.cpp
Normal file
67
editor/terminaleditor.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "terminaleditor.h"
|
||||
#include "partterminal.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param term Borne a editer
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
TerminalEditor::TerminalEditor(PartTerminal *term, QWidget *parent) : QWidget(parent) {
|
||||
part = term;
|
||||
|
||||
qle_x = new QLineEdit();
|
||||
qle_y = new QLineEdit();
|
||||
|
||||
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("Postion : ")));
|
||||
|
||||
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);
|
||||
|
||||
connect(qle_x, SIGNAL(textEdited(const QString &)), this, SLOT(updateTerminal()));
|
||||
connect(qle_y, SIGNAL(textEdited(const QString &)), this, SLOT(updateTerminal()));
|
||||
connect(orientation, SIGNAL(activated(int)), this, SLOT(updateTerminal()));
|
||||
|
||||
updateForm();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
TerminalEditor::~TerminalEditor() {
|
||||
qDebug() << "~TerminalEditor()";
|
||||
};
|
||||
|
||||
void TerminalEditor::updateTerminal() {
|
||||
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
|
||||
part -> setOrientation(
|
||||
static_cast<QET::Orientation>(
|
||||
orientation -> itemData(
|
||||
orientation -> currentIndex()
|
||||
).toInt()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void TerminalEditor::updateForm() {
|
||||
qle_x -> setText(QString("%1").arg(part -> pos().x()));
|
||||
qle_y -> setText(QString("%1").arg(part -> pos().y()));
|
||||
orientation -> setCurrentIndex(static_cast<int>(part -> orientation()));
|
||||
}
|
||||
30
editor/terminaleditor.h
Normal file
30
editor/terminaleditor.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef TERMINAL_EDITOR_H
|
||||
#define TERMINAL_EDITOR_H
|
||||
#include <QtGui>
|
||||
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 QWidget {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
TerminalEditor(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 updateForm();
|
||||
};
|
||||
#endif
|
||||
68
editor/texteditor.cpp
Normal file
68
editor/texteditor.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "texteditor.h"
|
||||
#include "parttext.h"
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param term Champ de texte a editer
|
||||
@param parent QWidget parent de ce widget
|
||||
*/
|
||||
TextEditor::TextEditor(PartText *text, QWidget *parent) : QWidget(parent) {
|
||||
part = text;
|
||||
|
||||
qle_x = new QLineEdit();
|
||||
qle_y = new QLineEdit();
|
||||
qle_text = new QLineEdit();
|
||||
font_size = new QSpinBox();
|
||||
font_size -> setRange(0, 144);
|
||||
|
||||
QVBoxLayout *main_layout = new QVBoxLayout();
|
||||
main_layout -> addWidget(new QLabel(tr("Postion : ")));
|
||||
|
||||
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);
|
||||
|
||||
connect(qle_x, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
|
||||
connect(qle_y, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
|
||||
connect(qle_text, SIGNAL(textEdited(const QString &)), this, SLOT(updateText()));
|
||||
connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(updateText()));
|
||||
|
||||
//updateForm();
|
||||
}
|
||||
|
||||
/**
|
||||
Destructeur
|
||||
*/
|
||||
TextEditor::~TextEditor() {
|
||||
qDebug() << "~TextEditor()";
|
||||
}
|
||||
|
||||
void TextEditor::updateText() {
|
||||
part -> can_check_changes = false;
|
||||
part -> setFont(QFont(part -> font().family(), font_size -> value()));
|
||||
part -> setPlainText(qle_text -> text());
|
||||
part -> setPos(qle_x -> text().toDouble(), qle_y -> text().toDouble());
|
||||
part -> can_check_changes = true;
|
||||
}
|
||||
|
||||
void TextEditor::updateForm() {
|
||||
qle_x -> setText(QString("%1").arg(part -> pos().x()));
|
||||
qle_y -> setText(QString("%1").arg(part -> pos().y()));
|
||||
qle_text -> setText(part -> toPlainText());
|
||||
font_size -> setValue(part -> font().pointSize());
|
||||
}
|
||||
30
editor/texteditor.h
Normal file
30
editor/texteditor.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef TEXT_EDITOR_H
|
||||
#define TEXT_EDITOR_H
|
||||
#include <QtGui>
|
||||
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 QWidget {
|
||||
Q_OBJECT
|
||||
// Constructeurs, destructeur
|
||||
public:
|
||||
TextEditor(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 updateForm();
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user