Debut du support des annulations dans l'editeur d'elements

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@102 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
xavierqet
2007-08-23 15:33:55 +00:00
parent dea9381090
commit 9e7005a829
9 changed files with 351 additions and 11 deletions

View File

@@ -143,6 +143,14 @@ void CustomElementEditor::setupMenus() {
file_menu -> addSeparator();
file_menu -> addAction(quit);
QAction *undo = ce_scene -> undoStack().createUndoAction(this, tr("Annuler"));
QAction *redo = ce_scene -> undoStack().createRedoAction(this, tr("Refaire"));
undo -> setShortcuts(QKeySequence::Undo);
redo -> setShortcuts(QKeySequence::Redo);
edit_menu -> addAction(undo);
edit_menu -> addAction(redo);
edit_menu -> addSeparator();
edit_menu -> addAction(selectall);
edit_menu -> addAction(deselectall);
edit_menu -> addAction(inv_select);
@@ -181,7 +189,7 @@ void CustomElementEditor::setupInterface() {
// widget par defaut dans le QDockWidget
default_informations = new QLabel();
// panel sur le cote
// panel sur le cote pour editer les parties
tools_dock = new QDockWidget(tr("Informations"), this);
tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
@@ -190,6 +198,15 @@ void CustomElementEditor::setupInterface() {
QWidget *info_widget = new QWidget();
info_widget -> setLayout(new QVBoxLayout(info_widget));
tools_dock -> setWidget(info_widget);
// panel sur le cote pour les annulations
undo_dock = new QDockWidget(tr("Annulations"), this);
undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures);
undo_dock -> setMinimumWidth(285);
addDockWidget(Qt::RightDockWidgetArea, undo_dock);
undo_dock -> setWidget(new QUndoView(&(ce_scene -> undoStack()), this));
slot_updateInformations();
// barre d'etat

View File

@@ -25,6 +25,8 @@ class CustomElementEditor : public QMainWindow {
EditorScene *ce_scene;
/// container pour les widgets d'edition des parties
QDockWidget *tools_dock;
/// container pour la liste des annulations
QDockWidget *undo_dock;
/// actions du menu fichier
QAction *new_element, *open, *save, *save_as, *quit;
/// actions du menu edition

125
editor/editorcommands.cpp Normal file
View File

@@ -0,0 +1,125 @@
#include "editorcommands.h"
/*** DeletePartsCommand ***/
/**
Constructeur
@param scene EditorScene concernee
@param parts Liste des parties supprimees
@param parent QUndoCommand parent
*/
DeletePartsCommand::DeletePartsCommand(
EditorScene *scene,
const QList<QGraphicsItem *> parts,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("suppression"), parent),
deleted_parts(parts),
editor_scene(scene)
{
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> qgiManager().manage(qgi);
}
}
/// Destructeur : detruit egalement les parties supprimees
DeletePartsCommand::~DeletePartsCommand() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> qgiManager().release(qgi);
}
}
/// Restaure les parties supprimees
void DeletePartsCommand::undo() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> addItem(qgi);
}
}
/// Supprime les parties
void DeletePartsCommand::redo() {
foreach(QGraphicsItem *qgi, deleted_parts) {
editor_scene -> removeItem(qgi);
}
}
/*** MovePartsCommand ***/
/**
Constructeur
@param m Mouvement sous forme de QPointF
@param scene EditorScene concernee
@param parts Liste des parties deplacees
@param parent QUndoCommand parent
*/
MovePartsCommand::MovePartsCommand(
const QPointF &m,
EditorScene *scene,
const QList<QGraphicsItem *> parts,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("d\351placement"), parent),
movement(m),
first_redo(true)
{
moved_parts = parts;
editor_scene = scene;
}
/// Destructeur
MovePartsCommand::~MovePartsCommand() {
}
/// Annule le deplacement
void MovePartsCommand::undo() {
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(-movement.x(), -movement.y());
}
/// Refait le deplacement
void MovePartsCommand::redo() {
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
if (first_redo) {
first_redo = false;
return;
}
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(movement.x(), movement.y());
}
/*** AddPartCommand ***/
/**
Constructeur
@param name Nom de la partie ajoutee
@param parts Liste des parties deplacees
@param parent QUndoCommand parent
*/
AddPartCommand::AddPartCommand(
const QString &name,
EditorScene *scene,
QGraphicsItem *p,
QUndoCommand *parent
) :
QUndoCommand(QObject::tr("ajout ") + name, parent),
part(p),
editor_scene(scene),
first_redo(true)
{
editor_scene -> qgiManager().manage(part);
}
/// Destructeur
AddPartCommand::~AddPartCommand() {
editor_scene -> qgiManager().release(part);
}
/// Annule le deplacement
void AddPartCommand::undo() {
editor_scene -> removeItem(part);
}
/// Refait le deplacement
void AddPartCommand::redo() {
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
if (first_redo) {
first_redo = false;
return;
}
editor_scene -> addItem(part);
}

