diff --git a/sources/conductor.cpp b/sources/conductor.cpp index 1b3020765..29aee60f7 100644 --- a/sources/conductor.cpp +++ b/sources/conductor.cpp @@ -46,12 +46,15 @@ Conductor::Conductor(Terminal *p1, Terminal* p2, Diagram *parent_diagram) : segments(NULL), moving_point(false), moving_segment(false), - previous_z_value(zValue()), modified_path(false), has_to_save_profile(false), segments_squares_scale_(1.0), must_highlight_(Conductor::None) { + //set Zvalue at 10 to be upper than the DiagramImageItem + setZValue(10); + previous_z_value = zValue(); + // ajout du conducteur a la liste de conducteurs de chacune des deux bornes bool ajout_p1 = terminal1 -> addConductor(this); bool ajout_p2 = terminal2 -> addConductor(this); diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 112d8d9ae..fd733cc52 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -30,6 +30,7 @@ #include "ghostelement.h" #include "independenttextitem.h" #include "qetapp.h" +#include "diagramimageitem.h" const int Diagram::xGrid = 10; const int Diagram::yGrid = 10; @@ -334,6 +335,7 @@ QDomDocument Diagram::toXml(bool whole_content) { QList list_elements; QList list_conductors; QList list_texts; + QList list_images; // Determine les elements a "XMLiser" foreach(QGraphicsItem *qgi, items()) { @@ -350,6 +352,9 @@ QDomDocument Diagram::toXml(bool whole_content) { } else if (IndependentTextItem *iti = qgraphicsitem_cast(qgi)) { if (whole_content) list_texts << iti; else if (iti -> isSelected()) list_texts << iti; + } else if (DiagramImageItem *dii = qgraphicsitem_cast(qgi)) { + if (whole_content) list_images << dii; + else if (dii -> isSelected()) list_images << dii; } } @@ -382,6 +387,15 @@ QDomDocument Diagram::toXml(bool whole_content) { } racine.appendChild(inputs); } + + // save of images + if (!list_images.isEmpty()) { + QDomElement images = document.createElement("images"); + foreach (DiagramImageItem *dii, list_images) { + images.appendChild(dii -> toXml(document)); + } + racine.appendChild(images); + } // on retourne le document XML ainsi genere return(document); @@ -536,6 +550,14 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf addIndependentTextItem(iti); added_texts << iti; } + + QList added_images; + foreach (QDomElement image_xml, QET::findInDomElement(root, "images", "image")) { + DiagramImageItem *dii = new DiagramImageItem (this); + dii -> fromXml(image_xml); + addItem(dii); + added_images << dii; + } // gere la translation des nouveaux elements et texte si celle-ci est demandee if (position != QPointF()) { @@ -545,6 +567,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf QList added_items; foreach (Element *added_element, added_elements) added_items << added_element; foreach (DiagramTextItem *added_text, added_texts) added_items << added_text; + foreach (DiagramImageItem *added_image, added_images) added_items << added_image; foreach (QGraphicsItem *item, added_items) { QPointF csg = item -> mapToScene(item -> boundingRect()).boundingRect().topLeft(); qreal px = csg.x(); @@ -566,6 +589,9 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf foreach (DiagramTextItem *added_text, added_texts) { added_text -> setPos(added_text -> pos().x() + diff_x, added_text -> pos().y() + diff_y); } + foreach (DiagramImageItem *added_image, added_images) { + added_image -> setPos(added_image -> pos().x() + diff_x, added_image -> pos().y() + diff_y); + } } // chargement de tous les Conducteurs du fichier XML @@ -601,6 +627,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf content_ptr -> elements = added_elements.toSet(); content_ptr -> conductorsToMove = added_conductors.toSet(); content_ptr -> textFields = added_texts.toSet(); + content_ptr -> images = added_images.toSet(); } return(true); @@ -707,6 +734,15 @@ void Diagram::addIndependentTextItem(IndependentTextItem *iti) { ); } +void Diagram::addDiagramImageItem(DiagramImageItem *dii) { + if (!dii || isReadOnly()) return; + + //add image at diagram + if (dii -> scene() != this) { + addItem(dii); + } +} + /** Enleve un element du schema @param element Element a enlever @@ -1183,6 +1219,8 @@ DiagramContent Diagram::selectedContent() { ) { dc.otherConductors << c; } + } else if (DiagramImageItem *dii = qgraphicsitem_cast(item)) { + dc.images << dii; } } @@ -1227,6 +1265,8 @@ bool Diagram::canRotateSelection() const { if (e -> orientation().current() != e -> orientation().next()) { return(true); } + } else if (qgraphicsitem_cast(qgi)) { + return (true); } } return(false); diff --git a/sources/diagram.h b/sources/diagram.h index 96eec4c69..7c5abafc2 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -40,6 +40,7 @@ class IndependentTextItem; class QETProject; class Terminal; class ConductorTextItem; +class DiagramImageItem; /** This class represents an electric diagram. It manages its various child elements, conductors and texts and handles their graphic rendering. @@ -134,6 +135,7 @@ class Diagram : public QGraphicsScene { void addElement(Element *); void addConductor(Conductor *); void addIndependentTextItem(IndependentTextItem *); + void addDiagramImageItem(DiagramImageItem *); void removeElement(Element *); void removeConductor(Conductor *); diff --git a/sources/diagramcommands.cpp b/sources/diagramcommands.cpp index 5f531660f..e1d8498ff 100644 --- a/sources/diagramcommands.cpp +++ b/sources/diagramcommands.cpp @@ -25,6 +25,7 @@ #include "qgimanager.h" #include "diagram.h" #include "diagramtextitem.h" +#include "diagramimageitem.h" /** Constructeur @@ -96,6 +97,38 @@ void AddTextCommand::redo() { textitem -> setPos(position); } +/** + Constructeur + @param dia Schema auquel on ajoute une image + @param image Image ajoute + @param pos Position a laquelle l'image est ajoute + @param parent QUndoCommand parent + */ +AddImageCommand::AddImageCommand(Diagram *dia, DiagramImageItem *image, const QPointF &pos, QUndoCommand *parent): + QUndoCommand(QObject::tr("Ajouter une image", "undo caption"), parent), + imageitem(image), + diagram(dia), + position(pos) +{ + diagram -> qgiManager().manage(imageitem); +} + +///Destructor +AddImageCommand::~AddImageCommand() { + diagram -> qgiManager().release(imageitem); +} + +///Annule l'ajout +void AddImageCommand::undo() { + diagram -> removeItem(imageitem); +} + +///Refait l'ajout +void AddImageCommand::redo() { + diagram -> addDiagramImageItem(imageitem); + imageitem -> setPos(position - imageitem -> boundingRect().center()); +} + /** Constructeur @param d Schema auquel on ajoute un conducteur @@ -176,6 +209,10 @@ void DeleteElementsCommand::undo() { foreach(IndependentTextItem *t, removed_content.textFields) { diagram -> addIndependentTextItem(t); } + + foreach(DiagramImageItem *dii, removed_content.images) { + diagram -> addItem(dii); + } } /// refait les suppressions @@ -194,6 +231,11 @@ void DeleteElementsCommand::redo() { foreach(IndependentTextItem *t, removed_content.textFields) { diagram -> removeIndependentTextItem(t); } + + //enleve les images + foreach(DiagramImageItem *dii, removed_content.images) { + diagram -> removeItem(dii); + } } /** @@ -310,7 +352,8 @@ MoveElementsCommand::MoveElementsCommand( DiagramContent::Elements | DiagramContent::TextFields | DiagramContent::ConductorsToUpdate | - DiagramContent::ConductorsToMove + DiagramContent::ConductorsToMove | + DiagramContent::Images ); setText( @@ -371,6 +414,11 @@ void MoveElementsCommand::move(const QPointF &actual_movement) { foreach(DiagramTextItem *text, content_to_move.textFields) { text -> setPos(text -> pos() + actual_movement); } + + // deplace les images + foreach (DiagramImageItem *dii, content_to_move.images) { + dii -> setPos(dii -> pos() + actual_movement); + } } /** @@ -575,10 +623,11 @@ void ChangeDiagramTextCommand::redo() { @param texts Textes a pivoter @param parent QUndoCommand parent */ -RotateElementsCommand::RotateElementsCommand(const QHash &elements, const QList &texts, QUndoCommand *parent) : +RotateElementsCommand::RotateElementsCommand(const QHash &elements, const QList &texts, const QList &images, QUndoCommand *parent) : QUndoCommand(parent), elements_to_rotate(elements), texts_to_rotate(texts), + images_to_rotate(images), applied_rotation_angle_(-90.0) { setText( @@ -587,7 +636,7 @@ RotateElementsCommand::RotateElementsCommand(const QHash rotateBy(-applied_rotation_angle_);} } + foreach(DiagramImageItem *dii, images_to_rotate) dii -> rotateBy(-applied_rotation_angle_); } /// refait le pivotement @@ -624,6 +674,7 @@ void RotateElementsCommand::redo() { } dti -> rotateBy(applied_rotation_angle_); } + foreach(DiagramImageItem *dii, images_to_rotate) dii -> rotateBy(applied_rotation_angle_); } /** diff --git a/sources/diagramcommands.h b/sources/diagramcommands.h index e19ede94c..7cb621613 100644 --- a/sources/diagramcommands.h +++ b/sources/diagramcommands.h @@ -29,6 +29,7 @@ class DiagramTextItem; class Element; class ElementTextItem; class IndependentTextItem; +class DiagramImageItem; /** This command adds an element to a particular diagram. @@ -83,6 +84,33 @@ class AddTextCommand : public QUndoCommand { QPointF position; }; +/** + This command adds an image item to a particular diagram +*/ +class AddImageCommand : public QUndoCommand { + //constructors, destructor + public: + AddImageCommand (Diagram *, DiagramImageItem *, const QPointF &, QUndoCommand * = 0); + virtual ~AddImageCommand(); + private: + AddImageCommand(const AddImageCommand &); + + //methods + public: + virtual void undo(); + virtual void redo(); + + // attributes + private: + /// added image item + DiagramImageItem *imageitem; + /// diagram the image item is added to + Diagram *diagram; + /// position of the image item on the diagram + QPointF position; + +}; + /** This command adds a conductor to a particular diagram. */ @@ -302,7 +330,7 @@ class ChangeDiagramTextCommand : public QUndoCommand { class RotateElementsCommand : public QUndoCommand { // constructors, destructor public: - RotateElementsCommand(const QHash &elements, const QList &, QUndoCommand * = 0); + RotateElementsCommand(const QHash &elements, const QList &, const QList &, QUndoCommand * = 0); virtual ~RotateElementsCommand(); private: RotateElementsCommand(const RotateElementsCommand &); @@ -321,6 +349,8 @@ class RotateElementsCommand : public QUndoCommand { QHash elements_to_rotate; /// text items to be rotated QList texts_to_rotate; + /// images item to be rotated + QList images_to_rotate; /// angle of rotation to be applied to text items qreal applied_rotation_angle_; /// previous state of each conductor text item diff --git a/sources/diagramcontent.cpp b/sources/diagramcontent.cpp index 650b64422..333a1ee4c 100644 --- a/sources/diagramcontent.cpp +++ b/sources/diagramcontent.cpp @@ -20,6 +20,7 @@ #include "element.h" #include "independenttextitem.h" #include "conductor.h" +#include "diagramimageitem.h" /** Constructeur par defaut. Ne contient rien. @@ -33,6 +34,7 @@ DiagramContent::DiagramContent() { DiagramContent::DiagramContent(const DiagramContent &other) : elements(other.elements), textFields(other.textFields), + images(other.images), conductorsToUpdate(other.conductorsToUpdate), conductorsToMove(other.conductorsToMove), otherConductors(other.otherConductors) @@ -68,6 +70,7 @@ QList DiagramContent::conductors(int filter) const { void DiagramContent::clear() { elements.clear(); textFields.clear(); + images.clear(); conductorsToUpdate.clear(); conductorsToMove.clear(); otherConductors.clear(); @@ -82,6 +85,7 @@ QList DiagramContent::items(int filter) const { foreach(QGraphicsItem *qgi, conductors(filter)) items_list << qgi; if (filter & Elements) foreach(QGraphicsItem *qgi, elements) items_list << qgi; if (filter & TextFields) foreach(QGraphicsItem *qgi, textFields) items_list << qgi; + if (filter & Images) foreach(QGraphicsItem *qgi, images) items_list << qgi; if (filter & SelectedOnly) { foreach(QGraphicsItem *qgi, items_list) { if (!qgi -> isSelected()) items_list.removeOne(qgi); @@ -99,12 +103,14 @@ int DiagramContent::count(int filter) const { if (filter & SelectedOnly) { if (filter & Elements) foreach(Element *element, elements) { if (element -> isSelected()) ++ count; } if (filter & TextFields) foreach(DiagramTextItem *dti, textFields) { if (dti -> isSelected()) ++ count; } + if (filter & Images) foreach(DiagramImageItem *dii, images) { if (dii -> isSelected()) ++ count; } if (filter & ConductorsToMove) foreach(Conductor *conductor, conductorsToMove) { if (conductor -> isSelected()) ++ count; } if (filter & ConductorsToUpdate) foreach(Conductor *conductor, conductorsToUpdate) { if (conductor -> isSelected()) ++ count; } if (filter & OtherConductors) foreach(Conductor *conductor, otherConductors) { if (conductor -> isSelected()) ++ count; } } else { if (filter & Elements) count += elements.count(); if (filter & TextFields) count += textFields.count(); + if (filter & Images) count += images.count(); if (filter & ConductorsToMove) count += conductorsToMove.count(); if (filter & ConductorsToUpdate) count += conductorsToUpdate.count(); if (filter & OtherConductors) count += otherConductors.count(); @@ -122,12 +128,14 @@ QString DiagramContent::sentence(int filter) const { int elements_count = (filter & Elements) ? elements.count() : 0; int conductors_count = conductors(filter).count(); int textfields_count = (filter & TextFields) ? textFields.count() : 0; + int images_count = (filter & Images) ? images.count() : 0; return( QET::ElementsAndConductorsSentence( elements_count, conductors_count, - textfields_count + textfields_count, + images_count ) ); } diff --git a/sources/diagramcontent.h b/sources/diagramcontent.h index e483cfd3a..701d3ad09 100644 --- a/sources/diagramcontent.h +++ b/sources/diagramcontent.h @@ -21,6 +21,7 @@ class Conductor; class Element; class IndependentTextItem; +class DiagramImageItem; /** This class provides a container that makes the transmission of diagram content to other functions/methods easier. The different kind of items are made @@ -40,6 +41,7 @@ class DiagramContent { enum Filter { Elements = 1, TextFields = 2, + Images = 3, ConductorsToMove = 4, ConductorsToUpdate = 8, OtherConductors = 16, @@ -52,6 +54,8 @@ class DiagramContent { QSet elements; /// Hold independent text items QSet textFields; + /// Hold image + QSet images; /// Hold conductors that would get updated considering electrical elements are moved QSet conductorsToUpdate; /// Hold conductors that would be moved as is considering electrical elements are moved diff --git a/sources/diagramimageitem.cpp b/sources/diagramimageitem.cpp new file mode 100644 index 000000000..fe8be08c8 --- /dev/null +++ b/sources/diagramimageitem.cpp @@ -0,0 +1,381 @@ +/* + Copyright 2006-2013 QElectroTech Team + 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 . +*/ +#include "diagramimageitem.h" +#include "diagramcommands.h" +#include "qet.h" +#include "qetapp.h" + +DiagramImageItem::DiagramImageItem(Diagram *parent_diagram) : + QGraphicsPixmapItem(0, parent_diagram) +{ + setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); +#if QT_VERSION >= 0x040600 + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); +#endif + //connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable())); +} + +/** + * @brief DiagramImageItem::DiagramImageItem + * @param parent + * @param parent_diagram + */ +DiagramImageItem::DiagramImageItem(const QPixmap &pixmap, Diagram *parent_diagram) : + QGraphicsPixmapItem(pixmap, 0, parent_diagram), + first_move_(false) +{ + setCursor(Qt::PointingHandCursor); + setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); +#if QT_VERSION >= 0x040600 + setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); +#endif + //connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable())); +} + +/// Destructeur +DiagramImageItem::~DiagramImageItem() { +} + +/** + @return le Diagram auquel ce image appartient, ou 0 si ce image n'est + rattache a aucun schema +*/ +Diagram *DiagramImageItem::diagram() const { + return(qobject_cast(scene())); +} + +/** + Permet de tourner le image a un angle donne de maniere absolue. + Un angle de 0 degres correspond a un image horizontal non retourne. + @param rotation Nouvel angle de rotation de ce image + @see applyRotation +*/ +void DiagramImageItem::setRotationAngle(const qreal &rotation_angle) { + qreal applied_rotation = QET::correctAngle(rotation_angle); + applyRotation(applied_rotation - rotation()); +} + +/** + Permet de tourner le image de maniere relative. + L'angle added_rotation est ajoute a l'orientation actuelle du image. + @param added_rotation Angle a ajouter a la rotation actuelle + @see applyRotation +*/ +void DiagramImageItem::rotateBy(const qreal &added_rotation) { + qreal applied_added_rotation = QET::correctAngle(added_rotation); + applyRotation(applied_added_rotation); +} + +/** + Traduit en coordonnees de la scene un mouvement / vecteur initialement + exprime en coordonnees locales. + @param movement Vecteur exprime en coordonnees locales + @return le meme vecteur, exprime en coordonnees de la scene +*/ +QPointF DiagramImageItem::mapMovementToScene(const QPointF &movement) const { + // on definit deux points en coordonnees locales + QPointF local_origin(0.0, 0.0); + QPointF local_movement_point(movement); + + // on les mappe sur la scene + QPointF scene_origin(mapToScene(local_origin)); + QPointF scene_movement_point(mapToScene(local_movement_point)); + + // on calcule le vecteur represente par ces deux points + return(scene_movement_point - scene_origin); +} + +/** + Traduit en coordonnees locales un mouvement / vecteur initialement + exprime en coordonnees de la scene. + @param movement Vecteur exprime en coordonnees de la scene + @return le meme vecteur, exprime en coordonnees locales +*/ +QPointF DiagramImageItem::mapMovementFromScene(const QPointF &movement) const { + // on definit deux points sur la scene + QPointF scene_origin(0.0, 0.0); + QPointF scene_movement_point(movement); + + // on les mappe sur ce QGraphicsItem + QPointF local_origin(mapFromScene(scene_origin)); + QPointF local_movement_point(mapFromScene(scene_movement_point)); + + // on calcule le vecteur represente par ces deux points + return(local_movement_point - local_origin); +} + +/** + Traduit en coordonnees de l'item parent un mouvement / vecteur initialement + exprime en coordonnees locales. + @param movement Vecteur exprime en coordonnees locales + @return le meme vecteur, exprime en coordonnees du parent +*/ +QPointF DiagramImageItem::mapMovementToParent(const QPointF &movement) const { + // on definit deux points en coordonnees locales + QPointF local_origin(0.0, 0.0); + QPointF local_movement_point(movement); + + // on les mappe sur la scene + QPointF parent_origin(mapToParent(local_origin)); + QPointF parent_movement_point(mapToParent(local_movement_point)); + + // on calcule le vecteur represente par ces deux points + return(parent_movement_point - parent_origin); +} + +/** + Traduit en coordonnees locales un mouvement / vecteur initialement + exprime en coordonnees du parent. + @param movement Vecteur exprime en coordonnees du parent + @return le meme vecteur, exprime en coordonnees locales +*/ +QPointF DiagramImageItem::mapMovementFromParent(const QPointF &movement) const { + // on definit deux points sur le parent + QPointF parent_origin(0.0, 0.0); + QPointF parent_movement_point(movement); + + // on les mappe sur ce QGraphicsItem + QPointF local_origin(mapFromParent(parent_origin)); + QPointF local_movement_point(mapFromParent(parent_movement_point)); + + // on calcule le vecteur represente par ces deux points + return(local_movement_point - local_origin); +} + +/** + Dessine le champ de image. + Cette methode delegue simplement le travail a QGraphicsPixmapItem::paint apres + avoir desactive l'antialiasing. + @param painter Le QPainter a utiliser pour dessiner le champ de image + @param option Les options de style pour le champ de image + @param widget Le QWidget sur lequel on dessine +*/ +void DiagramImageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + painter -> setRenderHint(QPainter::Antialiasing, false); + QGraphicsPixmapItem::paint(painter, option, widget); +} + +/** + Gere la prise de focus du champ de image + @param e Objet decrivant la prise de focus +*/ +void DiagramImageItem::focusInEvent(QFocusEvent *e) { + QGraphicsPixmapItem::focusInEvent(e); + + // empeche le deplacement du image pendant son edition + setFlag(QGraphicsItem::ItemIsMovable, false); +} + +/** + Gere la perte de focus du champ de image + @param e Objet decrivant la perte de focus +*/ +void DiagramImageItem::focusOutEvent(QFocusEvent *e) { + QGraphicsPixmapItem::focusOutEvent(e); + + /*// deselectionne le image + QTextCursor cursor = textCursor(); + cursor.clearSelection(); + setTextCursor(cursor); + + // hack a la con pour etre re-entrant + setTextInteractionFlags(Qt::NoTextInteraction); + + // autorise de nouveau le deplacement du image + setFlag(QGraphicsItem::ItemIsMovable, true); + QTimer::singleShot(0, this, SIGNAL(lostFocus()));*/ +} + +/** + Gere le clic sur le champ de texte + @param e Objet decrivant l'evenement souris +*/ +void DiagramImageItem::mousePressEvent(QGraphicsSceneMouseEvent *e) { + first_move_ = true; + if (e -> modifiers() & Qt::ControlModifier) { + setSelected(!isSelected()); + } + QGraphicsItem::mousePressEvent(e); +} + +/** + Gere les double-clics sur ce champ de image. + @param event un QGraphicsSceneMouseEvent decrivant le double-clic +*/ +void DiagramImageItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + /*if (!(textInteractionFlags() & Qt::imageditable)) { + // rend le champ de image editable + setTextInteractionFlags(Qt::imageditorInteraction); + + // edite le champ de image + setFocus(Qt::MouseFocusReason); + } else { + QGraphicsPixmapItem::mouseDoubleClickEvent(event); + }*/ +} + +/** + * @brief DiagramImageItem::mouseMoveEvent + * Gere les mouvements de souris lies a l'image + * @param e Objet decrivant l'evenement souris + */ +void DiagramImageItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { + if (isSelected() && e -> buttons() & Qt::LeftButton) { + //Image is moving + if(diagram()) { + if (first_move_) { + //It's the first movement, we signal it to parent diagram + diagram() -> beginMoveElements(this); + } + } + + //we apply the mouse movement + QPointF old_pos = pos(); + setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton))); + //we calcul the real movement apply by setPos() + QPointF effective_movement = pos() - old_pos; + + if (diagram()) { + //we signal the real movement apply to diagram, + //who he apply to other selected item + diagram() -> continueMoveElements(effective_movement); + } + } else e -> ignore(); + + if (first_move_) first_move_ = false; +} + +/** + * @brief DiagramImageItem::mouseReleaseEvent + * Gere le relachement de souris + * Cette methode a ete reimplementee pour tenir a jour la liste + * des images à deplacer au niveau du schema. + * @param e Objet decrivant l'evenement souris + */ +void DiagramImageItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { + if (diagram()) { + diagram() -> endMoveElements(); + } + if (!(e -> modifiers() & Qt::ControlModifier)) { + QGraphicsItem::mouseReleaseEvent(e); + } +} + +/** + Effectue la rotation du image en elle-meme + Pour les DiagramImageItem, la rotation s'effectue autour du point (0, 0). + Cette methode peut toutefois etre redefinie dans des classes filles + @param angle Angle de la rotation a effectuer +*/ +void DiagramImageItem::applyRotation(const qreal &angle) { + // un simple appel a QGraphicsPixmapItem::setRotation suffit + setTransformOriginPoint(boundingRect().center()); + QGraphicsPixmapItem::setRotation(QGraphicsPixmapItem::rotation() + angle); +} + +/** + Change la position du champ de image en veillant a ce qu'il + reste sur la grille du schema auquel il appartient. + @param p Nouvelles coordonnees de l'element +*/ +void DiagramImageItem::setPos(const QPointF &p) { + if (p == pos()) return; + // pas la peine de positionner sur la grille si l'element n'est pas sur un Diagram + if (scene()) { + // arrondit l'abscisse a 10 px pres + int p_x = qRound(p.x() / (Diagram::xGrid * 1.0)) * Diagram::xGrid; + // arrondit l'ordonnee a 10 px pres + int p_y = qRound(p.y() / (Diagram::yGrid * 1.0)) * Diagram::yGrid; + QGraphicsPixmapItem::setPos(p_x, p_y); + } else QGraphicsPixmapItem::setPos(p); +} + +/** + Change la position du champ de image en veillant a ce que l'il + reste sur la grille du schema auquel il appartient. + @param x Nouvelle abscisse de l'element + @param y Nouvelle ordonnee de l'element +*/ +void DiagramImageItem::setPos(qreal x, qreal y) { + setPos(QPointF(x, y)); +} + +/** + @return la position du champ de image +*/ +QPointF DiagramImageItem::pos() const { + return(QGraphicsPixmapItem::pos()); +} + +/// Rend le champ de image non focusable +void DiagramImageItem::setNonFocusable() { + setFlag(QGraphicsPixmapItem::ItemIsFocusable, false); +} + +/** + * @brief Edit the image with .... + */ +void DiagramImageItem::edit() { + // waiting +} + +/** + Load the image from this xml element + @param e xml element that define an image +*/ +bool DiagramImageItem::fromXml(const QDomElement &e) { + if (e.tagName() != "image") return (false); + QDomNode image_node = e.firstChild(); + if (!image_node.isText()) return (false); + + //load xml text image to QByteArray + QByteArray array; + array = QByteArray::fromBase64(e.text().toAscii()); + + //Set QPixmap from the @array + QPixmap pixmap; + pixmap.loadFromData(array); + setPixmap(pixmap); + + setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble()); + if (e.hasAttribute("rotation")) setRotationAngle(e.attribute("rotation").toDouble()); + + return (true); +} + +/** + @param document Le document XML a utiliser + @return L'element XML representant ce champ de texte +*/ +QDomElement DiagramImageItem::toXml(QDomDocument &document) const { + QDomElement result = document.createElement("image"); + //write some attribute + result.setAttribute("x", QString("%1").arg(pos().x())); + result.setAttribute("y", QString("%1").arg(pos().y())); + if (rotation()) result.setAttribute("rotation", QString("%1").arg(rotation())); + + //write the pixmap in the xml element after he was been transformed to base64 + QByteArray array; + QBuffer buffer(&array); + buffer.open(QIODevice::ReadWrite); + pixmap().save(&buffer, "PNG"); + QDomText base64 = document.createTextNode(array.toBase64()); + result.appendChild(base64); + + return(result); +} diff --git a/sources/diagramimageitem.h b/sources/diagramimageitem.h new file mode 100644 index 000000000..105c70628 --- /dev/null +++ b/sources/diagramimageitem.h @@ -0,0 +1,85 @@ +/* + Copyright 2006-2013 QElectroTech Team + 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 . +*/ +#ifndef DIAGRAM_IMAGE_ITEM_H +#define DIAGRAM_IMAGE_ITEM_H +#include +#include "diagram.h" +/** + This class represents a selectable, movable and editable image on a + diagram. + @see QGraphicsItem::GraphicsItemFlags +*/ +class DiagramImageItem : public QObject, public QGraphicsPixmapItem { + Q_OBJECT + // constructors, destructor + public: + DiagramImageItem(Diagram * = 0); + DiagramImageItem(const QPixmap &, Diagram * = 0); + virtual ~DiagramImageItem(); + + // attributes + public: + enum { Type = UserType + 1007 }; + + // methods + public: + /** + Enable the use of qgraphicsitem_cast to safely cast a QGraphicsItem into a + DiagramImageItem + @return the QGraphicsItem type + */ + virtual int type() const { return Type; } + Diagram *diagram() const; + + virtual bool fromXml(const QDomElement &); + virtual QDomElement toXml(QDomDocument &) const; + + virtual void setPos(const QPointF &); + virtual void setPos(qreal, qreal); + virtual QPointF pos() const; + void setRotationAngle(const qreal &); + void rotateBy(const qreal &); + void edit(); + QPointF mapMovementToScene(const QPointF &) const; + QPointF mapMovementFromScene(const QPointF &) const; + QPointF mapMovementToParent(const QPointF &) const; + QPointF mapMovementFromParent(const QPointF &) const; + + protected: + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void focusInEvent(QFocusEvent *); + void focusOutEvent(QFocusEvent *); + void mousePressEvent(QGraphicsSceneMouseEvent *e); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *); + void mouseMoveEvent(QGraphicsSceneMouseEvent *); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *); + void applyRotation(const qreal &); + + signals: + /// signal emitted when the image field loses focus + void lostFocus(); + /// signal emitted after image was changed + void diagramImageChanged(DiagramImageItem *, const QString &, const QString &); + + public slots: + void setNonFocusable(); + + private: + bool first_move_; +}; +#endif diff --git a/sources/diagramtextitem.cpp b/sources/diagramtextitem.cpp index a204280cd..7286b6f44 100644 --- a/sources/diagramtextitem.cpp +++ b/sources/diagramtextitem.cpp @@ -32,6 +32,8 @@ DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, Diagram *parent_diagram) previous_text_(), rotation_angle_(0.0) { + //set Zvalue at 10 to be upper than the DiagramImageItem + setZValue(10); setDefaultTextColor(Qt::black); setFont(QETApp::diagramTextsFont()); setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); @@ -52,6 +54,8 @@ DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, Dia previous_text_(text), rotation_angle_(0.0) { + //set Zvalue at 10 to be upper than the DiagramImageItem + setZValue(10); setDefaultTextColor(Qt::black); setFont(QETApp::diagramTextsFont()); setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index e7a0f702f..99b904950 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -26,6 +26,7 @@ #include "conductortextitem.h" #include "elementtextitem.h" #include "independenttextitem.h" +#include "diagramimageitem.h" #include "titleblockpropertieswidget.h" #include "templatelocation.h" #include "qetapp.h" @@ -37,6 +38,10 @@ #include "qeticons.h" #include "qetmessagebox.h" #include "qtextorientationspinboxwidget.h" +#include + +#include +#include /** @@ -44,10 +49,11 @@ @param diagram Schema a afficher ; si diagram vaut 0, un nouveau Diagram est utilise @param parent Le QWidget parent de cette vue de schema */ -DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : QGraphicsView(parent), is_adding_text(false), is_moving_view_(false) { +DiagramView::DiagramView(Diagram *diagram, QWidget *parent) : QGraphicsView(parent) { setAttribute(Qt::WA_DeleteOnClose, true); setInteractive(true); - + current_behavior = noAction; + QString whatsthis = tr( "Ceci est la zone dans laquelle vous concevez vos sch\351mas en y ajoutant" " des \351l\351ments et en posant des conducteurs entre leurs bornes. Il est" @@ -140,6 +146,7 @@ void DiagramView::rotateSelection() { // recupere les elements et les champs de texte a pivoter QHash elements_to_rotate; QList texts_to_rotate; + QList images_to_rotate; foreach (QGraphicsItem *item, scene -> selectedItems()) { if (Element *e = qgraphicsitem_cast(item)) { elements_to_rotate.insert(e, e -> orientation().current()); @@ -152,12 +159,14 @@ void DiagramView::rotateSelection() { if (eti -> parentItem() && !eti -> parentItem() -> isSelected()) { texts_to_rotate << eti; } + } else if (DiagramImageItem *dii = qgraphicsitem_cast(item)) { + images_to_rotate << dii; } } // effectue les rotations s'il y a quelque chose a pivoter - if (elements_to_rotate.isEmpty() && texts_to_rotate.isEmpty()) return; - scene -> undoStack().push(new RotateElementsCommand(elements_to_rotate, texts_to_rotate)); + if (elements_to_rotate.isEmpty() && texts_to_rotate.isEmpty() && images_to_rotate.isEmpty()) return; + scene -> undoStack().push(new RotateElementsCommand(elements_to_rotate, texts_to_rotate, images_to_rotate)); } void DiagramView::rotateTexts() { @@ -417,11 +426,16 @@ void DiagramView::mousePressEvent(QMouseEvent *e) { switchToVisualisationModeIfNeeded(e); fresh_focus_in_ = false; } - if (isInteractive() && !scene -> isReadOnly()) { - if (is_adding_text && e -> buttons() == Qt::LeftButton) { - addDiagramTextAtPos(mapToScene(e -> pos())); - is_adding_text = false; + if (isInteractive() && !scene -> isReadOnly() && current_behavior > noAction && e -> buttons() == Qt::LeftButton) { + switch (current_behavior) { + case addingText: + addDiagramTextAtPos(mapToScene(e -> pos())); + break; + case addingImage: + addDiagramImageAtPos(mapToScene(e -> pos())); + break; } + current_behavior = noAction; } // workaround for drag view with hold wheel click and drag mouse // see also mouseMoveEvent() and mouseReleaseEvent() @@ -632,7 +646,8 @@ bool DiagramView::hasCopiableItems() { foreach(QGraphicsItem *qgi, scene -> selectedItems()) { if ( qgraphicsitem_cast(qgi) || - qgraphicsitem_cast(qgi) + qgraphicsitem_cast(qgi) || + qgraphicsitem_cast(qgi) ) { return(true); } @@ -649,7 +664,8 @@ bool DiagramView::hasDeletableItems() { if ( qgraphicsitem_cast(qgi) || qgraphicsitem_cast(qgi) || - qgraphicsitem_cast(qgi) + qgraphicsitem_cast(qgi) || + qgraphicsitem_cast(qgi) ) { return(true); } @@ -1143,7 +1159,7 @@ bool DiagramView::event(QEvent *e) { bool DiagramView::switchToVisualisationModeIfNeeded(QInputEvent *e) { if (isCtrlShifting(e) && !selectedItemHasFocus()) { if (dragMode() != QGraphicsView::ScrollHandDrag) { - is_moving_view_ = true; + current_behavior = dragView; setVisualisationMode(); return(true); } @@ -1157,9 +1173,9 @@ bool DiagramView::switchToVisualisationModeIfNeeded(QInputEvent *e) { otherwise. */ bool DiagramView::switchToSelectionModeIfNeeded(QInputEvent *e) { - if (is_moving_view_ && !selectedItemHasFocus() && !isCtrlShifting(e)) { + if (current_behavior == dragView && !selectedItemHasFocus() && !isCtrlShifting(e)) { setSelectionMode(); - is_moving_view_ = false; + current_behavior = noAction; return(true); } return(false); @@ -1201,12 +1217,11 @@ bool DiagramView::selectedItemHasFocus() { */ void DiagramView::addText() { if (scene -> isReadOnly()) return; - is_adding_text = true; + current_behavior = addingText; } -/** - To edit the text through the htmlEditor +/** To edit the text through the htmlEditor */ void DiagramView::editText() { if (scene -> isReadOnly()) return; @@ -1225,6 +1240,50 @@ void DiagramView::editText() { else texts_to_edit.at(0)->edit(); } + +/** +* @brief DiagramView::addImage +*/ +void DiagramView::addImage() { + if (scene -> isReadOnly()) return; + + QString pathPictures = QDesktopServices::storageLocation ( QDesktopServices::PicturesLocation ); + QString fileName = QFileDialog::getOpenFileName(this, tr("Selectionner une image..."), pathPictures.toStdString().c_str(), tr("Image Files (*.png *.jpg *.bmp *.svg)")); + if(fileName.isEmpty()) { + emit ImageAddedCanceled(false); + return; + } + + int ret = image_to_add_.load(fileName); + if(!ret){ + QMessageBox::critical(this, tr("Erreur"), tr("Impossible de charger l'image...D\351soler :(")); + return; + } + current_behavior = addingImage; +} +/** +* @brief DiagramView::addDiagramImageAtPos +* @param pos +* @return +*/ +DiagramImageItem *DiagramView::addDiagramImageAtPos(const QPointF &pos) { + + if (!isInteractive() || scene -> isReadOnly()) return(0); + + // cree un nouveau champ image + DiagramImageItem *Imageitem = new DiagramImageItem( QPixmap::fromImage(image_to_add_) ); + + // le place a la position pos en gerant l'annulation + scene -> undoStack().push(new AddImageCommand(scene, Imageitem, pos)); + adjustSceneRect(); + + // emet le signal ImageAdded + emit(ImageAdded(false)); + + return(Imageitem); + +} + /** Cree un nouveau champ de texte et le place a la position pos en gerant l'annulation ; enfin, le signal textAdded est emis. @@ -1243,7 +1302,7 @@ IndependentTextItem *DiagramView::addDiagramTextAtPos(const QPointF &pos) { // emet le signal textAdded emit(textAdded(false)); - + return(iti); } diff --git a/sources/diagramview.h b/sources/diagramview.h index 655930460..f7e29111f 100644 --- a/sources/diagramview.h +++ b/sources/diagramview.h @@ -24,6 +24,7 @@ class Conductor; class Diagram; class Element; class IndependentTextItem; +class DiagramImageItem; class QETDiagramEditor; /** This class provides a widget to render an electric diagram in an editable, @@ -37,6 +38,8 @@ class DiagramView : public QGraphicsView { DiagramView(Diagram * = 0, QWidget * = 0); virtual ~DiagramView(); + enum behavior {noAction, addingText, addingImage, dragView}; + private: DiagramView(const DiagramView &); @@ -47,13 +50,13 @@ class DiagramView : public QGraphicsView { QAction *paste_here; QAction *find_element_; QPoint paste_here_pos; - bool is_adding_text; - bool is_moving_view_; ///< Indicate whether the visualisation mode has been enabled due to mouse/keyboard interactions + behavior current_behavior; bool fresh_focus_in_; ///< Indicate the focus was freshly gained ElementsLocation next_location_; QPoint next_position_; QPointF reference_view_; QPointF center_view_; + QImage image_to_add_; // methods public: @@ -71,7 +74,9 @@ class DiagramView : public QGraphicsView { bool hasDeletableItems(); void addText(); void editText(); + void addImage(); IndependentTextItem *addDiagramTextAtPos(const QPointF &); + DiagramImageItem *addDiagramImageAtPos(const QPointF &); protected: virtual void mouseDoubleClickEvent(QMouseEvent *); @@ -120,6 +125,10 @@ class DiagramView : public QGraphicsView { void editElementRequired(const ElementsLocation &); /// Signal emitted when users want to edit and/or duplicate an existing title block template void editTitleBlockTemplate(const QString &, bool); + /// Signal emitted after a image was added + void ImageAdded(bool); + /// Signal emmitted fater windows selection image have been canceled + void ImageAddedCanceled(bool); public slots: void selectNothing(); diff --git a/sources/elementsmover.cpp b/sources/elementsmover.cpp index 4c9e2ff06..c5e1b1e64 100644 --- a/sources/elementsmover.cpp +++ b/sources/elementsmover.cpp @@ -22,6 +22,7 @@ #include "diagramcommands.h" #include "element.h" #include "independenttextitem.h" +#include "diagramimageitem.h" /** Constructeur @@ -138,6 +139,13 @@ void ElementsMover::continueMovement(const QPointF &movement) { if (movement_driver_ && text_field == movement_driver_) continue; text_field -> setPos(text_field -> pos() + movement); } + + //deplace les images + foreach(DiagramImageItem *dii, moved_content_.images) { + if (movement_driver_ && dii == movement_driver_) continue; + dii -> setPos(dii -> pos() + movement); + } + } /** diff --git a/sources/qet.cpp b/sources/qet.cpp index ff4f71ac5..d5cf35231 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -196,10 +196,11 @@ bool QET::attributeIsAReal(const QDomElement &e, QString nom_attribut, qreal *re @param elements_count nombre d'elements @param conductors_count nombre de conducteurs @param texts_count nombre de champs de texte + @param images_count nombre d'images @return la proposition decrivant le nombre d'elements, de conducteurs et de textes */ -QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_count, int texts_count) { +QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_count, int texts_count, int images_count) { QString text; if (elements_count) { text += QObject::tr( @@ -207,13 +208,15 @@ QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_co "part of a sentence listing the content of a diagram", elements_count ); - if (conductors_count && texts_count) { + if ((conductors_count && texts_count) || + (conductors_count && images_count) || + (texts_count && images_count)) { text += QObject::tr( ", ", "separator between elements and conductors in a sentence " "listing the content of a diagram" ); - } else if (conductors_count || texts_count) { + } else if (conductors_count || texts_count || images_count) { text += QObject::tr( " et ", "separator between elements and conductors (or texts) in a " @@ -228,7 +231,14 @@ QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_co "part of a sentence listing the content of a diagram", conductors_count ); - if (texts_count) { + if (texts_count && images_count) { + text += QObject::tr( + ", ", + "separator between elements and conductors in a sentence " + "listing the content of a diagram" + ); + } + else if (texts_count || images_count) { text += QObject::tr( " et ", "separator between conductors and texts in a sentence listing " @@ -243,6 +253,21 @@ QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_co "part of a sentence listing the content of a diagram", texts_count ); + if (images_count) { + text += QObject::tr( + " et ", + "separator between conductors and texts in a sentence listing " + "the content of a diagram" + ); + } + } + + if (images_count) { + text += QObject::tr( + "%n image(s)", + "part of a sentence listing the content of a diagram", + images_count + ); } return(text); } diff --git a/sources/qet.h b/sources/qet.h index 4c61fb4f6..64cce2ed6 100644 --- a/sources/qet.h +++ b/sources/qet.h @@ -152,7 +152,7 @@ namespace QET { bool orthogonalProjection(const QPointF &, const QLineF &, QPointF * = 0); bool attributeIsAnInteger(const QDomElement &, QString , int * = NULL); bool attributeIsAReal(const QDomElement &, QString , qreal * = NULL); - QString ElementsAndConductorsSentence(int, int, int = 0); + QString ElementsAndConductorsSentence(int, int, int = 0, int = 0); QList findInDomElement(const QDomElement &, const QString &); QList findInDomElement(const QDomElement &, const QString &, const QString &); QList forbiddenCharacters(); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 1d22bb005..4b5b5e4f6 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -216,6 +216,7 @@ void QETDiagramEditor::actions() { add_text = new QAction(QET::Icons::PartTextField, tr("Ajouter un champ de texte"), this); add_edittext = new QAction(QET::Icons::EditText, tr("\311diter le champ de texte"), this); add_column = new QAction(QET::Icons::EditTableInsertColumnRight, tr("Ajouter une colonne"), this); + add_image = new QAction(QET::Icons::adding_image, tr("Ajouter une image"), this); remove_column = new QAction(QET::Icons::EditTableDeleteColumn, tr("Enlever une colonne"), this); add_row = new QAction(QET::Icons::EditTableInsertRowUnder, tr("Ajouter une ligne"), this); remove_row = new QAction(QET::Icons::EditTableDeleteRow, tr("Enlever une ligne"), this); @@ -337,6 +338,7 @@ void QETDiagramEditor::actions() { // traitements speciaux add_text -> setCheckable(true); + add_image -> setCheckable(true); windowed_view_mode -> setCheckable(true); tabbed_view_mode -> setCheckable(true); mode_selection -> setCheckable(true); @@ -399,6 +401,7 @@ void QETDiagramEditor::actions() { connect(infos_diagram, SIGNAL(triggered()), this, SLOT(editCurrentDiagramProperties())); connect(add_text, SIGNAL(triggered()), this, SLOT(slot_addText()) ); connect(add_edittext, SIGNAL(triggered()), this, SLOT(slot_editText()) ); + connect(add_image, SIGNAL(triggered()), this, SLOT(slot_addImage()) ); connect(add_column, SIGNAL(triggered()), this, SLOT(slot_addColumn()) ); connect(remove_column, SIGNAL(triggered()), this, SLOT(slot_removeColumn()) ); connect(add_row, SIGNAL(triggered()), this, SLOT(slot_addRow()) ); @@ -514,7 +517,7 @@ void QETDiagramEditor::menus() { menu_affichage -> addAction(zoom_content); menu_affichage -> addAction(zoom_fit); menu_affichage -> addAction(zoom_reset); - + // menu Fenetres slot_updateWindowsMenu(); } @@ -562,6 +565,7 @@ void QETDiagramEditor::toolbar() { diagram_bar -> addAction(infos_diagram); diagram_bar -> addAction(conductor_reset); diagram_bar -> addAction(add_text); + diagram_bar -> addAction(add_image); // ajout de la barre d'outils a la fenetre principale addToolBar(Qt::TopToolBarArea, main_bar); @@ -1150,6 +1154,7 @@ void QETDiagramEditor::slot_updateActions() { remove_column -> setEnabled(editable_diagram); add_row -> setEnabled(editable_diagram); remove_row -> setEnabled(editable_diagram); + add_image ->setEnabled(editable_diagram); //display the beta feature only in debug mode #ifdef QT_NO_DEBUG @@ -1193,8 +1198,8 @@ void QETDiagramEditor::slot_updateComplexActions() { // actions ayant aussi besoin d'items (elements, conducteurs, textes, ...) selectionnes bool copiable_items = dv ? (dv -> hasCopiableItems()) : false; bool deletable_items = dv ? (dv -> hasDeletableItems()) : false; - cut -> setEnabled(editable_diagram && copiable_items); - copy -> setEnabled(copiable_items); + cut -> setEnabled(editable_diagram); + copy -> setEnabled(editable_diagram); delete_selection -> setEnabled(editable_diagram && deletable_items); rotate_selection -> setEnabled(editable_diagram && dv -> diagram() -> canRotateSelection()); selection_prop -> setEnabled(deletable_items); @@ -1482,11 +1487,20 @@ void QETDiagramEditor::slot_resetConductors() { Ajoute un texte au schema courant */ void QETDiagramEditor::slot_addText() { + add_image -> setChecked(false); if (DiagramView *dv = currentDiagram()) { dv -> addText(); } } - +/** + Ajoute une image au schema courant +*/ +void QETDiagramEditor::slot_addImage() { + add_text -> setChecked(false); + if (DiagramView *dv = currentDiagram()) { + dv -> addImage(); + } +} /** to Edit en text through the html editor */ @@ -1754,6 +1768,8 @@ void QETDiagramEditor::diagramWasAdded(DiagramView *dv) { connect(dv, SIGNAL(modeChanged()), this, SLOT(slot_updateModeActions())); connect(dv, SIGNAL(textAdded(bool)), add_text, SLOT(setChecked(bool))); connect(dv, SIGNAL(textAdded(bool)), add_edittext, SLOT(setChecked(bool))); + connect(dv, SIGNAL(ImageAdded(bool)), add_image, SLOT(setChecked(bool))); + connect(dv, SIGNAL(ImageAddedCanceled(bool)), add_image, SLOT(setChecked(bool))); } /** diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 5a31fd2ed..2df50e716 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -124,6 +124,7 @@ class QETDiagramEditor : public QETMainWindow { void slot_resetConductors(); void slot_addText(); void slot_editText(); + void slot_addImage(); void setWindowedMode(); void setTabbedMode(); void readSettings(); @@ -215,7 +216,7 @@ class QETDiagramEditor : public QETMainWindow { QAction *cascade_window; ///< Show MDI subwindows as cascade QAction *prev_window; ///< Switch to the previous document QAction *next_window; ///< Switch to the next document - + QAction *add_image; ///< Tool to add an independent image item on diagrams private: QMdiArea workspace; QSignalMapper windowMapper; diff --git a/sources/qeticons.cpp b/sources/qeticons.cpp index 1a257916b..7d9d7bf5e 100644 --- a/sources/qeticons.cpp +++ b/sources/qeticons.cpp @@ -152,6 +152,7 @@ namespace QET { QIcon ZoomIn; QIcon ZoomOriginal; QIcon ZoomOut; + QIcon adding_image; } } @@ -221,6 +222,7 @@ void QET::Icons::initIcons() { EditClear .addFile(":/ico/16x16/edit-clear.png"); EditClear .addFile(":/ico/22x22/edit-clear.png"); EditText .addFile(":/ico/22x22/names.png"); + adding_image .addFile(":/ico/22x22/insert-image.png"); if (rtl) { EditClearLocationBar.addPixmap(QPixmap(":/ico/16x16/edit-clear-locationbar-ltr.png").transformed(reverse)); diff --git a/sources/qeticons.h b/sources/qeticons.h index 562b5caea..0d9aeaa87 100644 --- a/sources/qeticons.h +++ b/sources/qeticons.h @@ -161,6 +161,7 @@ namespace QET { extern QIcon ZoomIn; extern QIcon ZoomOriginal; extern QIcon ZoomOut; + extern QIcon adding_image; } } #endif diff --git a/sources/qgimanager.cpp b/sources/qgimanager.cpp index 6aea18239..2e13fa5c7 100644 --- a/sources/qgimanager.cpp +++ b/sources/qgimanager.cpp @@ -60,8 +60,8 @@ void QGIManager::release(QGraphicsItem *qgi) { if (!qgi_manager.contains(qgi)) return; -- qgi_manager[qgi]; if (qgi_manager[qgi] <= 0 && !(scene -> items().contains(qgi))) { - qgi_manager.remove(qgi); delete qgi; + qgi_manager.remove(qgi); } }