2017-08-03 17:36:08 +00:00
/*
2019-01-13 16:56:12 +00:00
Copyright 2006 - 2019 The QElectroTech Team
2017-08-03 17:36:08 +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/>.
*/
# include "deleteqgraphicsitemcommand.h"
# include "dynamicelementtextitem.h"
# include "diagram.h"
# include "element.h"
# include "conductor.h"
# include "conductortextitem.h"
2017-11-29 14:49:12 +00:00
# include "elementtextitemgroup.h"
2017-12-05 21:41:29 +00:00
# include "addelementtextcommand.h"
2019-01-09 18:08:49 +00:00
# include "terminal.h"
# include "diagramcommands.h"
2020-05-12 11:17:25 +02:00
# include "qetgraphicstableitem.h"
2020-06-05 20:00:13 +02:00
# include "qetdiagrameditor.h"
2017-08-03 17:36:08 +00:00
/**
* @ brief DeleteQGraphicsItemCommand : : DeleteQGraphicsItemCommand
* @ param diagram : deigram where this undo work
* @ param content : content to remove
* @ param parent : parent undo
*/
DeleteQGraphicsItemCommand : : DeleteQGraphicsItemCommand ( Diagram * diagram , const DiagramContent & content , QUndoCommand * parent ) :
QUndoCommand ( parent ) ,
m_removed_contents ( content ) ,
m_diagram ( diagram )
{
//If parent element of a dynamic element text item is also in @m_removed_content,
//we remove it, because when the element will be removed from the scene every child's will also be removed.
const QSet < DynamicElementTextItem * > elmt_set = m_removed_contents . m_element_texts ;
for ( DynamicElementTextItem * deti : elmt_set )
{
2017-08-22 18:27:23 +00:00
if ( m_removed_contents . m_elements . contains ( deti - > parentElement ( ) ) )
2017-08-03 17:36:08 +00:00
m_removed_contents . m_element_texts . remove ( deti ) ;
}
2017-12-05 21:41:29 +00:00
//When remove a deti we must to know his parent item, for re-add deti as child of the parent
//when undo this command
2017-08-03 17:36:08 +00:00
for ( DynamicElementTextItem * deti : m_removed_contents . m_element_texts )
2017-11-29 14:49:12 +00:00
{
if ( deti - > parentGroup ( ) )
m_grp_texts_hash . insert ( deti , deti - > parentGroup ( ) ) ;
else
m_elmt_text_hash . insert ( deti , deti - > parentElement ( ) ) ;
}
2017-08-03 17:36:08 +00:00
2017-12-05 21:41:29 +00:00
//If parent element of ElementTextItemGroup is also in @m_removed_content,
//we remove it, because when the element will be removed from the scene every child's will also be removed.
const QSet < ElementTextItemGroup * > group_set = m_removed_contents . m_texts_groups ;
for ( ElementTextItemGroup * group : group_set )
{
if ( m_removed_contents . m_elements . contains ( group - > parentElement ( ) ) )
m_removed_contents . m_texts_groups . remove ( group ) ;
}
//The deletion of the groups is not managed by this undo, but by a RemoveTextsGroupCommand
for ( ElementTextItemGroup * group : m_removed_contents . m_texts_groups ) {
2019-01-09 18:08:49 +00:00
new RemoveTextsGroupCommand ( group - > parentElement ( ) , group , this ) ;
}
2017-12-05 21:41:29 +00:00
m_removed_contents . m_texts_groups . clear ( ) ;
2019-01-09 18:08:49 +00:00
setPotentialsOfRemovedElements ( ) ;
2020-05-12 11:17:25 +02:00
2020-06-05 20:00:13 +02:00
//Get all linkeds table of removed table.
2020-05-12 11:17:25 +02:00
for ( auto table : m_removed_contents . m_tables )
{
2020-06-05 20:00:13 +02:00
//Table is already managed, jump to next loop
if ( m_table_scene_hash . keys ( ) . contains ( table ) )
continue ;
auto first_table = table ; //The first table if the table is linked to another
while ( first_table - > previousTable ( ) )
first_table = first_table - > previousTable ( ) ;
auto current_table = first_table ;
m_table_scene_hash . insert ( first_table , first_table - > scene ( ) ) ;
while ( current_table - > nextTable ( ) )
{
current_table = current_table - > nextTable ( ) ;
m_table_scene_hash . insert ( current_table , current_table - > scene ( ) ) ;
}
2020-05-12 11:17:25 +02:00
}
2017-12-05 21:41:29 +00:00
2017-08-03 17:36:08 +00:00
setText ( QString ( QObject : : tr ( " supprimer %1 " , " undo caption - %1 is a sentence listing the removed content " ) ) . arg ( m_removed_contents . sentence ( DiagramContent : : All ) ) ) ;
2020-06-05 20:00:13 +02:00
//Table is now managed by @m_table_scene_hash, we clear the tables of m_removed_content
m_removed_contents . m_tables . clear ( ) ;
2017-08-03 17:36:08 +00:00
m_diagram - > qgiManager ( ) . manage ( m_removed_contents . items ( DiagramContent : : All ) ) ;
}
DeleteQGraphicsItemCommand : : ~ DeleteQGraphicsItemCommand ( ) {
m_diagram - > qgiManager ( ) . release ( m_removed_contents . items ( DiagramContent : : All ) ) ;
}
2019-01-09 18:08:49 +00:00
/**
* @ brief DeleteQGraphicsItemCommand : : setPotentialsOfRemovedElements
* This function creates new conductors ( if needed ) for conserve the electrical potentials
* present at the terminals of each removed elements .
*/
void DeleteQGraphicsItemCommand : : setPotentialsOfRemovedElements ( )
{
for ( Element * elmt : m_removed_contents . m_elements )
{
//a list of terminals who have at least two conductors docked in.
QList < Terminal * > terminals_list ;
for ( Terminal * t : elmt - > terminals ( ) ) {
if ( t - > conductors ( ) . size ( ) > = 2 ) {
terminals_list . append ( t ) ;
}
}
if ( terminals_list . isEmpty ( ) ) {
continue ;
}
for ( Terminal * t : terminals_list )
{
//All new created conductors will be docked to hub_terminal
Terminal * hub_terminal = nullptr ;
QList < Terminal * > terminals_to_connect_list ;
for ( Conductor * c : t - > conductors ( ) )
{
Terminal * other_terminal = c - > terminal1 = = t ? c - > terminal2 : c - > terminal1 ;
if ( m_removed_contents . items ( DiagramContent : : Elements ) . contains ( other_terminal - > parentElement ( ) ) )
{
other_terminal = terminalInSamePotential ( other_terminal , c ) ;
if ( other_terminal = = nullptr ) {
continue ;
}
}
terminals_to_connect_list . append ( other_terminal ) ;
if ( hub_terminal = = nullptr ) {
hub_terminal = other_terminal ;
}
//hub_terminal must be the terminal the more at top left of the diagram.
else if ( other_terminal - > scenePos ( ) . x ( ) < hub_terminal - > scenePos ( ) . x ( ) ) {
hub_terminal = other_terminal ;
}
else if ( other_terminal - > scenePos ( ) . x ( ) = = hub_terminal - > scenePos ( ) . x ( ) ) {
if ( other_terminal - > scenePos ( ) . y ( ) < hub_terminal - > scenePos ( ) . y ( ) ) {
hub_terminal = other_terminal ;
}
}
}
terminals_to_connect_list . removeAll ( hub_terminal ) ;
if ( hub_terminal = = nullptr | | terminals_to_connect_list . isEmpty ( ) ) {
continue ;
}
ConductorProperties properties = hub_terminal - > conductors ( ) . first ( ) - > properties ( ) ;
for ( Terminal * t : terminals_to_connect_list )
{
//If a conductor was already created between these two terminals
//in this undo command, from another removed element, we do nothing
bool exist_ = false ;
for ( QPair < Terminal * , Terminal * > pair : m_connected_terminals )
{
if ( pair . first = = hub_terminal & & pair . second = = t ) {
exist_ = true ;
continue ;
} else if ( pair . first = = t & & pair . second = = hub_terminal ) {
exist_ = true ;
continue ;
}
}
if ( exist_ = = false )
{
m_connected_terminals . append ( qMakePair < Terminal * , Terminal * > ( hub_terminal , t ) ) ;
Conductor * new_cond = new Conductor ( hub_terminal , t ) ;
new_cond - > setProperties ( properties ) ;
new AddItemCommand < Conductor * > ( new_cond , t - > diagram ( ) , QPointF ( ) , this ) ;
}
}
}
}
}
/**
* @ brief DeleteQGraphicsItemCommand : : terminalInSamePotential
* Return a terminal at the same potential of @ terminal , by traveling through the conductors connected to @ terminal
* only if the owner element of the terminal is not delete by this undo command .
* Return nullptr if a terminal can ' t be found .
* @ param terminal - terminal from search
* @ param conductor_to_exclude - a conductor to exlcude from search .
* @ return
*/
Terminal * DeleteQGraphicsItemCommand : : terminalInSamePotential ( Terminal * terminal , Conductor * conductor_to_exclude )
{
QList < Conductor * > conductor_list = terminal - > conductors ( ) ;
conductor_list . removeAll ( conductor_to_exclude ) ;
for ( Conductor * c : conductor_list )
{
Terminal * other_terminal = c - > terminal1 = = terminal ? c - > terminal2 : c - > terminal1 ;
if ( ! m_removed_contents . items ( DiagramContent : : Elements ) . contains ( other_terminal - > parentElement ( ) ) ) {
return other_terminal ;
}
}
//No one of direct conductor of terminal are docked to an element which is not removed
for ( Conductor * c : conductor_list )
{
Terminal * other_terminal = c - > terminal1 = = terminal ? c - > terminal2 : c - > terminal1 ;
Terminal * terminal_to_return = terminalInSamePotential ( other_terminal , c ) ;
if ( terminal_to_return ! = nullptr ) {
return terminal_to_return ;
}
}
return nullptr ;
}
2017-08-03 17:36:08 +00:00
/**
* @ brief DeleteQGraphicsItemCommand : : undo
* Undo this command
*/
void DeleteQGraphicsItemCommand : : undo ( )
{
m_diagram - > showMe ( ) ;
for ( QGraphicsItem * item : m_removed_contents . items ( ) )
m_diagram - > addItem ( item ) ;
//We relink element after every element was added to diagram
for ( Element * e : m_removed_contents . m_elements )
for ( Element * elmt : m_link_hash [ e ] )
e - > linkToElement ( elmt ) ;
for ( DynamicElementTextItem * deti : m_removed_contents . m_element_texts )
{
2017-11-29 14:49:12 +00:00
if ( m_elmt_text_hash . keys ( ) . contains ( deti ) )
m_elmt_text_hash . value ( deti ) - > addDynamicTextItem ( deti ) ;
else if ( m_grp_texts_hash . keys ( ) . contains ( deti ) )
{
Element * elmt = m_grp_texts_hash . value ( deti ) - > parentElement ( ) ;
elmt - > addDynamicTextItem ( deti ) ;
elmt - > addTextToGroup ( deti , m_grp_texts_hash . value ( deti ) ) ;
}
2017-08-03 17:36:08 +00:00
}
2020-05-12 11:17:25 +02:00
2020-06-05 20:00:13 +02:00
for ( auto table : m_table_scene_hash . keys ( ) )
2020-05-12 11:17:25 +02:00
{
2020-06-05 20:00:13 +02:00
if ( ! m_table_scene_hash . value ( table ) . isNull ( ) ) {
m_table_scene_hash . value ( table ) - > addItem ( table ) ;
2020-05-12 11:17:25 +02:00
}
}
2017-12-05 21:41:29 +00:00
QUndoCommand : : undo ( ) ;
2017-08-03 17:36:08 +00:00
}
/**
* @ brief DeleteQGraphicsItemCommand : : redo
* Redo the delete command
*/
void DeleteQGraphicsItemCommand : : redo ( )
{
m_diagram - > showMe ( ) ;
for ( Conductor * c : m_removed_contents . conductors ( DiagramContent : : AnyConductor ) )
{
//If option one text per folio is enable, and the text item of
//current conductor is visible (that mean the conductor have the single displayed text)
//We call adjustTextItemPosition to other conductor at the same potential to keep
//a visible text on this potential.
if ( m_diagram - > defaultConductorProperties . m_one_text_per_folio & & c - > textItem ( ) - > isVisible ( ) )
{
QList < Conductor * > conductor_list ;
2020-05-27 23:01:39 +02:00
conductor_list < < c - > relatedPotentialConductors ( false ) . values ( ) ;
2017-08-03 17:36:08 +00:00
if ( conductor_list . count ( ) )
conductor_list . first ( ) - > calculateTextItemPosition ( ) ;
}
}
for ( Element * e : m_removed_contents . m_elements )
{
//Get linked element, for relink it at undo
if ( ! e - > linkedElements ( ) . isEmpty ( ) )
m_link_hash . insert ( e , e - > linkedElements ( ) ) ;
}
for ( DynamicElementTextItem * deti : m_removed_contents . m_element_texts )
{
2017-11-29 14:49:12 +00:00
if ( deti - > parentGroup ( ) & & deti - > parentGroup ( ) - > parentElement ( ) )
deti - > parentGroup ( ) - > parentElement ( ) - > removeTextFromGroup ( deti , deti - > parentGroup ( ) ) ;
2017-08-22 18:27:23 +00:00
deti - > parentElement ( ) - > removeDynamicTextItem ( deti ) ;
2017-08-03 17:36:08 +00:00
deti - > setParentItem ( nullptr ) ;
}
2020-06-05 20:00:13 +02:00
for ( auto table : m_table_scene_hash . keys ( ) )
2020-05-12 11:17:25 +02:00
{
2020-06-05 20:00:13 +02:00
if ( ! m_table_scene_hash . value ( table ) . isNull ( ) ) {
m_table_scene_hash . value ( table ) - > removeItem ( table ) ;
2020-05-12 11:17:25 +02:00
}
}
2017-08-03 17:36:08 +00:00
for ( QGraphicsItem * item : m_removed_contents . items ( ) )
m_diagram - > removeItem ( item ) ;
2017-12-05 21:41:29 +00:00
QUndoCommand : : redo ( ) ;
2017-08-03 17:36:08 +00:00
}