85
editor/editorcommands.h Normal file
View File

@@ -0,0 +1,85 @@
#ifndef EDITOR_COMMANDS_H
#define EDITOR_COMMANDS_H
#include "customelementpart.h"
#include "editorscene.h"
#include "qgimanager.h"
#include <QtGui>
/**
Cette classe represente l'action de supprimer une ou plusieurs
parties lors de l'edition d'un element
*/
class DeletePartsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
DeletePartsCommand(EditorScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
virtual ~DeletePartsCommand();
private:
DeletePartsCommand(const DeletePartsCommand &);
// methodes
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QList<QGraphicsItem *> deleted_parts;
/// scene sur laquelle se produisent les actions
EditorScene *editor_scene;
};
/**
Cette classe represente l'action de deplacer une ou plusieurs
parties lors de l'edition d'un element
*/
class MovePartsCommand : public QUndoCommand {
// constructeurs, destructeur
public:
MovePartsCommand(const QPointF &, EditorScene *, const QList<QGraphicsItem *>, QUndoCommand * = 0);
virtual ~MovePartsCommand();
private:
MovePartsCommand(const MovePartsCommand &);
// methodes
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QList<QGraphicsItem *> moved_parts;
/// scene sur laquelle se produisent les actions
EditorScene *editor_scene;
/// translation appliquee
QPointF movement;
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
bool first_redo;
};
/**
Cette classe represente l'action de deplacer une ou plusieurs
parties lors de l'edition d'un element
*/
class AddPartCommand : public QUndoCommand {
// constructeurs, destructeur
public:
AddPartCommand(const QString &, EditorScene *, QGraphicsItem *, QUndoCommand * = 0);
virtual ~AddPartCommand();
private:
AddPartCommand(const AddPartCommand &);
// methodes
virtual void undo();
virtual void redo();
// attributs
private:
/// Liste des parties supprimees
QGraphicsItem *part;
/// scene sur laquelle se produisent les actions
EditorScene *editor_scene;
/// booleen pour eviter d'appeler redo() lors de la construction de l'objet
bool first_redo;
};
#endif

View File

