mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-09-13 20:23:04 +02:00
338 lines
11 KiB
C++
338 lines
11 KiB
C++
/*
|
|
Copyright 2006-2020 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "deleteqgraphicsitemcommand.h"
|
|
|
|
#include "../conductortextitem.h"
|
|
#include "../diagram.h"
|
|
#include "../diagramcommands.h"
|
|
#include "../dynamicelementtextitem.h"
|
|
#include "../elementtextitemgroup.h"
|
|
#include "../qetdiagrameditor.h"
|
|
#include "../qetgraphicsitem/conductor.h"
|
|
#include "../qetgraphicsitem/element.h"
|
|
#include "../qetgraphicsitem/terminal.h"
|
|
#include "../qetgraphicstableitem.h"
|
|
#include "addelementtextcommand.h"
|
|
|
|
/**
|
|
@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)
|
|
{
|
|
if (m_removed_contents.m_elements.contains(deti->parentElement()))
|
|
m_removed_contents.m_element_texts.remove(deti);
|
|
|
|
}
|
|
|
|
//When remove a deti we must to know his parent item, for re-add deti as child of the parent
|
|
//when undo this command
|
|
for(DynamicElementTextItem *deti : m_removed_contents.m_element_texts)
|
|
{
|
|
if(deti->parentGroup())
|
|
m_grp_texts_hash.insert(deti, deti->parentGroup());
|
|
else
|
|
m_elmt_text_hash.insert(deti, deti->parentElement());
|
|
}
|
|
|
|
//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) {
|
|
new RemoveTextsGroupCommand(group->parentElement(), group, this);
|
|
}
|
|
|
|
m_removed_contents.m_texts_groups.clear();
|
|
setPotentialsOfRemovedElements();
|
|
|
|
//Get all linkeds table of removed table.
|
|
for (auto table : m_removed_contents.m_tables)
|
|
{
|
|
//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());
|
|
}
|
|
}
|
|
|
|
setText(QString(QObject::tr(
|
|
"supprimer %1",
|
|
"undo caption - %1 is a sentence listing the removed content"))
|
|
.arg(m_removed_contents.sentence(DiagramContent::All)));
|
|
//Table is now managed by m_table_scene_hash,
|
|
//we clear the tables of m_removed_content
|
|
m_removed_contents.m_tables.clear();
|
|
m_diagram->qgiManager().manage(m_removed_contents.items(DiagramContent::All));
|
|
}
|
|
|
|
DeleteQGraphicsItemCommand::~DeleteQGraphicsItemCommand()
|
|
{
|
|
m_diagram->qgiManager().release(m_removed_contents.items(DiagramContent::All));
|
|
}
|
|
|
|
/**
|
|
@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)
|
|
{
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
|
m_connected_terminals.append(qMakePair<Terminal *, Terminal *>(hub_terminal, t));
|
|
#else
|
|
#if TODO_LIST
|
|
#pragma message("@TODO remove code for QT 6 or later")
|
|
#endif
|
|
qDebug()<<"Help code for QT 6 or later";
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
/**
|
|
@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)
|
|
{
|
|
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));
|
|
}
|
|
}
|
|
|
|
for (auto table : m_table_scene_hash.keys())
|
|
{
|
|
if (!m_table_scene_hash.value(table).isNull()) {
|
|
m_table_scene_hash.value(table)->addItem(table);
|
|
}
|
|
}
|
|
|
|
QUndoCommand::undo();
|
|
}
|
|
|
|
/**
|
|
@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;
|
|
conductor_list << c -> relatedPotentialConductors(false).values();
|
|
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)
|
|
{
|
|
if(deti->parentGroup() && deti->parentGroup()->parentElement())
|
|
deti->parentGroup()->parentElement()->removeTextFromGroup(deti, deti->parentGroup());
|
|
|
|
deti->parentElement()->removeDynamicTextItem(deti);
|
|
deti->setParentItem(nullptr);
|
|
}
|
|
|
|
for (auto table : m_table_scene_hash.keys())
|
|
{
|
|
if (!m_table_scene_hash.value(table).isNull()) {
|
|
m_table_scene_hash.value(table)->removeItem(table);
|
|
}
|
|
}
|
|
|
|
for(QGraphicsItem *item : m_removed_contents.items())
|
|
m_diagram->removeItem(item);
|
|
|
|
QUndoCommand::redo();
|
|
}
|