qelectrotech-source-mirror/sources/diagramtextitem.cpp
xavier c8732714b8 Il est desormais possible de deplacer les champs de texte des conducteurs.
Leur deplacement est limite aux alentours du trajet de leur conducteur parent,
Reorganisation du code pour tout ce qui est relatif aux deplacements d'items sur les schemas.


git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/branches/0.3@987 bfdf4180-ca20-0410-9c96-a3a8aa849046
2010-05-08 21:24:43 +00:00

300 lines
9.7 KiB
C++

/*
Copyright 2006-2010 Xavier Guerrin
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "diagramtextitem.h"
#include "diagramcommands.h"
#include "qet.h"
#include "qetapp.h"
/**
Constructeur
@param parent Le QGraphicsItem parent du champ de texte
@param parent_diagram Le schema auquel appartient le champ de texte
*/
DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, Diagram *parent_diagram) :
QGraphicsTextItem(parent, parent_diagram),
previous_text_(),
rotation_angle_(0.0)
{
setDefaultTextColor(Qt::black);
setFont(QETApp::diagramTextsFont());
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
}
/**
Constructeur
@param text Le texte affiche par le champ de texte
@param parent Le QGraphicsItem parent du champ de texte
@param parent_diagram Le schema auquel appartient le champ de texte
*/
DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, Diagram *parent_diagram) :
QGraphicsTextItem(text, parent, parent_diagram),
previous_text_(text),
rotation_angle_(0.0)
{
setDefaultTextColor(Qt::black);
setFont(QETApp::diagramTextsFont());
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
#if QT_VERSION >= 0x040600
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
#endif
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
}
/// Destructeur
DiagramTextItem::~DiagramTextItem() {
}
/**
@return le Diagram auquel ce texte appartient, ou 0 si ce texte n'est
rattache a aucun schema
*/
Diagram *DiagramTextItem::diagram() const {
return(qobject_cast<Diagram *>(scene()));
}
/**
@return l'angle de rotation actuel de ce texte
*/
qreal DiagramTextItem::rotationAngle() const {
return(rotation_angle_);
}
/**
Permet de tourner le texte a un angle donne de maniere absolue.
Un angle de 0 degres correspond a un texte horizontal non retourne.
@param rotation Nouvel angle de rotation de ce texte
@see applyRotation
*/
void DiagramTextItem::setRotationAngle(const qreal &rotation) {
qreal applied_rotation = QET::correctAngle(rotation);
applyRotation(applied_rotation - rotation_angle_);
rotation_angle_ = applied_rotation;
}
/**
Permet de tourner le texte de maniere relative.
L'angle added_rotation est ajoute a l'orientation actuelle du texte.
@param added_rotation Angle a ajouter a la rotation actuelle
@see applyRotation
*/
void DiagramTextItem::rotateBy(const qreal &added_rotation) {
qreal applied_added_rotation = QET::correctAngle(added_rotation);
rotation_angle_ = QET::correctAngle(rotation_angle_ + applied_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 DiagramTextItem::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 DiagramTextItem::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 DiagramTextItem::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 DiagramTextItem::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 texte.
Cette methode delegue simplement le travail a QGraphicsTextItem::paint apres
avoir desactive l'antialiasing.
@param painter Le QPainter a utiliser pour dessiner le champ de texte
@param option Les options de style pour le champ de texte
@param widget Le QWidget sur lequel on dessine
*/
void DiagramTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
painter -> setRenderHint(QPainter::Antialiasing, false);
QGraphicsTextItem::paint(painter, option, widget);
}
/**
Gere la prise de focus du champ de texte
@param e Objet decrivant la prise de focus
*/
void DiagramTextItem::focusInEvent(QFocusEvent *e) {
QGraphicsTextItem::focusInEvent(e);
// empeche le deplacement du texte pendant son edition
setFlag(QGraphicsItem::ItemIsMovable, false);
// memorise le texte avant que l'utilisateur n'y touche
previous_text_ = toPlainText();
// cela permettra de determiner si l'utilisateur a modifie le texte a la fin de l'edition
}
/**
Gere la perte de focus du champ de texte
@param e Objet decrivant la perte de focus
*/
void DiagramTextItem::focusOutEvent(QFocusEvent *e) {
QGraphicsTextItem::focusOutEvent(e);
// signale la modification du texte si besoin
if (toPlainText() != previous_text_) {
emit(diagramTextChanged(this, previous_text_, toPlainText()));
previous_text_ = toPlainText();
}
// deselectionne le texte
QTextCursor cursor = textCursor();
cursor.clearSelection();
setTextCursor(cursor);
// hack a la con pour etre re-entrant
setTextInteractionFlags(Qt::NoTextInteraction);
// autorise de nouveau le deplacement du texte
setFlag(QGraphicsItem::ItemIsMovable, true);
QTimer::singleShot(0, this, SIGNAL(lostFocus()));
}
/**
Gere les double-clics sur ce champ de texte.
@param event un QGraphicsSceneMouseEvent decrivant le double-clic
*/
void DiagramTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
if (!(textInteractionFlags() & Qt::TextEditable)) {
// rend le champ de texte editable
setTextInteractionFlags(Qt::TextEditorInteraction);
// edite le champ de texte
setFocus(Qt::MouseFocusReason);
} else {
QGraphicsTextItem::mouseDoubleClickEvent(event);
}
}
/**
Effetue la rotation du texte en elle-meme
Pour les DiagramTextItem, la rotation s'effectue autour du point (0, 0).
Cette methode peut toutefois etre redefinie dans des classes
@param angle Angle de la rotation a effectuer
*/
void DiagramTextItem::applyRotation(const qreal &angle) {
// un simple appel a QGraphicsTextItem::rotate suffit
QGraphicsTextItem::rotate(angle);
}
/**
Change la position du champ de texte en veillant a ce qu'il
reste sur la grille du schema auquel il appartient.
@param p Nouvelles coordonnees de l'element
*/
void DiagramTextItem::setPos(const QPointF &p) {
if (p == pos()) return;
// pas la peine de positionner sur la grille si l'element n'est pas sur un Diagram
if (scene()) {
// arrondit l'abscisse a 10 px pres
int p_x = qRound(p.x() / (Diagram::xGrid * 1.0)) * Diagram::xGrid;
// arrondit l'ordonnee a 10 px pres
int p_y = qRound(p.y() / (Diagram::yGrid * 1.0)) * Diagram::yGrid;
QGraphicsTextItem::setPos(p_x, p_y);
} else QGraphicsTextItem::setPos(p);
}
/**
Change la position du champ de texte en veillant a ce que l'il
reste sur la grille du schema auquel il appartient.
@param x Nouvelle abscisse de l'element
@param y Nouvelle ordonnee de l'element
*/
void DiagramTextItem::setPos(qreal x, qreal y) {
setPos(QPointF(x, y));
}
/**
@return la position du champ de texte
*/
QPointF DiagramTextItem::pos() const {
return(QGraphicsTextItem::pos());
}
/// Rend le champ de texte non focusable
void DiagramTextItem::setNonFocusable() {
setFlag(QGraphicsTextItem::ItemIsFocusable, false);
}