2007-12-01 10:47:15 +00:00
/*
2015-02-20 14:56:22 +00:00
Copyright 2006 - 2015 The QElectroTech Team
2007-12-01 10:47:15 +00:00
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"
2013-02-08 22:05:15 +00:00
# include "elementprimitivedecorator.h"
2007-06-30 17:41:07 +00:00
# include <cmath>
# include "partline.h"
2009-04-03 19:30:25 +00:00
# include "partrectangle.h"
2007-06-30 17:41:07 +00:00
# include "partellipse.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-23 15:33:55 +00:00
# include "editorcommands.h"
2009-04-03 19:30:25 +00:00
# include "elementcontent.h"
2011-05-25 14:09:47 +00:00
# include "nameslist.h"
2014-06-03 20:21:19 +00:00
# include "ui/elementpropertieseditorwidget.h"
2014-11-04 22:08:42 +00:00
# include "eseventinterface.h"
# include <QKeyEvent>
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 ) ,
2014-10-19 11:25:03 +00:00
m_elmt_type ( " simple " ) ,
2007-08-25 03:43:05 +00:00
qgi_manager ( this ) ,
2014-11-04 22:08:42 +00:00
m_event_interface ( nullptr ) ,
2013-02-08 22:05:15 +00:00
element_editor ( editor ) ,
2014-10-19 11:25:03 +00:00
decorator_ ( 0 )
2007-06-30 17:41:07 +00:00
{
2014-11-11 12:02:08 +00:00
behavior = Normal ;
2010-02-28 16:13:45 +00:00
setItemIndexMethod ( NoIndex ) ;
2009-04-03 19:30:25 +00:00
setGrid ( 1 , 1 ) ;
initPasteArea ( ) ;
2007-08-25 15:46:09 +00:00
undo_stack . setClean ( ) ;
2013-02-08 22:05:15 +00:00
decorator_lock_ = new QMutex ( QMutex : : NonRecursive ) ;
connect ( & undo_stack , SIGNAL ( indexChanged ( int ) ) , this , SLOT ( managePrimitivesGroups ( ) ) ) ;
connect ( this , SIGNAL ( selectionChanged ( ) ) , this , SLOT ( managePrimitivesGroups ( ) ) ) ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/// Destructeur
2007-08-25 03:43:05 +00:00
ElementScene : : ~ ElementScene ( ) {
2013-02-08 22:05:15 +00:00
delete decorator_lock_ ;
2014-11-08 11:14:56 +00:00
if ( m_event_interface ) delete m_event_interface ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2014-11-10 21:47:28 +00:00
* @ brief ElementScene : : mouseMoveEvent
* @ param e
*/
2007-08-25 03:43:05 +00:00
void ElementScene : : mouseMoveEvent ( QGraphicsSceneMouseEvent * e ) {
2014-11-04 22:08:42 +00:00
if ( m_event_interface ) {
if ( m_event_interface - > mouseMoveEvent ( e ) ) {
if ( m_event_interface - > isFinish ( ) ) {
emit ( partsAdded ( ) ) ;
delete m_event_interface ; m_event_interface = nullptr ;
}
return ;
}
}
2009-04-03 19:30:25 +00:00
QPointF event_pos = e - > scenePos ( ) ;
2014-11-11 12:02:08 +00:00
if ( ! e - > modifiers ( ) & Qt : : ControlModifier )
event_pos = snapToGrid ( event_pos ) ;
2009-04-03 19:30:25 +00:00
if ( behavior = = PasteArea ) {
QRectF current_rect ( paste_area_ - > rect ( ) ) ;
current_rect . moveCenter ( event_pos ) ;
paste_area_ - > setRect ( current_rect ) ;
return ;
}
2014-11-09 21:58:46 +00:00
QGraphicsScene : : mouseMoveEvent ( e ) ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2014-11-10 21:47:28 +00:00
* @ brief ElementScene : : mousePressEvent
* @ param e
*/
2007-08-25 03:43:05 +00:00
void ElementScene : : mousePressEvent ( QGraphicsSceneMouseEvent * e ) {
2014-11-04 22:08:42 +00:00
if ( m_event_interface ) {
if ( m_event_interface - > mousePressEvent ( e ) ) {
if ( m_event_interface - > isFinish ( ) ) {
emit ( partsAdded ( ) ) ;
delete m_event_interface ; m_event_interface = nullptr ;
}
return ;
}
}
2014-11-09 21:58:46 +00:00
QGraphicsScene : : mousePressEvent ( e ) ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2014-11-10 21:47:28 +00:00
* @ brief ElementScene : : mouseReleaseEvent
* @ param e
*/
2007-08-25 03:43:05 +00:00
void ElementScene : : mouseReleaseEvent ( QGraphicsSceneMouseEvent * e ) {
2014-11-04 22:08:42 +00:00
if ( m_event_interface ) {
if ( m_event_interface - > mouseReleaseEvent ( e ) ) {
if ( m_event_interface - > isFinish ( ) ) {
emit ( partsAdded ( ) ) ;
delete m_event_interface ; m_event_interface = nullptr ;
}
return ;
}
}
2009-04-03 19:30:25 +00:00
if ( behavior = = PasteArea ) {
defined_paste_area_ = paste_area_ - > rect ( ) ;
removeItem ( paste_area_ ) ;
emit ( pasteAreaDefined ( defined_paste_area_ ) ) ;
behavior = Normal ;
return ;
}
2014-11-10 21:47:28 +00:00
QGraphicsScene : : mouseReleaseEvent ( e ) ;
2014-11-08 11:14:56 +00:00
}
2014-11-10 21:47:28 +00:00
/**
* @ brief ElementScene : : mouseDoubleClickEvent
* @ param event
*/
2014-11-08 11:14:56 +00:00
void ElementScene : : mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event ) {
if ( m_event_interface ) {
if ( m_event_interface - > mouseDoubleClickEvent ( event ) ) {
if ( m_event_interface - > isFinish ( ) ) {
emit ( partsAdded ( ) ) ;
delete m_event_interface ; m_event_interface = nullptr ;
}
return ;
}
}
QGraphicsScene : : mouseDoubleClickEvent ( event ) ;
2007-06-30 17:41:07 +00:00
}
2014-11-04 22:08:42 +00:00
/**
* @ brief ElementScene : : keyPressEvent
* manage key press event
* @ param event
*/
void ElementScene : : keyPressEvent ( QKeyEvent * event ) {
if ( m_event_interface ) {
if ( m_event_interface - > keyPressEvent ( event ) ) {
if ( m_event_interface - > isFinish ( ) ) {
emit ( partsAdded ( ) ) ;
delete m_event_interface ; m_event_interface = nullptr ;
}
return ;
}
}
QGraphicsScene : : keyPressEvent ( event ) ;
}
2007-06-30 17:41:07 +00:00
/**
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
2009-11-22 16:12:22 +00:00
@ param rect Le rectangle de la zone a dessiner
2007-06-30 17:41:07 +00:00
*/
2009-11-22 16:12:22 +00:00
void ElementScene : : drawForeground ( QPainter * p , const QRectF & rect ) {
Q_UNUSED ( rect ) ;
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 ) ;
2015-03-02 20:14:56 +00:00
QPen pen ( Qt : : red ) ;
pen . setCosmetic ( true ) ;
p - > setPen ( pen ) ;
2007-06-30 17:41:07 +00:00
p - > setBrush ( Qt : : NoBrush ) ;
2013-08-05 13:20:57 +00:00
p - > drawLine ( - 20 , 0 , 20 , 0 ) ;
p - > drawLine ( 0 , - 20 , 0 , 20 ) ;
2007-06-30 17:41:07 +00:00
p - > restore ( ) ;
}
2014-11-04 22:08:42 +00:00
/**
2014-11-06 09:44:20 +00:00
* @ brief ElementScene : : setEventInterface
2014-11-04 22:08:42 +00:00
* Set a new event interface
* @ param interface
*/
2015-03-02 20:14:56 +00:00
void ElementScene : : setEventInterface ( ESEventInterface * event_interface ) {
2014-11-10 22:57:32 +00:00
if ( m_event_interface ) {
delete m_event_interface ;
//We must to re-init because previous interface
//Reset his own init when deleted
2015-03-02 20:14:56 +00:00
event_interface - > init ( ) ;
2014-11-10 22:57:32 +00:00
}
2015-03-02 20:14:56 +00:00
m_event_interface = event_interface ;
2014-11-04 22:08:42 +00:00
}
2009-04-03 19:30:25 +00:00
/**
@ return la taille horizontale de la grille
*/
int ElementScene : : xGrid ( ) const {
return ( x_grid ) ;
}
/**
@ return la taille verticale de la grille
*/
int ElementScene : : yGrid ( ) const {
return ( y_grid ) ;
}
/**
2009-11-22 16:12:22 +00:00
@ param x_g Taille horizontale de la grille
@ param y_g Taille verticale de la grille
2009-04-03 19:30:25 +00:00
*/
void ElementScene : : setGrid ( int x_g , int y_g ) {
x_grid = x_g ? x_g : 1 ;
y_grid = y_g ? y_g : 1 ;
}
2007-12-05 21:16:01 +00:00
/**
Exporte l ' element en XML
2009-11-22 16:12:22 +00:00
@ param all_parts Booleen ( a vrai par defaut ) indiquant si le XML genere doit
2009-04-03 19:30:25 +00:00
representer tout l ' element ou seulement les elements selectionnes
2007-12-05 21:16:01 +00:00
@ return un document XML decrivant l ' element
*/
2013-09-21 13:09:23 +00:00
const QDomDocument ElementScene : : toXml ( bool all_parts ) {
2013-07-28 00:23:10 +00:00
QRectF size = elementSceneGeometricRect ( ) ;
2013-09-21 13:09:23 +00:00
//if the element doesn't contains the origin point of the scene
//we move the element to the origin for solve this default before saving
if ( ! size . contains ( 0 , 0 ) & & all_parts ) {
centerElementToOrigine ( ) ;
//recalcul the size after movement
size = elementSceneGeometricRect ( ) ;
}
//define the size of the element by the upper multiple of 10
2013-08-01 23:17:39 +00:00
int upwidth = ( ( qRound ( size . width ( ) ) / 10 ) * 10 ) + 10 ;
if ( ( qRound ( size . width ( ) ) % 10 ) > 6 ) upwidth + = 10 ;
2013-07-28 00:23:10 +00:00
2013-08-01 23:17:39 +00:00
int upheight = ( ( qRound ( size . height ( ) ) / 10 ) * 10 ) + 10 ;
if ( ( qRound ( size . height ( ) ) % 10 ) > 6 ) upheight + = 10 ;
2013-07-28 00:23:10 +00:00
2013-08-01 23:17:39 +00:00
//the margin between the real size of the element and the rectangle that delimits
int xmargin = qRound ( upwidth - size . width ( ) ) ;
int ymargin = qRound ( upheight - size . height ( ) ) ;
// document XML
QDomDocument xml_document ;
2007-06-30 17:41:07 +00:00
// racine du document XML
QDomElement root = xml_document . createElement ( " definition " ) ;
root . setAttribute ( " type " , " element " ) ;
2013-08-01 23:17:39 +00:00
root . setAttribute ( " width " , QString ( " %1 " ) . arg ( upwidth ) ) ;
root . setAttribute ( " height " , QString ( " %1 " ) . arg ( upheight ) ) ;
root . setAttribute ( " hotspot_x " , QString ( " %1 " ) . arg ( - ( qRound ( size . x ( ) - ( xmargin / 2 ) ) ) ) ) ;
root . setAttribute ( " hotspot_y " , QString ( " %1 " ) . arg ( - ( qRound ( size . y ( ) - ( ymargin / 2 ) ) ) ) ) ;
2013-11-14 10:11:22 +00:00
root . setAttribute ( " orientation " , " dyyy " ) ; //we keep the orientation for compatibility with previous version of qet
2007-10-04 17:32:41 +00:00
root . setAttribute ( " version " , QET : : version ) ;
2014-06-03 20:21:19 +00:00
root . setAttribute ( " link_type " , m_elmt_type ) ;
2007-06-30 17:41:07 +00:00
// noms de l'element
root . appendChild ( _names . toXml ( xml_document ) ) ;
2014-06-03 20:21:19 +00:00
2014-06-20 20:10:09 +00:00
if ( m_elmt_type = = " slave " | | m_elmt_type = = " master " ) {
2014-06-03 20:21:19 +00:00
QDomElement kindInfo = xml_document . createElement ( " kindInformations " ) ;
m_elmt_kindInfo . toXml ( kindInfo , " kindInformation " ) ;
root . appendChild ( kindInfo ) ;
}
2007-06-30 17:41:07 +00:00
2010-02-14 16:28:45 +00:00
// informations complementaires de l'element
QDomElement informations_element = xml_document . createElement ( " informations " ) ;
root . appendChild ( informations_element ) ;
informations_element . appendChild ( xml_document . createTextNode ( informations ( ) ) ) ;
2007-06-30 17:41:07 +00:00
QDomElement description = xml_document . createElement ( " description " ) ;
// description de l'element
2013-02-08 22:05:20 +00:00
foreach ( QGraphicsItem * qgi , zItems ( ) ) {
2009-04-03 19:30:25 +00:00
// si l'export ne concerne que la selection, on ignore les parties non selectionnees
if ( ! all_parts & & ! qgi - > isSelected ( ) ) continue ;
2007-06-30 17:41:07 +00:00
if ( CustomElementPart * ce = dynamic_cast < CustomElementPart * > ( qgi ) ) {
2007-12-15 21:57:00 +00:00
if ( ce - > isUseless ( ) ) continue ;
2007-06-30 17:41:07 +00:00
description . appendChild ( ce - > toXml ( xml_document ) ) ;
}
}
root . appendChild ( description ) ;
xml_document . appendChild ( root ) ;
return ( xml_document ) ;
}
2007-12-05 21:16:01 +00:00
/**
2009-04-03 19:30:25 +00:00
@ param xml_document un document XML decrivant un element
@ return le boundingRect du contenu de l ' element
2007-12-05 21:16:01 +00:00
*/
2009-04-03 19:30:25 +00:00
QRectF ElementScene : : boundingRectFromXml ( const QDomDocument & xml_document ) {
// charge les parties depuis le document XML
ElementContent loaded_content = loadContent ( xml_document ) ;
if ( loaded_content . isEmpty ( ) ) return ( QRectF ( ) ) ;
// calcule le boundingRect
QRectF bounding_rect = elementContentBoundingRect ( loaded_content ) ;
// detruit les parties chargees
qDeleteAll ( loaded_content ) ;
2007-06-30 17:41:07 +00:00
2009-04-03 19:30:25 +00:00
return ( bounding_rect ) ;
}
/**
Importe l ' element decrit dans un document XML . Si une position est
precisee , les elements importes sont positionnes de maniere a ce que le
coin superieur gauche du plus petit rectangle pouvant les entourant tous
( le bounding rect ) soit a cette position .
@ param xml_document un document XML decrivant l ' element
@ param position La position des parties importees
@ param consider_informations Si vrai , les informations complementaires
( dimensions , hotspot , etc . ) seront prises en compte
@ param content_ptr si ce pointeur vers un ElementContent est different de 0 ,
il sera rempli avec le contenu ajoute a l ' element par le fromXml
@ return true si l ' import a reussi , false sinon
*/
void ElementScene : : fromXml (
const QDomDocument & xml_document ,
const QPointF & position ,
bool consider_informations ,
ElementContent * content_ptr
) {
2007-06-30 17:41:07 +00:00
QString error_message ;
bool state = true ;
2009-04-03 19:30:25 +00:00
// prend en compte les informations de l'element
if ( consider_informations ) {
state = applyInformations ( xml_document , & error_message ) ;
2007-06-30 17:41:07 +00:00
}
2009-04-03 19:30:25 +00:00
// parcours des enfants de la definition : parties de l'element
2007-06-30 17:41:07 +00:00
if ( state ) {
2009-04-03 19:30:25 +00:00
ElementContent loaded_content = loadContent ( xml_document , & error_message ) ;
if ( position ! = QPointF ( ) ) {
addContentAtPos ( loaded_content , position , & error_message ) ;
2007-06-30 17:41:07 +00:00
} else {
2009-04-03 19:30:25 +00:00
addContent ( loaded_content , & error_message ) ;
2007-06-30 17:41:07 +00:00
}
2007-12-09 10:30:35 +00:00
2009-04-03 19:30:25 +00:00
// renvoie le contenu ajoute a l'element
if ( content_ptr ) {
* content_ptr = loaded_content ;
2007-06-30 17:41:07 +00:00
}
}
}
2013-07-28 00:23:10 +00:00
/**
@ return the minimum , margin - less rectangle the element can fit into , in scene
coordinates . It is different from itemsBoundingRect ( ) because it is not supposed
to imply any margin .
*/
QRectF ElementScene : : elementSceneGeometricRect ( ) const {
QRectF esgr ;
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( qgi - > type ( ) = = ElementPrimitiveDecorator : : Type ) continue ;
if ( qgi - > type ( ) = = QGraphicsRectItem : : Type ) continue ;
2014-07-03 22:48:36 +00:00
if ( qgi - > type ( ) = = PartTextField : : Type ) continue ;
2013-07-28 00:23:10 +00:00
if ( CustomElementPart * cep = dynamic_cast < CustomElementPart * > ( qgi ) ) {
esgr | = cep - > sceneGeometricRect ( ) ;
}
}
return ( esgr ) ;
}
2009-06-01 02:05:20 +00:00
/**
@ return true si l ' element comporte au moins une borne , false s ' il n ' en a
aucune .
*/
bool ElementScene : : containsTerminals ( ) const {
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( qgraphicsitem_cast < PartTerminal * > ( qgi ) ) {
return ( true ) ;
}
}
return ( false ) ;
}
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 ) ;
}
2009-04-03 19:30:25 +00:00
/**
@ return true si le presse - papier semble contenir un element
*/
bool ElementScene : : clipboardMayContainElement ( ) {
QString clipboard_text = QApplication : : clipboard ( ) - > text ( ) . trimmed ( ) ;
bool may_be_element = clipboard_text . startsWith ( " <definition " ) & & clipboard_text . endsWith ( " </definition> " ) ;
return ( may_be_element ) ;
}
/**
@ param clipboard_content chaine de caractere , provenant vraisemblablement du
presse - papier .
@ return true si clipboard_content a ete copie depuis cet element .
*/
bool ElementScene : : wasCopiedFromThisElement ( const QString & clipboard_content ) {
return ( clipboard_content = = last_copied_ ) ;
}
/**
Gere le fait de couper la selection = l ' exporter en XML dans le
presse - papier puis la supprimer .
*/
void ElementScene : : cut ( ) {
copy ( ) ;
QList < QGraphicsItem * > cut_content = selectedItems ( ) ;
clearSelection ( ) ;
undoStack ( ) . push ( new CutPartsCommand ( this , cut_content ) ) ;
}
/**
Gere le fait de copier la selection = l ' exporter en XML dans le
presse - papier .
*/
void ElementScene : : copy ( ) {
// accede au presse-papier
QClipboard * clipboard = QApplication : : clipboard ( ) ;
// genere la description XML de la selection
QString clipboard_content = toXml ( false ) . toString ( 4 ) ;
// met la description XML dans le presse-papier
if ( clipboard - > supportsSelection ( ) ) {
clipboard - > setText ( clipboard_content , QClipboard : : Selection ) ;
}
clipboard - > setText ( clipboard_content ) ;
// retient le dernier contenu copie
last_copied_ = clipboard_content ;
}
2013-09-17 20:14:30 +00:00
void ElementScene : : contextMenu ( QContextMenuEvent * event ) {
if ( behavior = = ElementScene : : Normal )
element_editor - > contextMenu ( event ) ;
}
2014-11-04 22:08:42 +00:00
QETElementEditor * ElementScene : : editor ( ) const {
return element_editor ;
}
2007-12-05 21:16:01 +00:00
/**
2009-04-18 18:08:54 +00:00
Selectionne une liste de parties
@ param content liste des parties a selectionner
2007-12-05 21:16:01 +00:00
*/
2009-04-18 18:08:54 +00:00
void ElementScene : : slot_select ( const ElementContent & content ) {
2009-04-18 14:21:08 +00:00
blockSignals ( true ) ;
2010-02-28 16:13:45 +00:00
clearSelection ( ) ;
2009-04-18 18:08:54 +00:00
foreach ( QGraphicsItem * qgi , content ) qgi - > setSelected ( true ) ;
2009-04-18 14:21:08 +00:00
blockSignals ( false ) ;
emit ( selectionChanged ( ) ) ;
2007-06-30 17:41:07 +00:00
}
2009-04-18 18:08:54 +00:00
/**
Selectionne tout
*/
void ElementScene : : slot_selectAll ( ) {
slot_select ( items ( ) ) ;
}
2007-12-05 21:16:01 +00:00
/**
Deselectionne tout
*/
2007-08-25 03:43:05 +00:00
void ElementScene : : slot_deselectAll ( ) {
2010-02-28 16:13:45 +00:00
slot_select ( ElementContent ( ) ) ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
Inverse la selection
*/
2007-08-25 03:43:05 +00:00
void ElementScene : : slot_invertSelection ( ) {
2009-04-18 14:21:08 +00:00
blockSignals ( true ) ;
2007-06-30 17:41:07 +00:00
foreach ( QGraphicsItem * qgi , items ( ) ) qgi - > setSelected ( ! qgi - > isSelected ( ) ) ;
2009-04-18 14:21:08 +00:00
blockSignals ( false ) ;
emit ( selectionChanged ( ) ) ;
2007-06-30 17:41:07 +00:00
}
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 ) ) ;
2013-02-08 22:05:15 +00:00
// removing items does not trigger QGraphicsScene::selectionChanged()
2007-11-07 20:23:24 +00:00
emit ( partsRemoved ( ) ) ;
2013-02-08 22:05:15 +00:00
emit ( selectionChanged ( ) ) ;
2007-06-30 17:41:07 +00:00
}
2010-02-14 16:28:45 +00:00
/**
Lance un dialogue pour editer les informations complementaires de cet
element . Concretement , ce champ libre est destine a accueillir des informations
sur l ' auteur de l ' element , sa licence , etc .
*/
void ElementScene : : slot_editAuthorInformations ( ) {
2010-02-28 16:13:45 +00:00
bool is_read_only = element_editor & & element_editor - > isReadOnly ( ) ;
2010-02-14 16:28:45 +00:00
// cree un dialogue
QDialog dialog_author ( element_editor ) ;
dialog_author . setModal ( true ) ;
2015-03-02 20:14:56 +00:00
# ifdef Q_OS_MAC
2010-02-14 16:28:45 +00:00
dialog_author . setWindowFlags ( Qt : : Sheet ) ;
# endif
dialog_author . setMinimumSize ( 400 , 260 ) ;
2015-03-02 20:14:56 +00:00
dialog_author . setWindowTitle ( tr ( " Éditer les informations sur l'auteur " , " window title " ) ) ;
2010-02-14 16:28:45 +00:00
QVBoxLayout * dialog_layout = new QVBoxLayout ( & dialog_author ) ;
// ajoute un champ explicatif au dialogue
2015-03-02 20:14:56 +00:00
QLabel * information_label = new QLabel ( tr ( " Vous pouvez utiliser ce champ libre pour mentionner les auteurs de l'élément, sa licence, ou tout autre renseignement que vous jugerez utile. " ) ) ;
2010-02-14 16:28:45 +00:00
information_label - > setAlignment ( Qt : : AlignJustify | Qt : : AlignVCenter ) ;
information_label - > setWordWrap ( true ) ;
dialog_layout - > addWidget ( information_label ) ;
// ajoute un QTextEdit au dialogue
QTextEdit * text_field = new QTextEdit ( ) ;
text_field - > setAcceptRichText ( false ) ;
text_field - > setPlainText ( informations ( ) ) ;
2010-02-28 16:13:45 +00:00
text_field - > setReadOnly ( is_read_only ) ;
2010-02-14 16:28:45 +00:00
dialog_layout - > addWidget ( text_field ) ;
// ajoute deux boutons au dialogue
2010-02-28 16:13:45 +00:00
QDialogButtonBox * dialog_buttons = new QDialogButtonBox ( is_read_only ? QDialogButtonBox : : Ok : QDialogButtonBox : : Ok | QDialogButtonBox : : Cancel ) ;
2010-02-14 16:28:45 +00:00
dialog_layout - > addWidget ( dialog_buttons ) ;
connect ( dialog_buttons , SIGNAL ( accepted ( ) ) , & dialog_author , SLOT ( accept ( ) ) ) ;
connect ( dialog_buttons , SIGNAL ( rejected ( ) ) , & dialog_author , SLOT ( reject ( ) ) ) ;
// lance le dialogue
2010-02-28 16:13:45 +00:00
if ( dialog_author . exec ( ) = = QDialog : : Accepted & & ! is_read_only ) {
2012-04-09 01:03:11 +00:00
QString new_infos = text_field - > toPlainText ( ) . remove ( QChar ( 13 ) ) ; // CR-less text
2010-02-14 16:28:45 +00:00
if ( new_infos ! = informations ( ) ) {
undoStack ( ) . push ( new ChangeInformationsCommand ( this , informations ( ) , new_infos ) ) ;
}
}
}
2014-06-03 20:21:19 +00:00
/**
* @ brief ElementScene : : slot_editProperties
* Open dialog to edit the element properties
*/
void ElementScene : : slot_editProperties ( ) {
2014-06-20 20:10:09 +00:00
QString type = m_elmt_type ;
DiagramContext info = m_elmt_kindInfo ;
ElementPropertiesEditorWidget epew ( type , info ) ;
2014-06-03 20:21:19 +00:00
epew . exec ( ) ;
2014-06-20 20:10:09 +00:00
if ( type ! = m_elmt_type | | info ! = m_elmt_kindInfo )
undoStack ( ) . push ( new ChangePropertiesCommand ( this , type , info ) ) ;
2014-06-03 20:21:19 +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 ( ) {
2010-02-28 16:13:45 +00:00
bool is_read_only = element_editor & & element_editor - > isReadOnly ( ) ;
2007-06-30 17:41:07 +00:00
// cree un dialogue
2008-08-17 20:41:37 +00:00
QDialog dialog ( element_editor ) ;
2015-03-02 20:14:56 +00:00
# ifdef Q_OS_MAC
2009-08-09 16:43:03 +00:00
dialog . setWindowFlags ( Qt : : Sheet ) ;
# endif
2007-06-30 17:41:07 +00:00
dialog . setModal ( true ) ;
2007-12-19 21:44:43 +00:00
dialog . setMinimumSize ( 400 , 330 ) ;
2015-03-02 20:14:56 +00:00
dialog . setWindowTitle ( tr ( " Éditer les noms " , " window title " ) ) ;
2007-06-30 17:41:07 +00:00
QVBoxLayout * dialog_layout = new QVBoxLayout ( & dialog ) ;
// ajoute un champ explicatif au dialogue
2015-03-02 20:14:56 +00:00
QLabel * information_label = new QLabel ( tr ( " Vous pouvez spécifier le nom de l'élément dans plusieurs langues. " ) ) ;
2007-06-30 17:41:07 +00:00
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 ) ;
2010-02-28 16:13:45 +00:00
names_widget - > setReadOnly ( is_read_only ) ;
2007-06-30 17:41:07 +00:00
dialog_layout - > addWidget ( names_widget ) ;
// ajoute deux boutons au dialogue
2010-02-28 16:13:45 +00:00
QDialogButtonBox * dialog_buttons = new QDialogButtonBox ( is_read_only ? QDialogButtonBox : : Ok : QDialogButtonBox : : Ok | QDialogButtonBox : : Cancel ) ;
2007-06-30 17:41:07 +00:00
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
2010-02-28 16:13:45 +00:00
if ( dialog . exec ( ) = = QDialog : : Accepted & & ! is_read_only ) {
2007-09-10 21:50:17 +00:00
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
}
2013-02-08 22:05:15 +00:00
/**
@ return the list of primitives currently present on the scene .
*/
QList < CustomElementPart * > ElementScene : : primitives ( ) const {
QList < CustomElementPart * > primitives_list ;
foreach ( QGraphicsItem * item , items ( ) ) {
if ( CustomElementPart * primitive = dynamic_cast < CustomElementPart * > ( item ) ) {
primitives_list < < primitive ;
}
}
return ( primitives_list ) ;
}
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
*/
2013-02-08 22:05:20 +00:00
QList < QGraphicsItem * > ElementScene : : zItems ( ItemOptions options ) const {
// handle dummy request, i.e. when neither Selected nor NonSelected are set
if ( ! ( options & ElementScene : : Selected ) & & ! ( options & ElementScene : : NonSelected ) ) {
return ( QList < QGraphicsItem * > ( ) ) ;
}
// retrieve all items
2007-10-07 18:52:01 +00:00
QList < QGraphicsItem * > all_items_list ( items ( ) ) ;
2013-02-08 22:05:20 +00:00
QMutableListIterator < QGraphicsItem * > i ( all_items_list ) ;
// remove unrequired items
if ( ( options & ElementScene : : SelectedOrNot ) ! = ElementScene : : SelectedOrNot ) {
bool keep_selected = options & ElementScene : : Selected ;
while ( i . hasNext ( ) ) {
if ( i . next ( ) - > isSelected ( ) ! = keep_selected ) {
i . remove ( ) ;
}
}
}
2007-10-07 18:52:01 +00:00
QList < QGraphicsItem * > terminals ;
2013-02-08 22:05:20 +00:00
QList < QGraphicsItem * > helpers ;
for ( i . toFront ( ) ; i . hasNext ( ) ; ) {
i . next ( ) ;
QGraphicsItem * qgi = i . value ( ) ;
2013-02-08 22:05:15 +00:00
if (
qgi - > type ( ) = = ElementPrimitiveDecorator : : Type | |
qgi - > type ( ) = = QGraphicsRectItem : : Type
) {
2013-02-08 22:05:20 +00:00
i . remove ( ) ;
helpers < < qgi ;
2013-02-08 22:05:15 +00:00
}
else if ( qgraphicsitem_cast < PartTerminal * > ( qgi ) ) {
2013-02-08 22:05:20 +00:00
i . remove ( ) ;
2007-10-07 18:52:01 +00:00
terminals < < qgi ;
}
}
// ordonne les parties par leur zValue
2013-02-08 22:05:20 +00:00
if ( options & SortByZValue ) {
qSort ( all_items_list . begin ( ) , all_items_list . end ( ) , ElementScene : : zValueLessThan ) ;
}
2007-10-07 18:52:01 +00:00
// rajoute eventuellement les bornes
2013-02-08 22:05:20 +00:00
if ( options & ElementScene : : IncludeTerminals ) {
all_items_list + = terminals ;
}
if ( options & ElementScene : : IncludeHelperItems ) {
all_items_list + = helpers ;
}
2007-10-07 18:52:01 +00:00
return ( all_items_list ) ;
}
2007-12-09 12:00:11 +00:00
2009-04-03 19:30:25 +00:00
/**
@ return les parties graphiques selectionnees
*/
ElementContent ElementScene : : selectedContent ( ) const {
ElementContent content ;
2013-02-08 22:05:20 +00:00
foreach ( QGraphicsItem * qgi , zItems ( ) ) {
2009-04-03 19:30:25 +00:00
if ( qgi - > isSelected ( ) ) content < < qgi ;
}
return ( content ) ;
}
/**
@ param to_paste Rectangle englobant les parties a coller
@ return le rectangle ou il faudra coller ces parties
*/
void ElementScene : : getPasteArea ( const QRectF & to_paste ) {
// on le dessine sur la scene
paste_area_ - > setRect ( to_paste ) ;
addItem ( paste_area_ ) ;
// on passe la scene en mode "recherche de zone pour copier/coller"
behavior = PasteArea ;
}
2007-12-09 12:00:11 +00:00
/**
Supprime les parties de l ' element et les objets d ' annulations .
Les autres caracteristiques sont conservees .
*/
void ElementScene : : reset ( ) {
// supprime les objets d'annulation
undoStack ( ) . clear ( ) ;
2013-07-28 22:48:36 +00:00
2007-12-09 12:00:11 +00:00
// enleve les elements de la scene
2013-07-28 22:48:36 +00:00
foreach ( QGraphicsItem * qgi , items ( ) ) {
2013-07-28 21:55:02 +00:00
removeItem ( qgi ) ;
2013-07-28 22:48:36 +00:00
qgiManager ( ) . release ( qgi ) ;
2007-12-09 12:00:11 +00:00
}
2013-07-28 22:48:36 +00:00
decorator_ = 0 ;
2007-12-09 12:00:11 +00:00
}
2009-04-03 19:30:25 +00:00
/**
@ param content Contenu ( = parties ) d ' un element
@ return le boundingRect de ces parties , exprime dans les coordonnes de la
scene
*/
2013-02-08 22:05:15 +00:00
QRectF ElementScene : : elementContentBoundingRect ( const ElementContent & content ) const {
2009-04-03 19:30:25 +00:00
QRectF bounding_rect ;
foreach ( QGraphicsItem * qgi , content ) {
2013-02-08 22:05:15 +00:00
// skip non-primitives QGraphicsItems (paste area, selection decorator)
if ( qgi - > type ( ) = = ElementPrimitiveDecorator : : Type ) continue ;
if ( qgi - > type ( ) = = QGraphicsRectItem : : Type ) continue ;
2009-04-03 19:30:25 +00:00
bounding_rect | = qgi - > sceneBoundingRect ( ) ;
}
return ( bounding_rect ) ;
}
/**
Applique les informations ( dimensions , hostpot , orientations , connexions
2010-02-14 16:28:45 +00:00
internes , noms et informations complementaires ) contenu dans un document XML .
2009-04-03 19:30:25 +00:00
@ param xml_document Document XML a analyser
@ param error_message pointeur vers une QString ; si error_message est
different de 0 , un message d ' erreur sera stocke dedans si necessaire
@ return true si la lecture et l ' application des informations s ' est bien
passee , false sinon .
*/
bool ElementScene : : applyInformations ( const QDomDocument & xml_document , QString * error_message ) {
2014-06-03 20:21:19 +00:00
// Root must be an element definition
2009-04-03 19:30:25 +00:00
QDomElement root = xml_document . documentElement ( ) ;
if ( root . tagName ( ) ! = " definition " | | root . attribute ( " type " ) ! = " element " ) {
if ( error_message ) {
2015-03-02 20:14:56 +00:00
* error_message = tr ( " Ce document XML n'est pas une définition d'élément. " , " error message " ) ;
2009-04-03 19:30:25 +00:00
}
return ( false ) ;
}
2013-11-14 10:11:22 +00:00
2014-06-03 20:21:19 +00:00
//Extract info about element type
m_elmt_type = root . attribute ( " link_type " , " simple " ) ;
m_elmt_kindInfo . fromXml ( root . firstChildElement ( " kindInformations " ) , " kindInformation " ) ;
//Extract names of xml definition
2009-04-03 19:30:25 +00:00
_names . fromXml ( root ) ;
2014-06-03 20:21:19 +00:00
//extract additional informations
2010-02-14 16:28:45 +00:00
setInformations ( QString ( ) ) ;
for ( QDomNode node = root . firstChild ( ) ; ! node . isNull ( ) ; node = node . nextSibling ( ) ) {
QDomElement elmt = node . toElement ( ) ;
if ( elmt . isNull ( ) ) continue ;
if ( elmt . tagName ( ) = = " informations " ) {
setInformations ( elmt . text ( ) ) ;
break ;
}
}
2009-04-03 19:30:25 +00:00
return ( true ) ;
}
/**
Par le document XML xml_document et retourne le contenu ( = liste de
parties ) correspondant .
@ param xml_document Document XML a analyser
@ param error_message pointeur vers une QString ; si error_message est
different de 0 , un message d ' erreur sera stocke dedans si necessaire
*/
ElementContent ElementScene : : loadContent ( const QDomDocument & xml_document , QString * error_message ) {
ElementContent loaded_parts ;
// la racine est supposee etre une definition d'element
QDomElement root = xml_document . documentElement ( ) ;
if ( root . tagName ( ) ! = " definition " | | root . attribute ( " type " ) ! = " element " ) {
if ( error_message ) {
2015-03-02 20:14:56 +00:00
* error_message = tr ( " Ce document XML n'est pas une définition d'élément. " , " error message " ) ;
2009-04-03 19:30:25 +00:00
}
return ( loaded_parts ) ;
}
// chargement de la description graphique de l'element
for ( QDomNode node = root . firstChild ( ) ; ! node . isNull ( ) ; node = node . nextSibling ( ) ) {
QDomElement elmts = node . toElement ( ) ;
if ( elmts . isNull ( ) ) continue ;
if ( elmts . tagName ( ) = = " description " ) {
// = 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 ;
2015-02-09 08:57:40 +00:00
if ( qde . tagName ( ) = = " line " ) cep = new PartLine ( element_editor ) ;
else if ( qde . tagName ( ) = = " rect " ) cep = new PartRectangle ( element_editor ) ;
else if ( qde . tagName ( ) = = " ellipse " ) cep = new PartEllipse ( element_editor ) ;
else if ( qde . tagName ( ) = = " circle " ) cep = new PartEllipse ( element_editor ) ;
else if ( qde . tagName ( ) = = " polygon " ) cep = new PartPolygon ( element_editor ) ;
else if ( qde . tagName ( ) = = " terminal " ) cep = new PartTerminal ( element_editor ) ;
else if ( qde . tagName ( ) = = " text " ) cep = new PartText ( element_editor ) ;
else if ( qde . tagName ( ) = = " input " ) cep = new PartTextField ( element_editor ) ;
else if ( qde . tagName ( ) = = " arc " ) cep = new PartArc ( element_editor ) ;
2009-04-03 19:30:25 +00:00
else continue ;
if ( QGraphicsItem * qgi = dynamic_cast < QGraphicsItem * > ( cep ) ) {
2012-05-11 21:27:31 +00:00
if ( ! qgi - > zValue ( ) ) qgi - > setZValue ( z + + ) ;
2009-04-03 19:30:25 +00:00
loaded_parts < < qgi ;
}
cep - > fromXml ( qde ) ;
}
}
}
return ( loaded_parts ) ;
}
/**
Ajoute le contenu content a cet element
@ param content contenu ( = liste de parties ) a charger
@ param error_message pointeur vers une QString ; si error_message est
different de 0 , un message d ' erreur sera stocke dedans si necessaire
@ return Le contenu ajoute
*/
2009-11-22 16:12:22 +00:00
ElementContent ElementScene : : addContent ( const ElementContent & content , QString * error_message ) {
Q_UNUSED ( error_message ) ;
2009-04-03 19:30:25 +00:00
foreach ( QGraphicsItem * part , content ) {
2013-02-08 22:05:15 +00:00
addPrimitive ( part ) ;
2009-04-03 19:30:25 +00:00
}
return ( content ) ;
}
/**
Ajoute le contenu content a cet element
@ param content contenu ( = liste de parties ) a charger
@ param pos Position du coin superieur gauche du contenu apres avoir ete ajoute
@ param error_message pointeur vers une QString ; si error_message est
different de 0 , un message d ' erreur sera stocke dedans si necessaire
@ return Le contenu ajoute
*/
2009-11-22 16:12:22 +00:00
ElementContent ElementScene : : addContentAtPos ( const ElementContent & content , const QPointF & pos , QString * error_message ) {
Q_UNUSED ( error_message ) ;
2009-04-03 19:30:25 +00:00
// calcule le boundingRect du contenu a ajouter
QRectF bounding_rect = elementContentBoundingRect ( content ) ;
// en deduit le decalage a appliquer aux parties pour les poser au point demander
QPointF offset = pos - bounding_rect . topLeft ( ) ;
// ajoute les parties avec le decalage adequat
foreach ( QGraphicsItem * part , content ) {
part - > setPos ( part - > pos ( ) + offset ) ;
2013-02-08 22:05:15 +00:00
addPrimitive ( part ) ;
2009-04-03 19:30:25 +00:00
}
return ( content ) ;
}
2013-02-08 22:05:15 +00:00
/**
Add a primitive to the scene by wrapping it within an
ElementPrimitiveDecorator group .
*/
void ElementScene : : addPrimitive ( QGraphicsItem * primitive ) {
if ( ! primitive ) return ;
addItem ( primitive ) ;
}
2009-04-03 19:30:25 +00:00
/**
Initialise la zone de collage
*/
void ElementScene : : initPasteArea ( ) {
paste_area_ = new QGraphicsRectItem ( ) ;
paste_area_ - > setZValue ( 1000000 ) ;
QPen paste_area_pen ;
paste_area_pen . setStyle ( Qt : : DashDotLine ) ;
paste_area_pen . setColor ( QColor ( 30 , 56 , 86 , 255 ) ) ;
QBrush paste_area_brush ;
paste_area_brush . setStyle ( Qt : : SolidPattern ) ;
paste_area_brush . setColor ( QColor ( 90 , 167 , 255 , 64 ) ) ;
paste_area_ - > setPen ( paste_area_pen ) ;
paste_area_ - > setBrush ( paste_area_brush ) ;
}
/**
Arrondit les coordonnees du point passees en parametre de facon a ce que ce
point soit aligne sur la grille .
@ param point une reference vers un QPointF . Cet objet sera modifie .
*/
2014-11-04 22:08:42 +00:00
QPointF ElementScene : : snapToGrid ( QPointF point ) {
2009-04-03 19:30:25 +00:00
point . rx ( ) = qRound ( point . x ( ) / x_grid ) * x_grid ;
point . ry ( ) = qRound ( point . y ( ) / y_grid ) * y_grid ;
2014-11-04 22:08:42 +00:00
return point ;
2009-04-03 19:30:25 +00:00
}
2012-05-11 21:38:50 +00:00
/**
@ return true if \ a item1 ' s zValue ( ) is less than \ a item2 ' s .
*/
bool ElementScene : : zValueLessThan ( QGraphicsItem * item1 , QGraphicsItem * item2 ) {
return ( item1 - > zValue ( ) < item2 - > zValue ( ) ) ;
}
2013-02-08 22:05:15 +00:00
2013-09-21 13:09:23 +00:00
/**
* @ brief ElementScene : : centerElementToOrigine
* try to center better is possible the element to the scene
* ( the calcul isn ' t optimal but work good )
*/
void ElementScene : : centerElementToOrigine ( ) {
QRectF size = elementSceneGeometricRect ( ) ;
int center_x = qRound ( size . center ( ) . x ( ) ) ;
int center_y = qRound ( size . center ( ) . y ( ) ) ;
//define the movement of translation
2015-03-02 20:14:56 +00:00
int move_x = center_x - ( center_x % 10 ) ;
2013-09-21 13:09:23 +00:00
if ( center_x < 0 ) move_x - = 10 ;
2015-03-02 20:14:56 +00:00
int move_y = center_y - ( center_y % 10 ) ;
2013-09-21 13:09:23 +00:00
if ( center_y < 0 ) move_y - = 10 ;
//move each primitive by @move
foreach ( QGraphicsItem * qgi , items ( ) ) {
if ( qgi - > type ( ) = = ElementPrimitiveDecorator : : Type ) continue ;
if ( qgi - > type ( ) = = QGraphicsRectItem : : Type ) continue ;
//deselect item for disable decorator
qgi - > setSelected ( false ) ;
qgi - > moveBy ( - ( move_x ) , - ( move_y ) ) ;
}
emit ( needZoomFit ( ) ) ;
}
2013-02-08 22:05:15 +00:00
/**
Ensure the decorator is adequately shown , hidden or updated so it always
represents the current selection .
*/
void ElementScene : : managePrimitivesGroups ( ) {
2013-02-08 22:05:20 +00:00
// this function is not supposed to be reentrant
2013-02-08 22:05:15 +00:00
if ( ! decorator_lock_ - > tryLock ( ) ) return ;
if ( ! decorator_ ) {
decorator_ = new ElementPrimitiveDecorator ( ) ;
connect ( decorator_ , SIGNAL ( actionFinished ( ElementEditionCommand * ) ) , this , SLOT ( stackAction ( ElementEditionCommand * ) ) ) ;
addItem ( decorator_ ) ;
decorator_ - > hide ( ) ;
}
// should we hide the decorator?
2013-02-08 22:05:20 +00:00
QList < QGraphicsItem * > selected_items = zItems ( ElementScene : : Selected | ElementScene : : IncludeTerminals ) ;
2013-02-08 22:05:15 +00:00
if ( ! selected_items . count ( ) ) {
decorator_ - > hide ( ) ;
} else {
decorator_ - > setZValue ( 1000000 ) ;
decorator_ - > setPos ( 0 , 0 ) ;
decorator_ - > setItems ( selected_items ) ;
}
decorator_lock_ - > unlock ( ) ;
}
/**
Push the provided \ a command on the undo stack .
*/
void ElementScene : : stackAction ( ElementEditionCommand * command ) {
if ( command - > elementScene ( ) ) {
if ( command - > elementScene ( ) ! = this ) return ;
} else {
command - > setElementScene ( this ) ;
}
if ( ! command - > elementView ( ) ) {
foreach ( QGraphicsView * view , views ( ) ) {
if ( ElementView * element_view = dynamic_cast < ElementView * > ( view ) ) {
command - > setElementView ( element_view ) ;
break ;
}
}
}
undoStack ( ) . push ( command ) ;
}