@@ -9,6 +9,7 @@
#include "parttextfield.h"
#include "partarc.h"
#include "hotspoteditor.h"
#include "editorcommands.h"
#define GRILLE_X 10
#define GRILLE_Y 10
@@ -16,7 +17,8 @@ EditorScene::EditorScene(QObject *parent) :
QGraphicsScene(parent),
_width(3),
_height(7),
_hotspot(15, 35)
_hotspot(15, 35),
qgi_manager(this)
{
current_polygon = NULL;
connect(this, SIGNAL(changed(const QList<QRectF> &)), this, SLOT(slot_checkSelectionChanged()));
@@ -161,38 +163,51 @@ void EditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
if (behavior != Polygon && current_polygon != NULL) current_polygon = NULL;
if (e -> button() & Qt::LeftButton) {
switch(behavior) {
case Normal:
QGraphicsScene::mouseReleaseEvent(e);
break;
case Line:
undo_stack.push(new AddPartCommand(tr("ligne"), this, current_line));
break;
case Ellipse:
current_ellipse -> setRect(current_ellipse -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("ellipse"), this, current_ellipse));
break;
case Arc:
current_arc-> setRect(current_arc -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("arc"), this, current_arc));
break;
case Circle:
current_circle -> setRect(current_circle -> rect().normalized());
undo_stack.push(new AddPartCommand(tr("cercle"), this, current_circle));
break;
case Terminal:
terminal = new PartTerminal(0, this);
terminal -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("borne"), this, terminal));
break;
case Text:
text = new PartText(0, this);
text -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("texte"), this, text));
break;
case TextField:
textfield = new PartTextField(0, this);
textfield -> setPos(e -> scenePos());
undo_stack.push(new AddPartCommand(tr("champ de texte"), this, textfield));
break;
case Normal:
default:
QGraphicsScene::mouseReleaseEvent(e);
// detecte les deplacements de parties
if (!selectedItems().isEmpty()) {
QPointF movement = e -> scenePos() - e -> buttonDownScenePos(Qt::LeftButton);
if (!movement.isNull()) {
undo_stack.push(new MovePartsCommand(movement, this, selectedItems()));
}
}
}
} else if (e -> button() & Qt::RightButton) {
if (behavior == Polygon) {
behavior = Normal;
undo_stack.push(new AddPartCommand(tr("polygone"), this, current_polygon));
current_polygon = NULL;
emit(needNormalMode());
} else QGraphicsScene::mouseReleaseEvent(e);
@@ -367,6 +382,14 @@ void EditorScene::fromXml(const QDomDocument &xml_document) {
}
}
QUndoStack &EditorScene::undoStack() {
return(undo_stack);
}
QGIManager &EditorScene::qgiManager() {
return(qgi_manager);
}
void EditorScene::slot_checkSelectionChanged() {
static QList<QGraphicsItem *> cache_selecteditems = QList<QGraphicsItem *>();
QList<QGraphicsItem *> selecteditems = selectedItems();
@@ -392,10 +415,7 @@ void EditorScene::slot_delete() {
if (selected_items.isEmpty()) return;
// efface tout ce qui est selectionne
foreach(QGraphicsItem *qgi, selected_items) {
removeItem(qgi);
delete qgi;
}
undo_stack.push(new DeletePartsCommand(this, selected_items));
}
void EditorScene::slot_editSizeHotSpot() {

View File

@@ -4,6 +4,7 @@
#include <QtXml>
#include "nameslistwidget.h"
#include "orientationsetwidget.h"
#include "qgimanager.h"
class PartLine;
class PartEllipse;
class PartCircle;
@@ -35,6 +36,10 @@ class EditorScene : public QGraphicsScene {
NamesList _names;
/// Liste des orientations de l'element
OrientationSet ori;
/// Pile des actions annulables
QUndoStack undo_stack;
/// Gestionnaire de QGraphicsItem
QGIManager qgi_manager;
/// Variables relatives a la gestion du dessin des parties sur la scene
Behavior behavior;
@@ -58,6 +63,8 @@ class EditorScene : public QGraphicsScene {
void setOrientations(const OrientationSet &);
virtual const QDomDocument toXml() const;
virtual void fromXml(const QDomDocument &);
QUndoStack &undoStack();
QGIManager &qgiManager();
protected:
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);

View File

@@ -54,7 +54,9 @@ HEADERS += aboutqet.h \
editor/arceditor.h \
editor/parttextfield.h \
editor/textfieldeditor.h \
hotspoteditor.h
hotspoteditor.h \
editor/editorcommands.h \
qgimanager.h
SOURCES += aboutqet.cpp \
borderinset.cpp \
conducer.cpp \
@@ -102,7 +104,9 @@ SOURCES += aboutqet.cpp \
editor/arceditor.cpp \
editor/parttextfield.cpp \
editor/textfieldeditor.cpp \
hotspoteditor.cpp
hotspoteditor.cpp \
editor/editorcommands.cpp \
qgimanager.cpp
RESOURCES += qelectrotech.qrc
TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts
QT += xml

54
qgimanager.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "qgimanager.h"
/**
Constructeur
@param sc QGraphicsScene a utiliser pour gerer au mieux les QGraphicsItem
*/
QGIManager::QGIManager(QGraphicsScene *sc) :
scene(sc),
destroy_qgi_on_delete(true)
{
}
/**
Destructeur
Lors de sa destruction, le QGI Manager detruit les QGraphicsItem restants
si ceux-ci n'appartiennent pas a la scene ; ce comportement peut etre
change avec la methode setDestroyQGIOnDelete
@see setDestroyQGIOnDelete
*/
QGIManager::~QGIManager(){
if (!destroy_qgi_on_delete) return;
foreach(QGraphicsItem *qgi, qgi_manager.keys()) {
if (!scene -> items().contains(qgi)) delete qgi;
}
}
/**
Demande au QGIManager de gerer un QGI
@param qgi QGraphicsItem a gerer
*/
void QGIManager::manage(QGraphicsItem *qgi) {
if (qgi_manager.contains(qgi)) ++ qgi_manager[qgi];
else qgi_manager.insert(qgi, 1);
}
/**
Indique au QGIManager qu'une reference vers un QGI a ete detruite
S'il n'y a plus de references vers ce QGI et que celui-ci n'est pas present
sur la scene de ce QGIManager, alors il sera detruit.
@param qgi QGraphicsItem a ne plus gerer
*/
void QGIManager::release(QGraphicsItem *qgi) {
if (!qgi_manager.contains(qgi)) return;
-- qgi_manager[qgi];
if (!qgi_manager[qgi] && !(scene -> items().contains(qgi))) delete qgi;
}
/**
Indique au QGIManager de detruire les QGraphicsItem restants lors de sa
destruction si ceux-ci n'appartiennent pas a la scene
*/
void QGIManager::setDestroyQGIOnDelete(bool b) {
destroy_qgi_on_delete = b;
}

26
qgimanager.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef QGI_MANAGER_H
#define QGI_MANAGER_H
#include <QtCore>
#include <QGraphicsScene>
#include <QGraphicsItem>
class QGIManager {
// constructeurs, destructeurs
public:
QGIManager(QGraphicsScene *);
virtual ~QGIManager();
private:
QGIManager(const QGIManager &);
// attributs
private:
QGraphicsScene *scene;
QHash<QGraphicsItem *, int> qgi_manager;
bool destroy_qgi_on_delete;
//methodes
public:
void manage(QGraphicsItem *);
void release(QGraphicsItem *);
void setDestroyQGIOnDelete(bool);
};
#endif