2007-12-01 10:47:15 +00:00
|
|
|
/*
|
|
|
|
Copyright 2006-2007 Xavier Guerrin
|
|
|
|
This file is part of QElectroTech.
|
|
|
|
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
#include "elementscene.h"
|
|
|
|
#include "qetelementeditor.h"
|
2007-06-30 17:41:07 +00:00
|
|
|
#include <cmath>
|
|
|
|
#include "partline.h"
|
|
|
|
#include "partellipse.h"
|
|
|
|
#include "partcircle.h"
|
|
|
|
#include "partpolygon.h"
|
|
|
|
#include "partterminal.h"
|
|
|
|
#include "parttext.h"
|
2007-08-18 04:42:39 +00:00
|
|
|
#include "parttextfield.h"
|
2007-07-10 22:54:22 +00:00
|
|
|
#include "partarc.h"
|
2007-08-18 22:59:10 +00:00
|
|
|
#include "hotspoteditor.h"
|
2007-08-23 15:33:55 +00:00
|
|
|
#include "editorcommands.h"
|
2007-10-10 22:35:32 +00:00
|
|
|
|
|
|
|
const int ElementScene::xGrid = 10;
|
|
|
|
const int ElementScene::yGrid = 10;
|
2007-06-30 17:41:07 +00:00
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Constructeur
|
|
|
|
@param editor L'editeur d'element concerne
|
|
|
|
@param parent le Widget parent
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
2007-06-30 17:41:07 +00:00
|
|
|
QGraphicsScene(parent),
|
|
|
|
_width(3),
|
|
|
|
_height(7),
|
2007-08-23 15:33:55 +00:00
|
|
|
_hotspot(15, 35),
|
2007-08-25 03:43:05 +00:00
|
|
|
qgi_manager(this),
|
|
|
|
element_editor(editor)
|
2007-06-30 17:41:07 +00:00
|
|
|
{
|
|
|
|
current_polygon = NULL;
|
2007-08-25 15:46:09 +00:00
|
|
|
undo_stack.setClean();
|
2007-06-30 17:41:07 +00:00
|
|
|
connect(this, SIGNAL(changed(const QList<QRectF> &)), this, SLOT(slot_checkSelectionChanged()));
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/// Destructeur
|
2007-08-25 03:43:05 +00:00
|
|
|
ElementScene::~ElementScene() {
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "selection et deplacement de parties"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_move() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Normal;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de ligne"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addLine() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Line;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de cercle"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addCircle() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Circle;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout d'ellipse"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addEllipse() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Ellipse;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de polygone"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addPolygon() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Polygon;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de texte statique"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addText() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Text;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de borne"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addTerminal() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Terminal;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout d'arc de cercle"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addArc() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = Arc;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Passe la scene en mode "ajout de champ de texte"
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_addTextField() {
|
2007-06-30 17:41:07 +00:00
|
|
|
behavior = TextField;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Gere les mouvements de la souris
|
|
|
|
@param e objet decrivant l'evenement
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
2007-06-30 17:41:07 +00:00
|
|
|
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
|
|
|
QRectF temp_rect;
|
|
|
|
qreal radius;
|
|
|
|
QPointF temp_point;
|
|
|
|
QPolygonF temp_polygon;
|
|
|
|
if (e -> buttons() & Qt::LeftButton) {
|
|
|
|
switch(behavior) {
|
|
|
|
case Line:
|
|
|
|
current_line -> setLine(QLineF(current_line -> line().p1(), e -> scenePos()));
|
|
|
|
break;
|
|
|
|
case Ellipse:
|
|
|
|
temp_rect = current_ellipse -> rect();
|
|
|
|
temp_rect.setBottomRight(e -> scenePos());
|
|
|
|
current_ellipse -> setRect(temp_rect);
|
|
|
|
break;
|
2007-07-10 22:54:22 +00:00
|
|
|
case Arc:
|
|
|
|
temp_rect = current_arc -> rect();
|
|
|
|
temp_rect.setBottomRight(e -> scenePos());
|
|
|
|
current_arc -> setRect(temp_rect);
|
|
|
|
break;
|
2007-06-30 17:41:07 +00:00
|
|
|
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;
|
2007-09-21 11:48:37 +00:00
|
|
|
case Normal:
|
2007-06-30 17:41:07 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Gere les appuis sur les boutons de la souris
|
|
|
|
@param e objet decrivant l'evenement
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
2007-06-30 17:41:07 +00:00
|
|
|
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
|
|
|
QPolygonF temp_polygon;
|
|
|
|
if (e -> button() & Qt::LeftButton) {
|
|
|
|
switch(behavior) {
|
|
|
|
case Line:
|
2007-08-25 03:43:05 +00:00
|
|
|
current_line = new PartLine(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
current_line -> setLine(QLineF(e -> scenePos(), e -> scenePos()));
|
|
|
|
break;
|
|
|
|
case Ellipse:
|
2007-08-25 03:43:05 +00:00
|
|
|
current_ellipse = new PartEllipse(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
current_ellipse -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
2007-10-06 19:46:44 +00:00
|
|
|
current_ellipse -> setProperty("antialias", true);
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
2007-07-10 22:54:22 +00:00
|
|
|
case Arc:
|
2007-08-25 03:43:05 +00:00
|
|
|
current_arc = new PartArc(element_editor, 0, this);
|
2007-07-10 22:54:22 +00:00
|
|
|
current_arc -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
2007-10-06 19:46:44 +00:00
|
|
|
current_arc -> setProperty("antialias", true);
|
2007-07-10 22:54:22 +00:00
|
|
|
break;
|
2007-06-30 17:41:07 +00:00
|
|
|
case Circle:
|
2007-08-25 03:43:05 +00:00
|
|
|
current_circle = new PartCircle(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
current_circle -> setRect(QRectF(e -> scenePos(), QSizeF(0.0, 0.0)));
|
2007-10-06 19:46:44 +00:00
|
|
|
current_circle -> setProperty("antialias", true);
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
|
|
|
case Polygon:
|
|
|
|
if (current_polygon == NULL) {
|
2007-08-25 03:43:05 +00:00
|
|
|
current_polygon = new PartPolygon(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
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;
|
2007-09-21 11:48:37 +00:00
|
|
|
case Normal:
|
2007-06-30 17:41:07 +00:00
|
|
|
default:
|
|
|
|
QGraphicsScene::mousePressEvent(e);
|
2007-09-21 11:48:37 +00:00
|
|
|
if (!selectedItems().isEmpty()) fsi_pos = selectedItems().first() -> scenePos();
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
} else QGraphicsScene::mousePressEvent(e);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Gere les relachements de boutons de la souris
|
|
|
|
@param e objet decrivant l'evenement
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
2007-06-30 17:41:07 +00:00
|
|
|
PartTerminal *terminal;
|
|
|
|
PartText *text;
|
2007-08-18 04:42:39 +00:00
|
|
|
PartTextField *textfield;
|
2007-06-30 17:41:07 +00:00
|
|
|
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
|
|
|
|
if (e -> button() & Qt::LeftButton) {
|
|
|
|
switch(behavior) {
|
|
|
|
case Line:
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("ligne"), this, current_line));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
|
|
|
case Ellipse:
|
|
|
|
current_ellipse -> setRect(current_ellipse -> rect().normalized());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("ellipse"), this, current_ellipse));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
2007-07-10 22:54:22 +00:00
|
|
|
case Arc:
|
|
|
|
current_arc-> setRect(current_arc -> rect().normalized());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("arc"), this, current_arc));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-07-10 22:54:22 +00:00
|
|
|
break;
|
2007-06-30 17:41:07 +00:00
|
|
|
case Circle:
|
|
|
|
current_circle -> setRect(current_circle -> rect().normalized());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("cercle"), this, current_circle));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
|
|
|
case Terminal:
|
2007-08-25 03:43:05 +00:00
|
|
|
terminal = new PartTerminal(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
terminal -> setPos(e -> scenePos());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("borne"), this, terminal));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
|
|
|
case Text:
|
2007-08-25 03:43:05 +00:00
|
|
|
text = new PartText(element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
text -> setPos(e -> scenePos());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("texte"), this, text));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
break;
|
2007-08-18 04:42:39 +00:00
|
|
|
case TextField:
|
2007-08-25 03:43:05 +00:00
|
|
|
textfield = new PartTextField(element_editor, 0, this);
|
2007-08-18 04:42:39 +00:00
|
|
|
textfield -> setPos(e -> scenePos());
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("champ de texte"), this, textfield));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-08-18 04:42:39 +00:00
|
|
|
break;
|
2007-08-23 15:33:55 +00:00
|
|
|
case Normal:
|
2007-06-30 17:41:07 +00:00
|
|
|
default:
|
|
|
|
QGraphicsScene::mouseReleaseEvent(e);
|
2007-08-23 15:33:55 +00:00
|
|
|
// detecte les deplacements de parties
|
|
|
|
if (!selectedItems().isEmpty()) {
|
2007-09-21 11:48:37 +00:00
|
|
|
QPointF movement = selectedItems().first() -> scenePos() - fsi_pos;
|
2007-08-23 15:33:55 +00:00
|
|
|
if (!movement.isNull()) {
|
|
|
|
undo_stack.push(new MovePartsCommand(movement, this, selectedItems()));
|
|
|
|
}
|
|
|
|
}
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
} else if (e -> button() & Qt::RightButton) {
|
|
|
|
if (behavior == Polygon) {
|
|
|
|
behavior = Normal;
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new AddPartCommand(tr("polygone"), this, current_polygon));
|
2007-06-30 17:41:07 +00:00
|
|
|
current_polygon = NULL;
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsAdded());
|
2007-06-30 17:41:07 +00:00
|
|
|
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
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::drawBackground(QPainter *p, const QRectF &r) {
|
2007-06-30 17:41:07 +00:00
|
|
|
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());
|
2007-10-10 22:35:32 +00:00
|
|
|
while (g_x % xGrid) ++ g_x;
|
2007-06-30 17:41:07 +00:00
|
|
|
int g_y = (int)ceil(r.y());
|
2007-10-10 22:35:32 +00:00
|
|
|
while (g_y % yGrid) ++ g_y;
|
2007-06-30 17:41:07 +00:00
|
|
|
|
2007-10-10 22:35:32 +00:00
|
|
|
for (int gx = g_x ; gx < limite_x ; gx += xGrid) {
|
|
|
|
for (int gy = g_y ; gy < limite_y ; gy += yGrid) {
|
2007-06-30 17:41:07 +00:00
|
|
|
p -> drawPoint(gx, gy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p -> restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-10-21 16:10:21 +00:00
|
|
|
Dessine l'arriere-plan de l'editeur, cad l'indicateur de hotspot.
|
2007-06-30 17:41:07 +00:00
|
|
|
@param p Le QPainter a utiliser pour dessiner
|
|
|
|
@param r Le rectangle de la zone a dessiner
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::drawForeground(QPainter *p, const QRectF &) {
|
2007-06-30 17:41:07 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Exporte l'element en XML
|
|
|
|
@return un document XML decrivant l'element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
const QDomDocument ElementScene::toXml() const {
|
2007-06-30 17:41:07 +00:00
|
|
|
// 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());
|
2007-10-04 17:32:41 +00:00
|
|
|
root.setAttribute("version", QET::version);
|
2007-06-30 17:41:07 +00:00
|
|
|
|
|
|
|
// noms de l'element
|
|
|
|
root.appendChild(_names.toXml(xml_document));
|
|
|
|
|
|
|
|
QDomElement description = xml_document.createElement("description");
|
|
|
|
// description de l'element
|
2007-10-07 18:52:01 +00:00
|
|
|
foreach(QGraphicsItem *qgi, zItems(true)) {
|
2007-06-30 17:41:07 +00:00
|
|
|
if (CustomElementPart *ce = dynamic_cast<CustomElementPart *>(qgi)) {
|
|
|
|
description.appendChild(ce -> toXml(xml_document));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
root.appendChild(description);
|
|
|
|
|
|
|
|
xml_document.appendChild(root);
|
|
|
|
return(xml_document);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Lit un element depuis un document XML
|
|
|
|
@param xml_document un document XML decrivant l'element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::fromXml(const QDomDocument &xml_document) {
|
2007-06-30 17:41:07 +00:00
|
|
|
|
|
|
|
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;
|
2007-08-25 03:43:05 +00:00
|
|
|
if (qde.tagName() == "line") cep = new PartLine (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "ellipse") cep = new PartEllipse (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "circle") cep = new PartCircle (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "polygon") cep = new PartPolygon (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "terminal") cep = new PartTerminal (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "text") cep = new PartText (element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "input") cep = new PartTextField(element_editor, 0, this);
|
|
|
|
else if (qde.tagName() == "arc") cep = new PartArc (element_editor, 0, this);
|
2007-06-30 17:41:07 +00:00
|
|
|
else continue;
|
|
|
|
if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep)) qgi -> setZValue(z++);
|
|
|
|
cep -> fromXml(qde);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
@return un rectangle englobant toutes les parties ainsi que le
|
|
|
|
"bounding rect" de l'element
|
|
|
|
*/
|
2007-09-10 21:12:49 +00:00
|
|
|
QRectF ElementScene::sceneContent() const {
|
|
|
|
return(itemsBoundingRect().unite(QRectF(-_hotspot, QSizeF(width(), height()))));
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
@return la pile d'annulations de cet editeur d'element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
QUndoStack &ElementScene::undoStack() {
|
2007-08-23 15:33:55 +00:00
|
|
|
return(undo_stack);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
@return le gestionnaire de QGraphicsItem de cet editeur d'element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
QGIManager &ElementScene::qgiManager() {
|
2007-08-23 15:33:55 +00:00
|
|
|
return(qgi_manager);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Detecte les changements de selection
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_checkSelectionChanged() {
|
2007-06-30 17:41:07 +00:00
|
|
|
static QList<QGraphicsItem *> cache_selecteditems = QList<QGraphicsItem *>();
|
|
|
|
QList<QGraphicsItem *> selecteditems = selectedItems();
|
|
|
|
if (cache_selecteditems != selecteditems) emit(selectionChanged());
|
|
|
|
cache_selecteditems = selecteditems;
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Selectionne tout
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_selectAll() {
|
2007-06-30 17:41:07 +00:00
|
|
|
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(true);
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Deselectionne tout
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_deselectAll() {
|
2007-06-30 17:41:07 +00:00
|
|
|
clearSelection();
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Inverse la selection
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_invertSelection() {
|
2007-06-30 17:41:07 +00:00
|
|
|
foreach(QGraphicsItem *qgi, items()) qgi -> setSelected(!qgi -> isSelected());
|
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Supprime les elements selectionnes
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_delete() {
|
2007-06-30 17:41:07 +00:00
|
|
|
// verifie qu'il y a qqc de selectionne
|
|
|
|
QList<QGraphicsItem *> selected_items = selectedItems();
|
|
|
|
if (selected_items.isEmpty()) return;
|
|
|
|
|
|
|
|
// efface tout ce qui est selectionne
|
2007-08-23 15:33:55 +00:00
|
|
|
undo_stack.push(new DeletePartsCommand(this, selected_items));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsRemoved());
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Lance un dialogue pour editer les dimensions et le point de saisie
|
|
|
|
(hotspot) de l'element.
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_editSizeHotSpot() {
|
2007-08-18 22:59:10 +00:00
|
|
|
// cree un dialogue
|
|
|
|
QDialog dialog_sh;
|
|
|
|
dialog_sh.setModal(true);
|
|
|
|
dialog_sh.setMinimumSize(400, 230);
|
|
|
|
dialog_sh.setWindowTitle(tr("\311diter la taille et le point de saisie"));
|
|
|
|
QVBoxLayout *dialog_layout = new QVBoxLayout(&dialog_sh);
|
|
|
|
|
|
|
|
// ajoute un HotspotEditor au dialogue
|
|
|
|
HotspotEditor *hotspot_editor = new HotspotEditor();
|
|
|
|
hotspot_editor -> setElementWidth(static_cast<uint>(width() / 10));
|
|
|
|
hotspot_editor -> setElementHeight(static_cast<uint>(height() / 10));
|
|
|
|
hotspot_editor -> setHotspot(hotspot());
|
|
|
|
hotspot_editor -> setOldHotspot(hotspot());
|
|
|
|
hotspot_editor -> setPartsRect(itemsBoundingRect());
|
|
|
|
hotspot_editor -> setPartsRectEnabled(true);
|
|
|
|
dialog_layout -> addWidget(hotspot_editor);
|
|
|
|
|
|
|
|
// ajoute deux boutons au dialogue
|
|
|
|
QDialogButtonBox *dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
|
|
dialog_layout -> addWidget(dialog_buttons);
|
|
|
|
connect(dialog_buttons, SIGNAL(accepted()), &dialog_sh, SLOT(accept()));
|
|
|
|
connect(dialog_buttons, SIGNAL(rejected()), &dialog_sh, SLOT(reject()));
|
|
|
|
|
|
|
|
// lance le dialogue
|
2007-09-10 21:50:17 +00:00
|
|
|
if (dialog_sh.exec() != QDialog::Accepted) return;
|
|
|
|
QSize new_size(hotspot_editor -> elementSize());
|
|
|
|
QSize old_size(width(), height());
|
|
|
|
QPoint new_hotspot(hotspot_editor -> hotspot());
|
|
|
|
QPoint old_hotspot(_hotspot);
|
|
|
|
|
|
|
|
if (new_size != old_size || new_hotspot != old_hotspot) {
|
|
|
|
undo_stack.push(new ChangeHotspotCommand(this, old_size, new_size, old_hotspot, new_hotspot, hotspot_editor -> offsetParts()));
|
2007-08-18 22:59:10 +00:00
|
|
|
}
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Lance un dialogue pour editer les noms de cete element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_editOrientations() {
|
2007-06-30 17:41:07 +00:00
|
|
|
|
|
|
|
// 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
|
2007-09-10 22:11:47 +00:00
|
|
|
if (dialog_ori.exec() == QDialog::Accepted) {
|
|
|
|
OrientationSet new_ori = ori_widget -> orientationSet();
|
|
|
|
if (new_ori != ori) {
|
|
|
|
undoStack().push(new ChangeOrientationsCommand(this, ori, new_ori));
|
|
|
|
}
|
|
|
|
}
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
|
2007-12-05 21:16:01 +00:00
|
|
|
/**
|
|
|
|
Lance un dialogue pour editer les noms de cet element
|
|
|
|
*/
|
2007-08-25 03:43:05 +00:00
|
|
|
void ElementScene::slot_editNames() {
|
2007-06-30 17:41:07 +00:00
|
|
|
|
|
|
|
// 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
|
2007-09-10 21:50:17 +00:00
|
|
|
if (dialog.exec() == QDialog::Accepted) {
|
|
|
|
NamesList new_names(names_widget -> names());
|
|
|
|
if (new_names != _names) undoStack().push(new ChangeNamesCommand(this, _names, new_names));
|
|
|
|
}
|
2007-06-30 17:41:07 +00:00
|
|
|
}
|
|
|
|
|
2007-10-07 18:52:01 +00:00
|
|
|
/**
|
|
|
|
Amene les elements selectionnes au premier plan
|
|
|
|
*/
|
|
|
|
void ElementScene::slot_bringForward() {
|
|
|
|
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::BringForward));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsZValueChanged());
|
2007-10-07 18:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Remonte les elements selectionnes d'un plan
|
|
|
|
*/
|
|
|
|
void ElementScene::slot_raise() {
|
|
|
|
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Raise));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsZValueChanged());
|
2007-10-07 18:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Descend les elements selectionnes d'un plan
|
|
|
|
*/
|
|
|
|
void ElementScene::slot_lower() {
|
|
|
|
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::Lower));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsZValueChanged());
|
2007-10-07 18:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Envoie les elements selectionnes au fond
|
|
|
|
*/
|
|
|
|
void ElementScene::slot_sendBackward() {
|
|
|
|
undoStack().push(new ChangeZValueCommand(this, ChangeZValueCommand::SendBackward));
|
2007-11-07 20:23:24 +00:00
|
|
|
emit(partsZValueChanged());
|
2007-10-07 18:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
@param include_terminals true pour inclure les bornes, false sinon
|
|
|
|
@return les parties de l'element ordonnes par zValue croissante
|
|
|
|
*/
|
|
|
|
QList<QGraphicsItem *> ElementScene::zItems(bool include_terminals) const {
|
|
|
|
// recupere les elements
|
|
|
|
QList<QGraphicsItem *> all_items_list(items());
|
|
|
|
|
|
|
|
// enleve les bornes
|
|
|
|
QList<QGraphicsItem *> terminals;
|
|
|
|
foreach(QGraphicsItem *qgi, all_items_list) {
|
|
|
|
if (qgraphicsitem_cast<PartTerminal *>(qgi)) {
|
|
|
|
all_items_list.removeAt(all_items_list.indexOf(qgi));
|
|
|
|
terminals << qgi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ordonne les parties par leur zValue
|
|
|
|
QMultiMap<qreal, QGraphicsItem *> mm;
|
|
|
|
foreach(QGraphicsItem *qgi, all_items_list) mm.insert(qgi -> zValue(), qgi);
|
|
|
|
all_items_list.clear();
|
2007-12-01 19:07:59 +00:00
|
|
|
QMapIterator<qreal, QGraphicsItem *> i(mm);
|
|
|
|
while (i.hasNext()) {
|
|
|
|
i.next();
|
|
|
|
all_items_list << i.value();
|
|
|
|
}
|
2007-10-07 18:52:01 +00:00
|
|
|
|
|
|
|
// rajoute eventuellement les bornes
|
|
|
|
if (include_terminals) all_items_list += terminals;
|
|
|
|
return(all_items_list);
|
|
|
|
}
|