2007-12-01 10:47:15 +00:00
/*
2025-01-04 13:37:40 +01:00
Copyright 2006 - 2025 The QElectroTech Team
2007-12-01 10:47:15 +00:00
This file is part of QElectroTech .
2020-10-13 17:44:08 +02:00
2007-12-01 10:47:15 +00:00
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 .
2020-10-13 17:44:08 +02:00
2007-12-01 10:47:15 +00:00
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 .
2020-10-13 17:44:08 +02:00
2007-12-01 10:47:15 +00:00
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"
2020-12-08 19:57:35 +01:00
# include "../NameList/ui/namelistdialog.h"
# include "../NameList/ui/namelistwidget.h"
# include "../QPropertyUndoCommand/qpropertyundocommand.h"
# include "../QetGraphicsItemModeler/qetgraphicshandleritem.h"
# include "editorcommands.h"
# include "elementcontent.h"
2013-02-08 22:05:15 +00:00
# include "elementprimitivedecorator.h"
2020-12-10 21:19:45 +01:00
# include "esevent/eseventinterface.h"
2020-12-10 18:44:03 +01:00
# include "graphicspart/partarc.h"
# include "graphicspart/partdynamictextfield.h"
# include "graphicspart/partellipse.h"
# include "graphicspart/partline.h"
# include "graphicspart/partpolygon.h"
# include "graphicspart/partrectangle.h"
# include "graphicspart/partterminal.h"
# include "graphicspart/parttext.h"
2021-01-30 19:34:21 +01:00
# include "ui/qetelementeditor.h"
2014-06-03 20:21:19 +00:00
# include "ui/elementpropertieseditorwidget.h"
2023-01-19 20:18:21 +01:00
# include "../qetversion.h"
2014-11-04 22:08:42 +00:00
# include <QKeyEvent>
2020-12-08 19:57:35 +01:00
# include <algorithm>
# include <cmath>
2007-06-30 17:41:07 +00:00
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : ElementScene
constructor
\ ~ French Constructeur
\ ~ @ param editor : Element editor concerned
\ ~ French L ' editeur d ' element concerne
\ ~ @ param parent : Widget parent
\ ~ French le Widget parent
2007-12-05 21:16:01 +00:00
*/
2007-08-25 03:43:05 +00:00
ElementScene : : ElementScene ( QETElementEditor * editor , QObject * parent ) :
2007-06-30 17:41:07 +00:00
QGraphicsScene ( parent ) ,
2017-07-31 17:41:48 +00:00
m_qgi_manager ( this ) ,
m_element_editor ( editor )
2007-06-30 17:41:07 +00:00
{
2017-10-09 16:05:19 +00:00
setItemIndexMethod ( QGraphicsScene : : NoIndex ) ;
2020-07-28 20:56:41 +02:00
//Set to no index, because they can be the source of the crash with conductor and shape ghost.
//https://forum.qt.io/topic/71316/qgraphicsscenefinditembsptreevisitor-visit-crashes-due-to-an-obsolete-paintevent-after-qgraphicsscene-removeitem
//https://stackoverflow.com/questions/38458830/crash-after-qgraphicssceneremoveitem-with-custom-item-class
//http://www.qtcentre.org/archive/index.php/t-33730.html
//http://tech-artists.org/t/qt-properly-removing-qgraphicitems/3063
2020-10-13 17:43:26 +02:00
2017-07-31 17:41:48 +00:00
m_behavior = Normal ;
2010-02-28 16:13:45 +00:00
setItemIndexMethod ( NoIndex ) ;
2009-04-03 19:30:25 +00:00
setGrid ( 1 , 1 ) ;
initPasteArea ( ) ;
2017-07-31 17:41:48 +00:00
m_undo_stack . setClean ( ) ;
2020-10-13 17:43:26 +02:00
m_decorator_lock = new QMutex ( ) ;
2020-07-28 20:57:02 +02:00
connect ( & m_undo_stack , SIGNAL ( indexChanged ( int ) ) ,
this , SLOT ( managePrimitivesGroups ( ) ) ) ;
connect ( this , SIGNAL ( selectionChanged ( ) ) ,
2021-02-13 21:38:36 +01:00
this , SLOT ( managePrimitivesGroups ( ) ) ) ;
}
/**
* @ brief ElementScene : : elementData
* @ return the elementdata using by the scene
*/
ElementData ElementScene : : elementData ( ) {
return m_element_data ;
}
void ElementScene : : setElementData ( ElementData data )
{
bool emit_ = m_element_data . m_informations ! = data . m_informations ;
m_element_data = data ;
if ( emit_ )
emit elementInfoChanged ( ) ;
2007-06-30 17:41:07 +00:00
}
2017-01-02 18:15:18 +00:00
/**
2020-07-28 20:57:02 +02:00
@ brief ElementScene : : ~ ElementScene
2020-08-16 11:19:36 +02:00
*/
2017-01-02 18:15:18 +00:00
ElementScene : : ~ ElementScene ( )
{
2020-07-28 20:57:02 +02:00
//Disconnect to avoid crash, see bug report N° 122.
disconnect ( & m_undo_stack , SIGNAL ( indexChanged ( int ) ) ,
this , SLOT ( managePrimitivesGroups ( ) ) ) ;
2017-01-02 18:15:18 +00:00
delete m_decorator_lock ;
if ( m_event_interface )
delete m_event_interface ;
if ( m_decorator )
delete m_decorator ;
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : mouseMoveEvent
@ param e
*/
2020-10-13 17:44:08 +02: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 ( ) ) {
2020-07-28 20:57:02 +02:00
delete m_event_interface ;
m_event_interface = nullptr ;
2014-11-04 22:08:42 +00:00
}
return ;
}
}
2009-04-03 19:30:25 +00:00
QPointF event_pos = e - > scenePos ( ) ;
2015-05-25 15:15:02 +00:00
if ( ! ( e - > modifiers ( ) & Qt : : ControlModifier ) )
2014-11-11 12:02:08 +00:00
event_pos = snapToGrid ( event_pos ) ;
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
if ( m_behavior = = PasteArea ) {
QRectF current_rect ( m_paste_area - > rect ( ) ) ;
2009-04-03 19:30:25 +00:00
current_rect . moveCenter ( event_pos ) ;
2017-07-31 17:41:48 +00:00
m_paste_area - > setRect ( current_rect ) ;
2009-04-03 19:30:25 +00:00
return ;
}
2014-11-09 21:58:46 +00:00
QGraphicsScene : : mouseMoveEvent ( e ) ;
2020-10-13 17:44:08 +02:00
2007-06-30 17:41:07 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : mousePressEvent
@ param e
*/
2020-10-13 17:44:08 +02: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 ( ) ) {
2020-07-28 20:57:02 +02:00
delete m_event_interface ;
m_event_interface = nullptr ;
2014-11-04 22:08:42 +00:00
}
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : mouseReleaseEvent
@ param e
*/
2020-10-13 17:44:08 +02: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 ( ) ) {
2020-07-28 20:57:02 +02:00
delete m_event_interface ;
m_event_interface = nullptr ;
2014-11-04 22:08:42 +00:00
}
return ;
}
}
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
if ( m_behavior = = PasteArea ) {
m_defined_paste_area = m_paste_area - > rect ( ) ;
removeItem ( m_paste_area ) ;
emit ( pasteAreaDefined ( m_defined_paste_area ) ) ;
m_behavior = Normal ;
2009-04-03 19:30:25 +00:00
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : mouseDoubleClickEvent
@ param event
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event )
{
2014-11-08 11:14:56 +00:00
if ( m_event_interface ) {
if ( m_event_interface - > mouseDoubleClickEvent ( event ) ) {
if ( m_event_interface - > isFinish ( ) ) {
2020-07-28 20:57:02 +02:00
delete m_event_interface ;
m_event_interface = nullptr ;
2014-11-08 11:14:56 +00:00
}
return ;
}
}
QGraphicsScene : : mouseDoubleClickEvent ( event ) ;
2007-06-30 17:41:07 +00:00
}
2014-11-04 22:08:42 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : keyPressEvent
manage key press event
@ param event
*/
2018-03-20 10:59:39 +00:00
void ElementScene : : keyPressEvent ( QKeyEvent * event )
{
if ( m_event_interface )
{
if ( m_event_interface - > keyPressEvent ( event ) )
{
if ( m_event_interface - > isFinish ( ) )
{
2020-07-28 20:57:02 +02:00
delete m_event_interface ;
m_event_interface = nullptr ;
2014-11-04 22:08:42 +00:00
}
return ;
}
}
2020-10-13 17:44:08 +02:00
2018-03-20 10:59:39 +00:00
if ( selectedItems ( ) . size ( ) = = 1 )
2018-04-19 09:22:08 +00:00
{
if ( selectedItems ( ) . first ( ) - > type ( ) = = PartText : : Type )
{
PartText * t = static_cast < PartText * > ( selectedItems ( ) . first ( ) ) ;
if ( t - > textInteractionFlags ( ) & Qt : : TextEditorInteraction )
{
QGraphicsScene : : keyPressEvent ( event ) ;
return ;
}
}
2020-10-13 17:44:08 +02:00
2018-03-20 10:59:39 +00:00
QGraphicsObject * qgo = selectedItems ( ) . first ( ) - > toGraphicsObject ( ) ;
if ( qgo )
{
2019-08-26 12:37:58 +02:00
QPointF original_pos = qgo - > pos ( ) ;
QPointF p = qgo - > pos ( ) ;
2020-10-13 17:44:08 +02:00
2019-08-26 12:37:58 +02:00
if ( event - > modifiers ( ) & Qt : : ControlModifier ) {
2020-10-13 17:44:08 +02:00
2019-08-26 12:37:58 +02:00
int k = event - > key ( ) ;
if ( k = = Qt : : Key_Right )
p . rx ( ) + = 0.1 ;
else if ( k = = Qt : : Key_Left )
p . rx ( ) - = 0.1 ;
else if ( k = = Qt : : Key_Up )
p . ry ( ) - = 0.1 ;
else if ( k = = Qt : : Key_Down )
p . ry ( ) + = 0.1 ;
}
else {
2020-10-13 17:44:08 +02:00
2018-03-20 10:59:39 +00:00
int k = event - > key ( ) ;
if ( k = = Qt : : Key_Right )
p . rx ( ) + = 1 ;
else if ( k = = Qt : : Key_Left )
p . rx ( ) - = 1 ;
else if ( k = = Qt : : Key_Up )
p . ry ( ) - = 1 ;
else if ( k = = Qt : : Key_Down )
p . ry ( ) + = 1 ;
2019-08-26 12:37:58 +02:00
}
2020-10-13 17:44:08 +02:00
2018-03-20 10:59:39 +00:00
qgo - > setPos ( p ) ;
2020-07-28 20:57:02 +02:00
QPropertyUndoCommand * undo =
2020-10-13 17:44:08 +02:00
new QPropertyUndoCommand (
qgo , " pos " , QVariant ( original_pos ) , QVariant ( p ) ) ;
2018-03-20 10:59:39 +00:00
undo - > setText ( tr ( " Déplacer une primitive " ) ) ;
undo - > enableAnimation ( ) ;
undoStack ( ) . push ( undo ) ;
event - > accept ( ) ;
return ;
}
}
2020-10-13 17:44:08 +02:00
2014-11-04 22:08:42 +00:00
QGraphicsScene : : keyPressEvent ( event ) ;
}
2015-04-18 11:02:10 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : contextMenuEvent
Display the context menu event , only if behavior are Normal
@ param event
*/
2015-04-18 11:02:10 +00:00
void ElementScene : : contextMenuEvent ( QGraphicsSceneContextMenuEvent * event )
{
2018-06-30 21:41:27 +00:00
QGraphicsScene : : contextMenuEvent ( event ) ;
if ( event - > isAccepted ( ) )
return ;
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
if ( m_behavior = = ElementScene : : Normal )
m_element_editor - > contextMenu ( event - > screenPos ( ) ) ;
2015-04-18 11:02:10 +00:00
}
2007-06-30 17:41:07 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : drawForeground
Draws the background of the editor , ie the hotspot indicator .
\ ~ French Dessine l ' arriere - plan de l ' editeur , cad l ' indicateur de hotspot .
\ ~ @ param p : The QPainter to use for drawing
\ ~ French Le QPainter a utiliser pour dessiner
2007-06-30 17:41:07 +00:00
*/
2020-09-04 23:00:32 +02:00
void ElementScene : : drawForeground ( QPainter * p , const QRectF & )
{
2007-06-30 17:41:07 +00:00
p - > save ( ) ;
2020-09-04 23:00:32 +02:00
2007-06-30 17:41:07 +00:00
// desactive tout antialiasing, sauf pour le texte
p - > setRenderHint ( QPainter : : Antialiasing , false ) ;
p - > setRenderHint ( QPainter : : TextAntialiasing , true ) ;
p - > setRenderHint ( QPainter : : SmoothPixmapTransform , false ) ;
2020-09-04 23:00:32 +02:00
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : setEventInterface
Set a new event interface
2020-08-20 21:57:35 +02:00
@ param event_interface
2020-07-28 20:56:41 +02:00
*/
2017-07-31 17:41:48 +00:00
void ElementScene : : setEventInterface ( ESEventInterface * event_interface )
{
if ( m_event_interface )
{
2014-11-10 22:57:32 +00:00
delete m_event_interface ;
2022-12-04 08:21:12 -05:00
//We must re-init because previous interface
//Reset its 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
}
2017-07-31 17:41:48 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : clearEventInterface
Clear the current event interface
*/
2017-07-31 17:41:48 +00:00
void ElementScene : : clearEventInterface ( )
{
if ( m_event_interface )
{
delete m_event_interface ;
m_event_interface = nullptr ;
}
}
2015-04-18 11:02:10 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : setBehavior
Modify the current behavior of this scene
\ ~ French Modifie the current behavior of this scene
\ ~ @ param b
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : setBehavior ( ElementScene : : Behavior b )
{
2017-07-31 17:41:48 +00:00
m_behavior = b ;
2015-04-18 11:02:10 +00:00
}
2020-09-07 22:03:40 +02:00
ElementScene : : Behavior ElementScene : : behavior ( ) const
{
2018-06-30 21:41:27 +00:00
return m_behavior ;
}
2009-04-03 19:30:25 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : xGrid
@ return the horizontal size of the grid
\ ~ French la taille horizontale de la grille
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
int ElementScene : : xGrid ( ) const
{
2017-07-31 17:41:48 +00:00
return ( m_x_grid ) ;
2009-04-03 19:30:25 +00:00
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : yGrid
@ return vertical grid size
\ ~ French la taille verticale de la grille
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
int ElementScene : : yGrid ( ) const
{
2017-07-31 17:41:48 +00:00
return ( m_y_grid ) ;
2009-04-03 19:30:25 +00:00
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : setGrid
\ ~ @ param x_g : Horizontal grid size
\ ~ French Taille horizontale de la grille
\ ~ @ param y_g : Vertical grid size
\ ~ French Taille verticale de la grille
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : setGrid ( int x_g , int y_g )
{
2017-07-31 17:41:48 +00:00
m_x_grid = x_g ? x_g : 1 ;
m_y_grid = y_g ? y_g : 1 ;
2009-04-03 19:30:25 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : toXml
Export this element as a xml file
@ param all_parts : ( true by default )
if true , export the entire element in xml ,
if false , only export the selected parts .
@ return an xml document that describe the element .
*/
2015-06-28 16:30:13 +00:00
const QDomDocument ElementScene : : toXml ( bool all_parts )
{
2013-07-28 00:23:10 +00:00
QRectF size = elementSceneGeometricRect ( ) ;
2015-06-28 16:30:13 +00:00
2025-02-09 12:25:09 +01:00
// if the element doesn't contain the origin point of the scene
// we move the element to the origin to solve this default before saving
2015-06-28 16:30:13 +00:00
if ( ! size . contains ( 0 , 0 ) & & all_parts )
{
2013-09-21 13:09:23 +00:00
centerElementToOrigine ( ) ;
2020-07-28 20:56:41 +02:00
//recalcul the size after movement
size = elementSceneGeometricRect ( ) ;
2013-09-21 13:09:23 +00:00
}
2020-07-28 20:56:41 +02:00
// 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 ;
2020-07-28 20:57:02 +02:00
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 ;
2020-07-28 20:57:02 +02:00
if ( ( qRound ( size . height ( ) ) % 10 ) > 6 )
upheight + = 10 ;
2013-07-28 00:23:10 +00:00
2020-07-28 20:56:41 +02:00
// the margin between the real size of the element and the rectangle that delimits
2013-08-01 23:17:39 +00:00
int xmargin = qRound ( upwidth - size . width ( ) ) ;
int ymargin = qRound ( upheight - size . height ( ) ) ;
2020-07-28 20:56:41 +02:00
// document XML
2013-08-01 23:17:39 +00:00
QDomDocument xml_document ;
2015-06-28 16:30:13 +00:00
2020-07-28 20:56:41 +02:00
//Root of xml document
2007-06-30 17:41:07 +00:00
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 ) ) ;
2020-07-28 20:57:02 +02:00
root . setAttribute ( " hotspot_x " , QString ( " %1 " ) . arg (
- ( qRound ( size . x ( ) - ( xmargin / 2 ) ) ) ) ) ;
root . setAttribute ( " hotspot_y " , QString ( " %1 " ) . arg (
- ( qRound ( size . y ( ) - ( ymargin / 2 ) ) ) ) ) ;
2024-04-24 14:14:40 +02:00
QetVersion : : toXmlAttribute ( root ) ;
2021-02-13 21:38:36 +01:00
root . setAttribute ( " link_type " , m_element_data . typeToString ( m_element_data . m_type ) ) ;
2015-06-28 16:30:13 +00:00
2020-07-28 20:56:41 +02:00
//Uuid used to compare two elements
2015-06-28 16:30:13 +00:00
QDomElement uuid = xml_document . createElement ( " uuid " ) ;
uuid . setAttribute ( " uuid " , QUuid : : createUuid ( ) . toString ( ) ) ;
root . appendChild ( uuid ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
//names of element
2021-02-13 21:38:36 +01:00
root . appendChild ( m_element_data . m_names_list . toXml ( xml_document ) ) ;
2014-06-03 20:21:19 +00:00
2021-02-13 21:38:36 +01:00
auto type_ = m_element_data . m_type ;
2021-02-16 21:39:09 +01:00
if ( type_ = = ElementData : : Slave | |
type_ = = ElementData : : Master | |
2022-05-16 08:59:25 +02:00
type_ = = ElementData : : Terminale | |
type_ = = ElementData : : Thumbnail )
2015-06-28 16:30:13 +00:00
{
2021-02-13 21:38:36 +01:00
root . appendChild ( m_element_data . kindInfoToXml ( xml_document ) ) ;
2014-06-03 20:21:19 +00:00
}
2020-10-13 17:44:08 +02:00
2025-02-09 12:25:09 +01:00
if ( type_ = = ElementData : : Simple | |
type_ = = ElementData : : Master | |
type_ = = ElementData : : Terminale | |
2022-05-16 08:59:25 +02:00
type_ = = ElementData : : Thumbnail )
2017-10-01 15:25:34 +00:00
{
QDomElement element_info = xml_document . createElement ( " elementInformations " ) ;
2021-02-13 21:38:36 +01:00
m_element_data . m_informations . toXml ( element_info , " elementInformation " ) ;
2017-10-01 15:25:34 +00:00
root . appendChild ( element_info ) ;
}
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
//complementary information about the element
2010-02-14 16:28:45 +00:00
QDomElement informations_element = xml_document . createElement ( " informations " ) ;
root . appendChild ( informations_element ) ;
2021-02-13 21:38:36 +01:00
informations_element . appendChild ( xml_document . createTextNode ( m_element_data . m_drawing_information ) ) ;
2020-10-13 17:44:08 +02:00
2007-06-30 17:41:07 +00:00
QDomElement description = xml_document . createElement ( " description " ) ;
2015-06-28 16:30:13 +00:00
2020-07-28 20:56:41 +02:00
//the graphic description of the element
2017-02-05 16:18:50 +00:00
foreach ( QGraphicsItem * qgi , zItems ( ) )
2015-06-28 16:30:13 +00:00
{
2020-07-28 20:56:41 +02:00
//If the export concerns only the selection, the not selected part is ignored
2009-04-03 19:30:25 +00:00
if ( ! all_parts & & ! qgi - > isSelected ( ) ) continue ;
2018-07-30 15:24:29 +00:00
if ( CustomElementPart * ce = dynamic_cast < CustomElementPart * > ( qgi ) )
2015-06-28 16:30:13 +00:00
{
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 ) ;
2020-10-13 17:44:08 +02:00
2007-06-30 17:41:07 +00:00
xml_document . appendChild ( root ) ;
return ( xml_document ) ;
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : boundingRectFromXml
@ param xml_document : an XML document describing an element
\ ~ French un document XML decrivant un element
\ ~ @ return the boundingRect of the element ' s content
\ ~ French le boundingRect du contenu de l ' element
2007-12-05 21:16:01 +00:00
*/
2020-10-13 17:44:08 +02:00
QRectF ElementScene : : boundingRectFromXml ( const QDomDocument & xml_document )
{
2020-07-28 20:56:41 +02:00
// load parts from XML document
2009-04-03 19:30:25 +00:00
// charge les parties depuis le document XML
ElementContent loaded_content = loadContent ( xml_document ) ;
if ( loaded_content . isEmpty ( ) ) return ( QRectF ( ) ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// calcule the boundingRect
2009-04-03 19:30:25 +00:00
// calcule le boundingRect
QRectF bounding_rect = elementContentBoundingRect ( loaded_content ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// destroy charged parties
2009-04-03 19:30:25 +00:00
// detruit les parties chargees
qDeleteAll ( loaded_content ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
return ( bounding_rect ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : fromXml
Imports the element described in an XML document . If a position is
specified , the imported elements are positioned in such a way that the
upper left corner of the smallest rectangle that can surround them all
( the bounding rect ) either at this position .
\ ~ French Importe l ' element decrit dans un document XML . Si une position est
2009-04-03 19:30:25 +00:00
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 .
2020-07-28 20:56:41 +02:00
\ ~ @ param xml_document : an XML document describing the element
\ ~ French un document XML decrivant l ' element
\ ~ @ param position : The position of the imported parts
\ ~ French La position des parties importees
\ ~ @ param consider_informations : If true , additional information
( dimensions , hotspot , etc . ) will be taken into account
\ ~ French Si vrai , les informations complementaires
2009-04-03 19:30:25 +00:00
( dimensions , hotspot , etc . ) seront prises en compte
2020-07-28 20:56:41 +02:00
\ ~ @ param content_ptr :
if this pointer to an ElementContent is different from 0 ,
it will be filled with the content added to the element by the fromXml
\ ~ French si ce pointeur vers un ElementContent est different de 0 ,
2009-04-03 19:30:25 +00:00
il sera rempli avec le contenu ajoute a l ' element par le fromXml
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : fromXml (
const QDomDocument & xml_document ,
const QPointF & position ,
bool consider_informations ,
ElementContent * content_ptr )
2017-09-25 17:44:02 +00:00
{
2007-06-30 17:41:07 +00:00
bool state = true ;
2020-10-13 17:44:08 +02:00
2021-02-13 21:38:36 +01:00
//Consider the informations of the element
if ( consider_informations )
{
// Root must be an element definition
QDomElement root = xml_document . documentElement ( ) ;
if ( root . tagName ( ) = = " definition " & &
root . attribute ( " type " ) = = " element " ) {
m_element_data . fromXml ( root ) ;
}
2007-06-30 17:41:07 +00:00
}
2020-10-13 17:44:08 +02:00
2017-09-25 17:44:02 +00:00
if ( state )
{
ElementContent loaded_content = loadContent ( xml_document ) ;
if ( position ! = QPointF ( ) )
addContentAtPos ( loaded_content , position ) ;
else
addContent ( loaded_content ) ;
2020-10-13 17:44:08 +02:00
2017-09-25 17:44:02 +00:00
if ( content_ptr )
2009-04-03 19:30:25 +00:00
* content_ptr = loaded_content ;
2007-06-30 17:41:07 +00:00
}
}
2013-07-28 00:23:10 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : elementSceneGeometricRect
@ return the minimum , margin - less rectangle the element can fit into ,
in scene coordinates .
It is different from itemsBoundingRect ( ) because it is not supposed
2013-07-28 00:23:10 +00:00
to imply any margin .
*/
2020-10-13 17:44:08 +02:00
QRectF ElementScene : : elementSceneGeometricRect ( ) const
{
2013-07-28 00:23:10 +00:00
QRectF esgr ;
2017-02-05 16:18:50 +00:00
foreach ( QGraphicsItem * qgi , items ( ) ) {
2017-09-25 17:44:02 +00:00
if ( qgi - > type ( ) = = ElementPrimitiveDecorator : : Type ) continue ;
if ( qgi - > type ( ) = = QGraphicsRectItem : : Type ) continue ;
if ( qgi - > type ( ) = = PartDynamicTextField : : Type ) continue ;
2018-07-30 15:24:29 +00:00
if ( CustomElementPart * cep = dynamic_cast < CustomElementPart * > ( qgi ) ) {
2013-07-28 00:23:10 +00:00
esgr | = cep - > sceneGeometricRect ( ) ;
}
}
return ( esgr ) ;
}
2009-06-01 02:05:20 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : containsTerminals
@ return true if the element has at least one terminal ,
false if it has none .
\ ~ French true si l ' element comporte au moins une borne ,
false s ' il n ' en a aucune .
2009-06-01 02:05:20 +00:00
*/
2020-09-07 22:03:40 +02:00
bool ElementScene : : containsTerminals ( ) const
{
2020-10-13 17:44:08 +02:00
foreach ( QGraphicsItem * qgi , items ( ) )
{
if ( qgraphicsitem_cast < PartTerminal * > ( qgi ) )
{
2009-06-01 02:05:20 +00:00
return ( true ) ;
}
}
return ( false ) ;
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : undoStack
@ return the undo stack of this element editor
\ ~ French la pile d ' annulations de cet editeur d ' element
2007-12-05 21:16:01 +00:00
*/
2020-09-07 22:03:40 +02:00
QUndoStack & ElementScene : : undoStack ( )
{
2017-07-31 17:41:48 +00:00
return ( m_undo_stack ) ;
2007-08-23 15:33:55 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : qgiManager
@ return the QGraphicsItem manager of this item editor
\ ~ French le gestionnaire de QGraphicsItem de cet editeur d ' element
2007-12-05 21:16:01 +00:00
*/
2020-09-07 22:03:40 +02:00
QGIManager & ElementScene : : qgiManager ( )
{
2017-07-31 17:41:48 +00:00
return ( m_qgi_manager ) ;
2007-08-23 15:33:55 +00:00
}
2009-04-03 19:30:25 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : clipboardMayContainElement
@ return true if the clipboard appears to contain an element
\ ~ French true si le presse - papier semble contenir un element
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
bool ElementScene : : clipboardMayContainElement ( )
{
2009-04-03 19:30:25 +00:00
QString clipboard_text = QApplication : : clipboard ( ) - > text ( ) . trimmed ( ) ;
2020-07-28 20:56:41 +02:00
bool may_be_element = clipboard_text . startsWith ( " <definition " )
& & clipboard_text . endsWith ( " </definition> " ) ;
2009-04-03 19:30:25 +00:00
return ( may_be_element ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : wasCopiedFromThisElement
\ ~ @ param clipboard_content :
character string , probably coming from the clipboard .
\ ~ French chaine de caractere , provenant vraisemblablement du presse - papier .
\ ~ @ return
true if clipboard_content has been copied from this element .
\ ~ French true si clipboard_content a ete copie depuis cet element .
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
bool ElementScene : : wasCopiedFromThisElement ( const QString & clipboard_content )
{
2017-07-31 17:41:48 +00:00
return ( clipboard_content = = m_last_copied ) ;
2009-04-03 19:30:25 +00:00
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : cut
Handles the fact of cutting the selection
= exporting it in XML to the clipboard then deleting it .
\ ~ French Gere le fait de couper la selection
= l ' exporter en XML dans le presse - papier puis la supprimer .
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : cut ( )
{
2009-04-03 19:30:25 +00:00
copy ( ) ;
QList < QGraphicsItem * > cut_content = selectedItems ( ) ;
clearSelection ( ) ;
undoStack ( ) . push ( new CutPartsCommand ( this , cut_content ) ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : copy
Handles the fact of copying the selection
= exporting it as XML to the clipboard .
\ ~ French Gere le fait de copier la selection
= l ' exporter en XML dans lepresse - papier .
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : copy ( )
{
2009-04-03 19:30:25 +00:00
// accede au presse-papier
QClipboard * clipboard = QApplication : : clipboard ( ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
// genere la description XML de la selection
QString clipboard_content = toXml ( false ) . toString ( 4 ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
// met la description XML dans le presse-papier
if ( clipboard - > supportsSelection ( ) ) {
clipboard - > setText ( clipboard_content , QClipboard : : Selection ) ;
}
clipboard - > setText ( clipboard_content ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
// retient le dernier contenu copie
2017-07-31 17:41:48 +00:00
m_last_copied = clipboard_content ;
2009-04-03 19:30:25 +00:00
}
2020-07-28 20:56:41 +02:00
/**
@ brief ElementScene : : editor
@ return
*/
2020-09-07 22:03:40 +02:00
QETElementEditor * ElementScene : : editor ( ) const
{
2017-07-31 17:41:48 +00:00
return m_element_editor ;
2014-11-04 22:08:42 +00:00
}
2022-07-26 16:17:47 +02:00
/**
* @ brief ElementScene : : addItems
* Add items to the scene and emit partsAdded .
* Prefer always use this method instead of QGraphicsScene : : addItem
* even if you want to add one item , for gain the signal emission
* @ param items
*/
void ElementScene : : addItems ( QVector < QGraphicsItem * > items )
{
for ( const auto & item : items ) {
addItem ( item ) ;
}
emit partsAdded ( ) ;
}
/**
* @ brief ElementScene : : removeItems
* Remove items from the scene and emit partsRemoved .
* Prefer always use this method instead of QGraphicsScene : : removeItem
* even if you want to remove one item , for gain the signal emission
* @ param items
*/
void ElementScene : : removeItems ( QVector < QGraphicsItem * > items )
{
2022-08-13 13:06:46 +02:00
const int previous_selected_count { selectedItems ( ) . size ( ) } ;
//block signal to avoid multiple emit of selection changed,
//we emit this signal only once at the end of this function.
blockSignals ( true ) ;
2022-07-26 16:17:47 +02:00
for ( const auto & item : items ) {
removeItem ( item ) ;
}
2022-08-13 13:06:46 +02:00
blockSignals ( false ) ;
if ( previous_selected_count ! = selectedItems ( ) . size ( ) ) {
emit selectionChanged ( ) ;
}
2022-07-26 16:17:47 +02:00
emit partsRemoved ( ) ;
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_select
Select the item in content ,
every others items in the scene are deselected
@ param content
*/
2017-08-02 15:26:14 +00:00
void ElementScene : : slot_select ( const ElementContent & content )
{
2009-04-18 14:21:08 +00:00
blockSignals ( true ) ;
2020-10-13 17:44:08 +02:00
2022-12-04 08:21:12 -05:00
/* Before clearing selection,
* we must remove the handlers items in @ content ,
2020-07-28 20:56:41 +02:00
* because if in @ content there are a selected item ,
* but also its handlers items , When item is deselected ,
2022-12-04 08:21:12 -05:00
* the item deletes its handlers items ,
2020-07-28 20:56:41 +02:00
* then handlers in content doesn ' t exist anymore and cause segfault
*/
2017-08-02 15:26:14 +00:00
QList < QGraphicsItem * > items_list ;
for ( QGraphicsItem * qgi : content )
{
if ( qgi - > type ( ) ! = QetGraphicsHandlerItem : : Type )
items_list < < qgi ;
}
2010-02-28 16:13:45 +00:00
clearSelection ( ) ;
2017-08-02 15:26:14 +00:00
foreach ( QGraphicsItem * qgi , items_list )
qgi - > setSelected ( true ) ;
2020-10-13 17:44:08 +02:00
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_selectAll
Select all items
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : slot_selectAll ( )
{
2009-04-18 18:08:54 +00:00
slot_select ( items ( ) ) ;
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_deselectAll
deselect all item
*/
2020-09-07 22:03:40 +02: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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_invertSelection
Inverse Selection
\ ~ French Inverse la selection
2007-12-05 21:16:01 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : slot_invertSelection ( )
{
2009-04-18 14:21:08 +00:00
blockSignals ( true ) ;
2020-07-28 20:56:41 +02: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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_delete
Delete selected items
\ ~ French Supprime les elements selectionnes
2007-12-05 21:16:01 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : slot_delete ( )
{
2022-07-26 17:03:18 +02:00
const auto selected_items { selectedItems ( ) . toVector ( ) } ;
if ( selected_items . isEmpty ( ) ) {
return ;
}
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
m_undo_stack . push ( new DeletePartsCommand ( this , selected_items ) ) ;
2020-10-13 17:44:08 +02:00
2022-07-26 17:03:18 +02:00
// removing items does not trigger QGraphicsScene::selectionChanged()
2022-07-26 16:17:47 +02:00
emit selectionChanged ( ) ;
2007-06-30 17:41:07 +00:00
}
2010-02-14 16:28:45 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_editAuthorInformations
Starts a dialog to edit the additional information of this element .
Concretely , this free field is intended to receive information
on the author of the element , its license , etc .
\ ~ French 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 .
2010-02-14 16:28:45 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : slot_editAuthorInformations ( )
{
2017-07-31 17:41:48 +00:00
bool is_read_only = m_element_editor & & m_element_editor - > isReadOnly ( ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// create a dialogue
2010-02-14 16:28:45 +00:00
// cree un dialogue
2017-07-31 17:41:48 +00:00
QDialog dialog_author ( m_element_editor ) ;
2010-02-14 16:28:45 +00:00
dialog_author . setModal ( true ) ;
2019-09-08 18:29:29 +02:00
# ifdef Q_OS_MACOS
2010-02-14 16:28:45 +00:00
dialog_author . setWindowFlags ( Qt : : Sheet ) ;
# endif
dialog_author . setMinimumSize ( 400 , 260 ) ;
2020-10-13 17:44:08 +02:00
dialog_author . setWindowTitle (
tr ( " Éditer les informations sur l'auteur " , " window title " ) ) ;
2018-07-30 15:24:29 +00:00
QVBoxLayout * dialog_layout = new QVBoxLayout ( & dialog_author ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// adds an explanatory field to the dialogue
2010-02-14 16:28:45 +00:00
// 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 ) ;
2020-07-28 20:56:41 +02:00
// add a QTextEdit to the dialog
2010-02-14 16:28:45 +00:00
// ajoute un QTextEdit au dialogue
2018-07-30 15:24:29 +00:00
QTextEdit * text_field = new QTextEdit ( ) ;
2010-02-14 16:28:45 +00:00
text_field - > setAcceptRichText ( false ) ;
2021-02-13 21:38:36 +01:00
text_field - > setPlainText ( m_element_data . m_drawing_information ) ;
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 ) ;
2020-10-13 17:44:08 +02:00
2010-02-14 16:28:45 +00:00
// ajoute deux boutons au dialogue
2020-07-28 20:57:02 +02:00
QDialogButtonBox * dialog_buttons = new QDialogButtonBox (
is_read_only ? QDialogButtonBox : : Ok :
2020-10-13 17:44:08 +02:00
QDialogButtonBox : : Ok
| QDialogButtonBox : : Cancel ) ;
2010-02-14 16:28:45 +00:00
dialog_layout - > addWidget ( dialog_buttons ) ;
2020-07-28 20:57:02 +02:00
connect ( dialog_buttons , SIGNAL ( accepted ( ) ) , & dialog_author , SLOT ( accept ( ) ) ) ;
connect ( dialog_buttons , SIGNAL ( rejected ( ) ) , & dialog_author , SLOT ( reject ( ) ) ) ;
// start the dialogue
2010-02-14 16:28:45 +00:00
// lance le dialogue
2020-10-13 17:44:08 +02: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
2021-02-13 21:38:36 +01:00
if ( new_infos ! = m_element_data . m_drawing_information )
2020-10-13 17:44:08 +02:00
{
undoStack ( ) . push ( new ChangeInformationsCommand (
2021-02-13 21:38:36 +01:00
this , m_element_data . m_drawing_information , new_infos ) ) ;
2010-02-14 16:28:45 +00:00
}
}
}
2014-06-03 20:21:19 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_editProperties
Open dialog to edit the element properties
*/
2017-10-01 15:25:34 +00:00
void ElementScene : : slot_editProperties ( )
{
2021-02-13 21:38:36 +01:00
ElementPropertiesEditorWidget epew ( m_element_data ) ;
2014-06-03 20:21:19 +00:00
epew . exec ( ) ;
2020-10-13 17:44:08 +02:00
2021-02-13 21:38:36 +01:00
if ( m_element_data ! = epew . editedData ( ) )
{
undoStack ( ) . push ( new changeElementDataCommand ( this ,
m_element_data ,
epew . editedData ( ) ) ) ;
}
2014-06-03 20:21:19 +00:00
}
2007-12-05 21:16:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : slot_editNames
Launch a dialog for edit the names of the edited element
*/
2019-01-02 16:56:46 +00:00
void ElementScene : : slot_editNames ( )
{
2017-07-31 17:41:48 +00:00
bool is_read_only = m_element_editor & & m_element_editor - > isReadOnly ( ) ;
2020-10-13 17:44:08 +02:00
2019-01-02 16:56:46 +00:00
NameListDialog dialog_ ( m_element_editor ) ;
2020-10-13 17:44:08 +02:00
2019-01-02 16:56:46 +00:00
dialog_ . setModal ( true ) ;
dialog_ . setMinimumSize ( 400 , 330 ) ;
dialog_ . setWindowTitle ( tr ( " Éditer les noms " , " window title " ) ) ;
2020-10-13 17:44:08 +02:00
2019-01-02 16:56:46 +00:00
dialog_ . setInformationText ( tr ( " Vous pouvez spécifier le nom de l'élément dans plusieurs langues. " ) ) ;
2020-10-13 17:44:08 +02:00
2019-01-02 16:56:46 +00:00
NameListWidget * nlw_ = dialog_ . namelistWidget ( ) ;
2021-02-13 21:38:36 +01:00
nlw_ - > setNames ( m_element_data . m_names_list ) ;
2019-01-02 16:56:46 +00:00
nlw_ - > setReadOnly ( is_read_only ) ;
2020-10-13 17:44:08 +02:00
2019-01-02 16:56:46 +00:00
if ( dialog_ . exec ( ) = = QDialog : : Accepted & & ! is_read_only & & ! nlw_ - > isEmpty ( ) )
{
NamesList new_names = nlw_ - > names ( ) ;
2021-02-13 21:38:36 +01:00
if ( new_names ! = m_element_data . m_names_list ) {
2020-07-28 20:57:02 +02:00
undoStack ( ) . push ( new ChangeNamesCommand ( this ,
2021-02-13 21:38:36 +01:00
m_element_data . m_names_list ,
2020-07-28 20:57:02 +02:00
new_names ) ) ;
2019-01-02 16:56:46 +00:00
}
2007-09-10 21:50:17 +00:00
}
2007-06-30 17:41:07 +00:00
}
2013-02-08 22:05:15 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : primitives
2013-02-08 22:05:15 +00:00
@ return the list of primitives currently present on the scene .
*/
2020-09-07 22:03:40 +02:00
QList < CustomElementPart * > ElementScene : : primitives ( ) const
{
2013-02-08 22:05:15 +00:00
QList < CustomElementPart * > primitives_list ;
2020-10-13 17:44:08 +02:00
foreach ( QGraphicsItem * item , items ( ) )
{
if ( CustomElementPart * primitive = dynamic_cast < CustomElementPart * > ( item ) )
{
2013-02-08 22:05:15 +00:00
primitives_list < < primitive ;
}
}
return ( primitives_list ) ;
}
2007-10-07 18:52:01 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : zItems
@ param options
@ return the parts of the element ordered by increasing zValue
\ ~ French les parties de l ' element ordonnes par zValue croissante
2007-10-07 18:52:01 +00:00
*/
2020-09-07 22:03:40 +02:00
QList < QGraphicsItem * > ElementScene : : zItems ( ItemOptions options ) const
{
2013-02-08 22:05:20 +00:00
// handle dummy request, i.e. when neither Selected nor NonSelected are set
2020-07-28 20:57:02 +02:00
if ( ! ( options & ElementScene : : Selected )
& &
2020-10-13 17:44:08 +02:00
! ( options & ElementScene : : NonSelected ) )
{
2013-02-08 22:05:20 +00:00
return ( QList < QGraphicsItem * > ( ) ) ;
}
2020-10-13 17:44:08 +02:00
2013-02-08 22:05:20 +00:00
// 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 ) ;
2020-10-13 17:44:08 +02:00
2013-02-08 22:05:20 +00:00
// remove unrequired items
2020-07-28 20:57:02 +02:00
if ( ( options & ElementScene : : SelectedOrNot )
! = ElementScene : : SelectedOrNot ) {
2013-02-08 22:05:20 +00:00
bool keep_selected = options & ElementScene : : Selected ;
while ( i . hasNext ( ) ) {
if ( i . next ( ) - > isSelected ( ) ! = keep_selected ) {
i . remove ( ) ;
}
}
}
2020-10-13 17:44:08 +02:00
2007-10-07 18:52:01 +00:00
QList < QGraphicsItem * > terminals ;
2013-02-08 22:05:20 +00:00
QList < QGraphicsItem * > helpers ;
2020-10-13 17:44:08 +02:00
for ( i . toFront ( ) ; i . hasNext ( ) ; )
{
2013-02-08 22:05:20 +00:00
i . next ( ) ;
QGraphicsItem * qgi = i . value ( ) ;
2013-02-08 22:05:15 +00:00
if (
qgi - > type ( ) = = ElementPrimitiveDecorator : : Type | |
2017-08-24 14:48:58 +00:00
qgi - > type ( ) = = QGraphicsRectItem : : Type | |
qgi - > type ( ) = = QetGraphicsHandlerItem : : Type
2013-02-08 22:05:15 +00:00
) {
2013-02-08 22:05:20 +00:00
i . remove ( ) ;
helpers < < qgi ;
2013-02-08 22:05:15 +00:00
}
2020-10-13 17:44:08 +02: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 ;
}
}
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// orders the parts by their zValue
2007-10-07 18:52:01 +00:00
// ordonne les parties par leur zValue
2020-10-13 17:44:08 +02:00
if ( options & SortByZValue )
{
std : : sort (
all_items_list . begin ( ) ,
all_items_list . end ( ) ,
ElementScene : : zValueLessThan ) ;
2013-02-08 22:05:20 +00:00
}
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// possibly add the limits
2007-10-07 18:52:01 +00:00
// rajoute eventuellement les bornes
2020-10-13 17:44:08 +02:00
if ( options & ElementScene : : IncludeTerminals )
{
2013-02-08 22:05:20 +00:00
all_items_list + = terminals ;
}
2020-10-13 17:44:08 +02:00
if ( options & ElementScene : : IncludeHelperItems )
{
2013-02-08 22:05:20 +00:00
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : selectedContent
@ return the selected graphic parts
\ ~ French les parties graphiques selectionnees
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
ElementContent ElementScene : : selectedContent ( ) const
{
2009-04-03 19:30:25 +00:00
ElementContent content ;
2020-10-13 17:44:08 +02:00
foreach ( QGraphicsItem * qgi , zItems ( ) )
{
2009-04-03 19:30:25 +00:00
if ( qgi - > isSelected ( ) ) content < < qgi ;
}
return ( content ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : getPasteArea
\ ~ @ param to_paste : Rectangle enclosing the parts to be glued
\ ~ French Rectangle englobant les parties a coller
\ ~ @ return the rectangle where you will have to glue these parts
\ ~ French le rectangle ou il faudra coller ces parties
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : getPasteArea ( const QRectF & to_paste )
{
2020-07-28 20:56:41 +02:00
// we draw it on the stage
2009-04-03 19:30:25 +00:00
// on le dessine sur la scene
2017-07-31 17:41:48 +00:00
m_paste_area - > setRect ( to_paste ) ;
addItem ( m_paste_area ) ;
2020-07-28 20:56:41 +02:00
//we switch the scene to "zone search for copy / paste" mode
2009-04-03 19:30:25 +00:00
// on passe la scene en mode "recherche de zone pour copier/coller"
2017-07-31 17:41:48 +00:00
m_behavior = PasteArea ;
2009-04-03 19:30:25 +00:00
}
2007-12-09 12:00:11 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : reset
Remove all QGraphicsItems in the scene and clear the undo stack .
*/
2017-01-02 18:15:18 +00:00
void ElementScene : : reset ( )
{
2016-10-11 18:34:02 +00:00
clearSelection ( ) ;
2007-12-09 12:00:11 +00:00
undoStack ( ) . clear ( ) ;
2013-07-28 22:48:36 +00:00
2020-07-28 20:56:41 +02:00
// We don't add handlers,
// because it's the role of the primitive or decorator to remove it.
2017-08-02 15:26:14 +00:00
QList < QGraphicsItem * > items_list ;
for ( QGraphicsItem * qgi : items ( ) )
{
if ( qgi - > type ( ) ! = QetGraphicsHandlerItem : : Type )
items_list < < qgi ;
}
2020-10-13 17:44:08 +02:00
2017-08-02 15:26:14 +00:00
for ( QGraphicsItem * qgi : items_list )
2017-01-02 18:15:18 +00:00
{
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
}
2017-01-02 18:15:18 +00:00
delete m_decorator ;
m_decorator = nullptr ;
2007-12-09 12:00:11 +00:00
}
2009-04-03 19:30:25 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : elementContentBoundingRect
\ ~ @ param content : Content ( = parts ) of an element
\ ~ French Contenu ( = parties ) d ' un element
\ ~ @ return the boundingRect of these parts ,
expressed in the coordinates of the scene
\ ~ French le boundingRect de ces parties ,
exprime dans les coordonnes de la scene
2009-04-03 19:30:25 +00:00
*/
2020-07-28 20:57:02 +02:00
QRectF ElementScene : : elementContentBoundingRect (
2020-09-07 22:03:40 +02:00
const ElementContent & content ) const
{
2009-04-03 19:30:25 +00:00
QRectF bounding_rect ;
2017-02-05 16:18:50 +00:00
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 ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : loadContent
Create and load the content describe in the xml document .
@ param xml_document : xml dom document to analyze
@ return the loaded content
2009-04-03 19:30:25 +00:00
*/
2017-09-25 17:44:02 +00:00
ElementContent ElementScene : : loadContent ( const QDomDocument & xml_document )
{
2009-04-03 19:30:25 +00:00
ElementContent loaded_parts ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// The root is supposed to be an element definition
2009-04-03 19:30:25 +00:00
QDomElement root = xml_document . documentElement ( ) ;
2020-10-13 17:44:08 +02:00
2017-09-25 17:44:02 +00:00
if ( root . tagName ( ) ! = " definition " | | root . attribute ( " type " ) ! = " element " )
2009-04-03 19:30:25 +00:00
return ( loaded_parts ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
//Load the graphic description of the element
2017-09-25 17:44:02 +00:00
for ( QDomNode node = root . firstChild ( ) ; ! node . isNull ( ) ; node = node . nextSibling ( ) )
{
2009-04-03 19:30:25 +00:00
QDomElement elmts = node . toElement ( ) ;
2017-09-25 17:44:02 +00:00
if ( elmts . isNull ( ) )
continue ;
2020-10-13 17:44:08 +02:00
2017-09-25 17:44:02 +00:00
if ( elmts . tagName ( ) = = " description " )
{
2009-04-03 19:30:25 +00:00
int z = 1 ;
2017-09-25 17:44:02 +00:00
for ( QDomNode n = node . firstChild ( ) ; ! n . isNull ( ) ; n = n . nextSibling ( ) )
{
2009-04-03 19:30:25 +00:00
QDomElement qde = n . toElement ( ) ;
2017-09-25 17:44:02 +00:00
if ( qde . isNull ( ) )
continue ;
CustomElementPart * cep = nullptr ;
2017-09-27 15:31:57 +00:00
PartDynamicTextField * pdtf = nullptr ;
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
if ( qde . tagName ( ) = = " line " ) cep = new PartLine ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " rect " ) cep = new PartRectangle ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " ellipse " ) cep = new PartEllipse ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " circle " ) cep = new PartEllipse ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " polygon " ) cep = new PartPolygon ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " terminal " ) cep = new PartTerminal ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " text " ) cep = new PartText ( m_element_editor ) ;
else if ( qde . tagName ( ) = = " arc " ) cep = new PartArc ( m_element_editor ) ;
2017-09-25 17:44:02 +00:00
else if ( qde . tagName ( ) = = " dynamic_text " ) cep = new PartDynamicTextField ( m_element_editor ) ;
2020-07-28 20:56:41 +02:00
//For the input (aka the old text field) we try to convert it to the new partDynamicTextField
2018-03-11 14:44:21 +00:00
else if ( qde . tagName ( ) = = " input " ) cep = pdtf = new PartDynamicTextField ( m_element_editor ) ;
2009-04-03 19:30:25 +00:00
else continue ;
2020-10-13 17:44:08 +02:00
2018-07-30 15:24:29 +00:00
if ( QGraphicsItem * qgi = dynamic_cast < QGraphicsItem * > ( cep ) )
2017-09-25 17:44:02 +00:00
{
if ( ! qgi - > zValue ( ) )
qgi - > setZValue ( z + + ) ;
2020-10-13 17:44:08 +02:00
2017-09-25 17:44:02 +00:00
loaded_parts < < qgi ;
2020-10-13 17:44:08 +02:00
2018-03-11 14:44:21 +00:00
if ( pdtf )
2017-09-27 15:31:57 +00:00
pdtf - > fromTextFieldXml ( qde ) ;
else
cep - > fromXml ( qde ) ;
2009-04-03 19:30:25 +00:00
}
2017-09-25 17:44:02 +00:00
else
delete cep ;
2009-04-03 19:30:25 +00:00
}
}
}
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
return ( loaded_parts ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : addContent
Add content content to this element
\ ~ French Ajoute le contenu content a cet element
\ ~ @ param content :
content ( = list of parts ) to load
\ ~ French contenu ( = liste de parties ) a charger
\ ~ @ return Content adds
\ ~ French Le contenu ajoute
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
ElementContent ElementScene : : addContent ( const ElementContent & content )
{
2017-02-05 16:18:50 +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 ) ;
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : addContentAtPos
Add content content to this element
\ ~ French Ajoute le contenu content a cet element
\ ~ @ param content :
content ( = list of parts ) to load
\ ~ French contenu ( = liste de parties ) a charger
\ ~ @ param pos :
Position of the upper left corner of the content after being added
\ ~ French Position du coin superieur gauche du contenu apres avoir ete ajoute
\ ~ @ return Content adds
\ ~ French Le contenu ajoute
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
ElementContent ElementScene : : addContentAtPos (
const ElementContent & content ,
const QPointF & pos )
{
2020-07-28 20:57:02 +02:00
// calculate the boundingRect of the content to add
2009-04-03 19:30:25 +00:00
// calcule le boundingRect du contenu a ajouter
QRectF bounding_rect = elementContentBoundingRect ( content ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
/* deduced the offset to be applied to the parts to place
* them at the point requested
* en deduit le decalage a appliquer aux parties pour les poser
* au point demander
*/
2009-04-03 19:30:25 +00:00
QPointF offset = pos - bounding_rect . topLeft ( ) ;
2020-10-13 17:44:08 +02:00
2020-07-28 20:56:41 +02:00
// add the parts with the correct offset
2009-04-03 19:30:25 +00:00
// ajoute les parties avec le decalage adequat
2017-02-05 16:18:50 +00:00
foreach ( QGraphicsItem * part , content ) {
2009-04-03 19:30:25 +00:00
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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : addPrimitive
2013-02-08 22:05:15 +00:00
Add a primitive to the scene by wrapping it within an
ElementPrimitiveDecorator group .
2020-07-28 20:56:41 +02:00
@ param primitive
2013-02-08 22:05:15 +00:00
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : addPrimitive ( QGraphicsItem * primitive )
{
2013-02-08 22:05:15 +00:00
if ( ! primitive ) return ;
addItem ( primitive ) ;
}
2009-04-03 19:30:25 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : initPasteArea
Initializes the paste area
\ ~ French Initialise la zone de collage
2009-04-03 19:30:25 +00:00
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : initPasteArea ( )
{
2017-07-31 17:41:48 +00:00
m_paste_area = new QGraphicsRectItem ( ) ;
m_paste_area - > setZValue ( 1000000 ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
QPen paste_area_pen ;
paste_area_pen . setStyle ( Qt : : DashDotLine ) ;
paste_area_pen . setColor ( QColor ( 30 , 56 , 86 , 255 ) ) ;
2020-10-13 17:44:08 +02:00
2009-04-03 19:30:25 +00:00
QBrush paste_area_brush ;
paste_area_brush . setStyle ( Qt : : SolidPattern ) ;
paste_area_brush . setColor ( QColor ( 90 , 167 , 255 , 64 ) ) ;
2020-10-13 17:44:08 +02:00
2017-07-31 17:41:48 +00:00
m_paste_area - > setPen ( paste_area_pen ) ;
m_paste_area - > setBrush ( paste_area_brush ) ;
2009-04-03 19:30:25 +00:00
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : snapToGrid
Rounds the coordinates of the point passed as a parameter
so that this point is aligned with the grid .
\ ~ French Arrondit les coordonnees du point passees en parametre
de facon a ce que ce point soit aligne sur la grille .
\ ~ @ param point :
a reference to a QPointF . This object will be modified .
\ ~ French une reference vers un QPointF . Cet objet sera modifie .
\ ~ @ return point
2009-04-03 19:30:25 +00:00
*/
2020-10-13 17:44:08 +02:00
QPointF ElementScene : : snapToGrid ( QPointF point )
{
2017-07-31 17:41:48 +00:00
point . rx ( ) = qRound ( point . x ( ) / m_x_grid ) * m_x_grid ;
point . ry ( ) = qRound ( point . y ( ) / m_y_grid ) * m_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
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : zValueLessThan
@ param item1 : QGraphicsItem
@ param item2 : QGraphicsItem
2012-05-11 21:38:50 +00:00
@ return true if \ a item1 ' s zValue ( ) is less than \ a item2 ' s .
*/
2020-10-13 17:44:08 +02:00
bool ElementScene : : zValueLessThan ( QGraphicsItem * item1 , QGraphicsItem * item2 )
{
2012-05-11 21:38:50 +00:00
return ( item1 - > zValue ( ) < item2 - > zValue ( ) ) ;
}
2013-02-08 22:05:15 +00:00
2013-09-21 13:09:23 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : centerElementToOrigine
try to center better is possible the element to the scene
( the calcul isn ' t optimal but work good )
*/
2020-09-07 22:03:40 +02:00
void ElementScene : : centerElementToOrigine ( )
{
2013-09-21 13:09:23 +00:00
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 ;
2020-07-28 20:57:02 +02:00
//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-09-21 13:09:23 +00:00
}
2013-02-08 22:05:15 +00:00
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : managePrimitivesGroups
Ensure the decorator is adequately shown , hidden or updated so it always
represents the current selection .
*/
2017-01-02 18:15:18 +00:00
void ElementScene : : managePrimitivesGroups ( )
{
2020-07-28 20:56:41 +02:00
//this function is not supposed to be reentrant
2017-01-02 18:15:18 +00:00
if ( ! m_decorator_lock - > tryLock ( ) )
return ;
2020-10-13 17:44:08 +02:00
2017-01-02 18:15:18 +00:00
if ( ! m_decorator )
{
m_decorator = new ElementPrimitiveDecorator ( ) ;
2020-07-28 20:57:02 +02:00
connect ( m_decorator ,
SIGNAL ( actionFinished ( ElementEditionCommand * ) ) ,
this , SLOT ( stackAction ( ElementEditionCommand * ) ) ) ;
2017-01-02 18:15:18 +00:00
addItem ( m_decorator ) ;
m_decorator - > hide ( ) ;
2013-02-08 22:05:15 +00:00
}
2020-10-13 17:44:08 +02:00
2022-08-13 12:40:59 +02:00
if ( m_single_selected_item ) {
m_single_selected_item - > removeHandler ( ) ;
m_single_selected_item . clear ( ) ;
}
2015-07-20 17:45:37 +00:00
// should we hide the decorator?
2022-08-13 12:40:59 +02:00
const auto selected_items { zItems ( ElementScene : : Selected | ElementScene : : IncludeTerminals ) } ;
2020-07-28 20:57:02 +02:00
if ( selected_items . size ( ) < = 1 )
2017-08-02 15:26:14 +00:00
{
2022-08-13 12:40:59 +02:00
m_decorator - > hide ( ) ;
if ( ! selected_items . isEmpty ( ) )
{
if ( CustomElementGraphicPart * item_ = dynamic_cast < CustomElementGraphicPart * > ( selected_items . first ( ) ) )
{
item_ - > addHandler ( ) ;
m_single_selected_item = item_ ;
}
}
2017-08-02 15:26:14 +00:00
}
2015-07-20 17:45:37 +00:00
else
{
2017-01-02 18:15:18 +00:00
m_decorator - > setZValue ( 1000000 ) ;
m_decorator - > setPos ( 0 , 0 ) ;
m_decorator - > setItems ( selected_items ) ;
2013-02-08 22:05:15 +00:00
}
2017-01-02 18:15:18 +00:00
m_decorator_lock - > unlock ( ) ;
2013-02-08 22:05:15 +00:00
}
/**
2020-07-28 20:56:41 +02:00
@ brief ElementScene : : stackAction
2013-02-08 22:05:15 +00:00
Push the provided \ a command on the undo stack .
2020-07-28 20:56:41 +02:00
@ param command
2013-02-08 22:05:15 +00:00
*/
2020-10-13 17:44:08 +02:00
void ElementScene : : stackAction ( ElementEditionCommand * command )
{
2013-02-08 22:05:15 +00:00
if ( command - > elementScene ( ) ) {
if ( command - > elementScene ( ) ! = this ) return ;
} else {
command - > setElementScene ( this ) ;
}
2020-10-13 17:44:08 +02:00
2013-02-08 22:05:15 +00:00
if ( ! command - > elementView ( ) ) {
2017-02-05 16:18:50 +00:00
foreach ( QGraphicsView * view , views ( ) ) {
2020-07-28 20:57:02 +02:00
if ( ElementView * element_view =
dynamic_cast < ElementView * > ( view ) ) {
2013-02-08 22:05:15 +00:00
command - > setElementView ( element_view ) ;
break ;
}
}
}
2020-10-13 17:44:08 +02:00
2013-02-08 22:05:15 +00:00
undoStack ( ) . push ( command ) ;
}