From 6e81451b46453e11b3c47cac49fb162b0dae4811 Mon Sep 17 00:00:00 2001 From: joshua Date: Sat, 23 Jul 2022 21:54:23 +0200 Subject: [PATCH 1/4] Add import dxf feature Use dxf2elmt to import dxf. See https://github.com/antonioaja/dxf2elmt --- qelectrotech.pro | 6 +- sources/dxf/dxftoelmt.cpp | 102 ++++++++++++++++++ sources/dxf/dxftoelmt.h | 30 ++++++ sources/editor/ui/qetelementeditor.cpp | 29 ++++++ sources/editor/ui/qetelementeditor.h | 1 + sources/editor/ui/qetelementeditor.ui | 10 ++ sources/ui/thirdpartybinaryinstalldialog.cpp | 51 +++++++++ sources/ui/thirdpartybinaryinstalldialog.h | 42 ++++++++ sources/ui/thirdpartybinaryinstalldialog.ui | 104 +++++++++++++++++++ 9 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 sources/dxf/dxftoelmt.cpp create mode 100644 sources/dxf/dxftoelmt.h create mode 100644 sources/ui/thirdpartybinaryinstalldialog.cpp create mode 100644 sources/ui/thirdpartybinaryinstalldialog.h create mode 100644 sources/ui/thirdpartybinaryinstalldialog.ui diff --git a/qelectrotech.pro b/qelectrotech.pro index 7baddbb08..5ae48a6ec 100644 --- a/qelectrotech.pro +++ b/qelectrotech.pro @@ -159,7 +159,8 @@ HEADERS += $$files(sources/*.h) $$files(sources/ui/*.h) \ $$files(sources/print/*.h) \ $$files(sources/TerminalStrip/*.h) \ $$files(sources/TerminalStrip/ui/*.h) \ - $$files(sources/TerminalStrip/UndoCommand/*.h) + $$files(sources/TerminalStrip/UndoCommand/*.h) \ + $$files(sources/dxf/*.h) SOURCES += $$files(sources/*.cpp) \ $$files(sources/editor/*.cpp) \ @@ -195,7 +196,8 @@ SOURCES += $$files(sources/*.cpp) \ $$files(sources/print/*.cpp) \ $$files(sources/TerminalStrip/*.cpp) \ $$files(sources/TerminalStrip/ui/*.cpp) \ - $$files(sources/TerminalStrip/UndoCommand/*.cpp) + $$files(sources/TerminalStrip/UndoCommand/*.cpp) \ + $$files(sources/dxf/*.cpp) # Needed for use promote QTreeWidget in terminalstripeditor.ui INCLUDEPATH += sources/TerminalStrip/ui diff --git a/sources/dxf/dxftoelmt.cpp b/sources/dxf/dxftoelmt.cpp new file mode 100644 index 000000000..5e33b4e9d --- /dev/null +++ b/sources/dxf/dxftoelmt.cpp @@ -0,0 +1,102 @@ +/* + Copyright 2006-2022 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 . +*/ +#include "dxftoelmt.h" +#include "../ui/thirdpartybinaryinstalldialog.h" + +#include +#include +#include +#include + +/** + * @brief dxftoElmt + * Return the dxf at @a file_path converted to elmt. + * The returned value is a QByteArray, instead of a + * QDomDocument or QString, to let user do what they want with that. + * @param file_path + * @return + */ +QByteArray dxfToElmt(const QString &file_path) +{ + if (!dxf2ElmtIsPresent(false)) { + return QByteArray(); + } + + QProcess process_; + const QString program{dxf2ElmtBinaryPath()}; + const QStringList arguments{file_path, QStringLiteral("-v")}; + + process_.start(program, arguments); + process_.waitForFinished(); + + const auto byte_array{process_.readAll()}; + process_.close(); + return byte_array; +} + +QString dxf2ElmtDirPath() +{ +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) + return (QDir::homePath() + QStringLiteral("/Application Data/qet/binary")); +#elif defined(Q_OS_MAC) + return (QDir::homePath() + QStringLiteral("/.qet/binary")); +#else + return (QDir::homePath() + QStringLiteral("/.qet/binary")); +#endif +} + +/** + * @brief dxf2ElmtBinaryPath + * @return the path to the dxf2elmt program + */ +QString dxf2ElmtBinaryPath() +{ +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) + return dxf2ElmtDirPath() + QStringLiteral("/dxf2elmt.exe"); +#elif defined(Q_OS_MAC) + return dxf2ElmtDirPath() + QStringLiteral("/dxf2elmt.app"); +#else + return dxf2ElmtDirPath() + QStringLiteral("/dxf2elmt"); +#endif +} + +/** + * @brief dxf2ElmtIsPresent + * Return true if dxf2elmt is present in the system + * @param install_dialog + * True to display a dialog with the explanations + * of how to install the dxf2elmt program + * if not present in the system. + * @return + */ +bool dxf2ElmtIsPresent(bool install_dialog, QWidget *parent) +{ + const bool exist{QFile::exists(dxf2ElmtBinaryPath())}; + if (!exist && install_dialog) + { + auto string_{QStringLiteral("L'import dxf nécessite le logiciel dxf2elmt. \n" + "Veuillez télécharger celui-ci en suivant le lien ci dessous et le dézipper dans le dossier d'installation")}; + + ThirdPartyBinaryInstallDialog dialog_(string_, + QStringLiteral("https://github.com/antonioaja/dxf2elmt/releases"), + dxf2ElmtDirPath(), + parent); + dialog_.exec(); + } + return exist; +} diff --git a/sources/dxf/dxftoelmt.h b/sources/dxf/dxftoelmt.h new file mode 100644 index 000000000..97f06af19 --- /dev/null +++ b/sources/dxf/dxftoelmt.h @@ -0,0 +1,30 @@ +/* + Copyright 2006-2022 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 . +*/ +#ifndef DXFTOELMT_H +#define DXFTOELMT_H + +#include + +class QWidget; + +QByteArray dxfToElmt(const QString &file_path); +QString dxf2ElmtDirPath(); +QString dxf2ElmtBinaryPath(); +bool dxf2ElmtIsPresent(bool install_dialog = true, QWidget *parent = nullptr); + +#endif // DXFTOELMT_H diff --git a/sources/editor/ui/qetelementeditor.cpp b/sources/editor/ui/qetelementeditor.cpp index 1e06360d2..4fa0e74e1 100644 --- a/sources/editor/ui/qetelementeditor.cpp +++ b/sources/editor/ui/qetelementeditor.cpp @@ -46,6 +46,7 @@ #include "dynamictextfieldeditor.h" #include "../../newelementwizard.h" #include "../editorcommands.h" +#include "../../dxf/dxftoelmt.h" #include #include @@ -1490,3 +1491,31 @@ void QETElementEditor::on_m_donate_action_triggered() { } void QETElementEditor::on_m_about_qt_action_triggered() { qApp->aboutQt(); } + +void QETElementEditor::on_m_import_dxf_triggered() +{ + if (dxf2ElmtIsPresent(true, this)) + { + QString file_path{QFileDialog::getOpenFileName(this, + QObject::tr("Importer un fichier dxf"), + "/home", + "DXF (*.dxf)")}; + if (file_path.isEmpty()) { + return; + } + + QMessageBox::information(this, tr("Avertissement"), tr("L'import d'un dxf volumineux peut prendre du temps \n" + "veuillez patienter durant l'import...")); + + const QByteArray array_{dxfToElmt(file_path)}; + if (array_.isEmpty()) { + return; + } + QDomDocument xml_; + xml_.setContent(array_); + + m_elmt_scene->fromXml(xml_); + fillPartsList(); + } +} + diff --git a/sources/editor/ui/qetelementeditor.h b/sources/editor/ui/qetelementeditor.h index faae89aed..386dc3ee2 100644 --- a/sources/editor/ui/qetelementeditor.h +++ b/sources/editor/ui/qetelementeditor.h @@ -110,6 +110,7 @@ class QETElementEditor : public QMainWindow void on_m_youtube_action_triggered(); void on_m_donate_action_triggered(); void on_m_about_qt_action_triggered(); + void on_m_import_dxf_triggered(); private: bool canClose(); diff --git a/sources/editor/ui/qetelementeditor.ui b/sources/editor/ui/qetelementeditor.ui index 07452bbb8..2c650052d 100644 --- a/sources/editor/ui/qetelementeditor.ui +++ b/sources/editor/ui/qetelementeditor.ui @@ -35,6 +35,7 @@ + @@ -501,6 +502,15 @@ Space + + + + :/ico/16x16/run-dxf.png:/ico/16x16/run-dxf.png + + + Importer un dxf + + diff --git a/sources/ui/thirdpartybinaryinstalldialog.cpp b/sources/ui/thirdpartybinaryinstalldialog.cpp new file mode 100644 index 000000000..07522803f --- /dev/null +++ b/sources/ui/thirdpartybinaryinstalldialog.cpp @@ -0,0 +1,51 @@ +/* + Copyright 2006-2022 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 . +*/ +#include "thirdpartybinaryinstalldialog.h" +#include "ui_thirdpartybinaryinstalldialog.h" + +#include +#include +#include +#include +#include + +ThirdPartyBinaryInstallDialog::ThirdPartyBinaryInstallDialog(const QString &text, + const QString &downloadLink, + const QString &binaryFolderPath, + QWidget *parent) : + QDialog{parent}, + ui{new Ui::ThirdPartyBinaryInstallDialog} +{ + ui->setupUi(this); + ui->m_label->setText(text); + + connect(ui->m_download_pb, &QPushButton::clicked, [downloadLink](){ + QDesktopServices::openUrl(QUrl(downloadLink)); + }); + connect(ui->m_install_dir_pb, &QPushButton::clicked, [binaryFolderPath]() { + //Make sure the path exist + QDir dir_; + dir_.mkpath(binaryFolderPath); + QDesktopServices::openUrl(QUrl("file:///" + binaryFolderPath)); + }); +} + +ThirdPartyBinaryInstallDialog::~ThirdPartyBinaryInstallDialog() +{ + delete ui; +} diff --git a/sources/ui/thirdpartybinaryinstalldialog.h b/sources/ui/thirdpartybinaryinstalldialog.h new file mode 100644 index 000000000..6bbb93b18 --- /dev/null +++ b/sources/ui/thirdpartybinaryinstalldialog.h @@ -0,0 +1,42 @@ +/* + Copyright 2006-2022 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 . +*/ +#ifndef THIRDPARTYBINARYINSTALLDIALOG_H +#define THIRDPARTYBINARYINSTALLDIALOG_H + +#include + +namespace Ui { + class ThirdPartyBinaryInstallDialog; +} + +class ThirdPartyBinaryInstallDialog : public QDialog +{ + Q_OBJECT + + public: + explicit ThirdPartyBinaryInstallDialog(const QString &text, + const QString &downloadLink, + const QString &binaryFolderPath, + QWidget *parent = nullptr); + ~ThirdPartyBinaryInstallDialog(); + + private: + Ui::ThirdPartyBinaryInstallDialog *ui; +}; + +#endif // THIRDPARTYBINARYINSTALLDIALOG_H diff --git a/sources/ui/thirdpartybinaryinstalldialog.ui b/sources/ui/thirdpartybinaryinstalldialog.ui new file mode 100644 index 000000000..899666d2c --- /dev/null +++ b/sources/ui/thirdpartybinaryinstalldialog.ui @@ -0,0 +1,104 @@ + + + ThirdPartyBinaryInstallDialog + + + + 0 + 0 + 373 + 64 + + + + Logiciel tiers requis + + + true + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + Télechargement + + + + :/ico/16x16/edit-download.png:/ico/16x16/edit-download.png + + + + + + + Dossier installation + + + + :/ico/16x16/folder-open.png:/ico/16x16/folder-open.png + + + + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + 5 + + + + + + + + + + + m_button_box + accepted() + ThirdPartyBinaryInstallDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + m_button_box + rejected() + ThirdPartyBinaryInstallDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From cae7cbdbd8ebdd51446fd4733878a5cc093b1d6d Mon Sep 17 00:00:00 2001 From: joshua Date: Sun, 24 Jul 2022 20:58:00 +0200 Subject: [PATCH 2/4] Import dxf is managed by undo command --- .../editor/UndoCommand/openelmtcommand.cpp | 62 +++++++++++++++++++ sources/editor/UndoCommand/openelmtcommand.h | 43 +++++++++++++ sources/editor/ui/qetelementeditor.cpp | 4 +- 3 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 sources/editor/UndoCommand/openelmtcommand.cpp create mode 100644 sources/editor/UndoCommand/openelmtcommand.h diff --git a/sources/editor/UndoCommand/openelmtcommand.cpp b/sources/editor/UndoCommand/openelmtcommand.cpp new file mode 100644 index 000000000..8fa9f9898 --- /dev/null +++ b/sources/editor/UndoCommand/openelmtcommand.cpp @@ -0,0 +1,62 @@ +/* + Copyright 2006-2022 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 . +*/ +#include "openelmtcommand.h" +#include "../elementscene.h" + +#include +#include + +OpenElmtCommand::OpenElmtCommand(const QDomDocument &document, + QPointer scene, + QUndoCommand *parent) : + QUndoCommand{parent}, + m_document{document.cloneNode().toDocument()}, + m_scene{scene} +{ + setText(QObject::tr("Ouvrir un element")); +} + +void OpenElmtCommand::undo() +{ + for (const auto &item : qAsConst(m_graphics_item)) { + m_scene->removeItem(item); + } +} + +void OpenElmtCommand::redo() +{ + if (!m_scene) { + return; + } + + if (m_first_redo) + { + m_scene->fromXml(m_document, QPointF(), true, &m_graphics_item); + m_first_redo = false; + + //m_document is now useless, + //we clear it to use less memory + m_document.clear(); + } + else { + for (const auto &item : qAsConst(m_graphics_item)) { + m_scene->addItem(item); + } + } + m_scene->slot_select(m_graphics_item); +} diff --git a/sources/editor/UndoCommand/openelmtcommand.h b/sources/editor/UndoCommand/openelmtcommand.h new file mode 100644 index 000000000..e318b4ee3 --- /dev/null +++ b/sources/editor/UndoCommand/openelmtcommand.h @@ -0,0 +1,43 @@ +/* + Copyright 2006-2022 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 . +*/ +#ifndef OPENELMTCOMMAND_H +#define OPENELMTCOMMAND_H + +#include +#include +#include + +class ElementScene; +class QGraphicsItem; + +class OpenElmtCommand : public QUndoCommand +{ + public: + OpenElmtCommand(const QDomDocument &document, QPointer scene, QUndoCommand *parent = nullptr); + + virtual void undo() override; + virtual void redo() override; + + private: + QDomDocument m_document; + bool m_first_redo{true}; + QPointer m_scene; + QList m_graphics_item; +}; + +#endif // OPENELMTCOMMAND_H diff --git a/sources/editor/ui/qetelementeditor.cpp b/sources/editor/ui/qetelementeditor.cpp index 4fa0e74e1..09dcb03de 100644 --- a/sources/editor/ui/qetelementeditor.cpp +++ b/sources/editor/ui/qetelementeditor.cpp @@ -47,6 +47,7 @@ #include "../../newelementwizard.h" #include "../editorcommands.h" #include "../../dxf/dxftoelmt.h" +#include "../UndoCommand/openelmtcommand.h" #include #include @@ -1514,8 +1515,7 @@ void QETElementEditor::on_m_import_dxf_triggered() QDomDocument xml_; xml_.setContent(array_); - m_elmt_scene->fromXml(xml_); - fillPartsList(); + m_elmt_scene->undoStack().push(new OpenElmtCommand(xml_, m_elmt_scene)); } } From 5a497cd6b53f49d0527716b37bb0cdb3cebbdfe6 Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 26 Jul 2022 16:17:47 +0200 Subject: [PATCH 3/4] Element editor : improve code Better use of signal partsAdded and partsRemoved --- sources/editor/UndoCommand/addpartcommand.cpp | 84 +++++++++++++++++++ sources/editor/UndoCommand/addpartcommand.h | 50 +++++++++++ .../editor/UndoCommand/openelmtcommand.cpp | 17 ++-- sources/editor/UndoCommand/openelmtcommand.h | 1 + sources/editor/editorcommands.cpp | 52 ------------ sources/editor/editorcommands.h | 25 ------ sources/editor/elementscene.cpp | 40 +++++++-- sources/editor/elementscene.h | 5 ++ sources/editor/esevent/eseventaddarc.cpp | 2 +- .../esevent/eseventadddynamictextfield.cpp | 2 +- sources/editor/esevent/eseventaddellipse.cpp | 2 +- sources/editor/esevent/eseventaddline.cpp | 2 +- sources/editor/esevent/eseventaddpolygon.cpp | 2 +- sources/editor/esevent/eseventaddrect.cpp | 2 +- sources/editor/esevent/eseventaddterminal.cpp | 2 +- sources/editor/esevent/eseventaddtext.cpp | 2 +- sources/editor/ui/qetelementeditor.cpp | 1 - 17 files changed, 192 insertions(+), 99 deletions(-) create mode 100644 sources/editor/UndoCommand/addpartcommand.cpp create mode 100644 sources/editor/UndoCommand/addpartcommand.h diff --git a/sources/editor/UndoCommand/addpartcommand.cpp b/sources/editor/UndoCommand/addpartcommand.cpp new file mode 100644 index 000000000..c5944ab0b --- /dev/null +++ b/sources/editor/UndoCommand/addpartcommand.cpp @@ -0,0 +1,84 @@ +/* + Copyright 2006-2022 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 . +*/ +#include "addpartcommand.h" +#include "../elementscene.h" + +/** + * @brief AddPartCommand::AddPartCommand + * @param text : text of the undo command + * @param scene : scene where @a part must be added + * @param part : part to add + * @param parent : parent undo command + */ +AddPartCommand::AddPartCommand(const QString &text, + QPointer scene, + QGraphicsItem *part, + QUndoCommand *parent) : + QUndoCommand{parent}, + m_scene{scene}, + m_part{part} +{ + setText(text); + m_scene->qgiManager().manage(part); +} + +/** + * @brief AddPartCommand::~AddPartCommand + */ +AddPartCommand::~AddPartCommand() +{ + if (m_scene) { + m_scene->qgiManager().release(m_part.first()); + } +} + +/** + * @brief AddPartCommand::undo + */ +void AddPartCommand::undo() +{ + if (m_scene) { + m_scene->removeItems(m_part); + } +} + +/** + * @brief AddPartCommand::redo + */ +void AddPartCommand::redo() +{ + if (!m_scene) { + return; + } + + if (m_first_redo) + { + auto part_{m_part.first()}; + if (!part_->zValue()) + { + // the added part has no specific zValue already defined, we put it + // above existing items (but still under terminals) + const auto existing_items = m_scene->zItems(ElementScene::SortByZValue | ElementScene::SelectedOrNot); + const auto z_{existing_items.count() ? existing_items.last()->zValue() + 1 : 1}; + part_->setZValue(z_); + } + m_scene->clearSelection(); + m_first_redo = false; + } + m_scene->addItems(m_part); +} diff --git a/sources/editor/UndoCommand/addpartcommand.h b/sources/editor/UndoCommand/addpartcommand.h new file mode 100644 index 000000000..11914c365 --- /dev/null +++ b/sources/editor/UndoCommand/addpartcommand.h @@ -0,0 +1,50 @@ +/* + Copyright 2006-2022 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 . +*/ +#ifndef ADDPARTCOMMAND_H +#define ADDPARTCOMMAND_H + +#include +#include + +class ElementScene; +class QGraphicsItem; + +/** + * @brief The AddPartCommand class + * Undo command use to add a graphics part into an element scene. + */ +class AddPartCommand : public QUndoCommand +{ + public: + AddPartCommand(const QString &text, QPointer scene, QGraphicsItem *part, QUndoCommand *parent = nullptr); + ~AddPartCommand() override; + + private: + AddPartCommand(const AddPartCommand &); + + public: + void undo() override; + void redo() override; + + private: + QPointer m_scene; + QVector m_part; + bool m_first_redo{true}; +}; + +#endif // ADDPARTCOMMAND_H diff --git a/sources/editor/UndoCommand/openelmtcommand.cpp b/sources/editor/UndoCommand/openelmtcommand.cpp index 8fa9f9898..79786dfc6 100644 --- a/sources/editor/UndoCommand/openelmtcommand.cpp +++ b/sources/editor/UndoCommand/openelmtcommand.cpp @@ -31,11 +31,16 @@ OpenElmtCommand::OpenElmtCommand(const QDomDocument &document, setText(QObject::tr("Ouvrir un element")); } +OpenElmtCommand::~OpenElmtCommand() +{ + if (m_scene) { + m_scene->qgiManager().release(m_graphics_item); + } +} + void OpenElmtCommand::undo() { - for (const auto &item : qAsConst(m_graphics_item)) { - m_scene->removeItem(item); - } + m_scene->removeItems(m_graphics_item.toVector()); } void OpenElmtCommand::redo() @@ -47,6 +52,7 @@ void OpenElmtCommand::redo() if (m_first_redo) { m_scene->fromXml(m_document, QPointF(), true, &m_graphics_item); + m_scene->qgiManager().manage(m_graphics_item); m_first_redo = false; //m_document is now useless, @@ -54,9 +60,8 @@ void OpenElmtCommand::redo() m_document.clear(); } else { - for (const auto &item : qAsConst(m_graphics_item)) { - m_scene->addItem(item); - } + m_scene->addItems(m_graphics_item.toVector()); } + m_scene->slot_select(m_graphics_item); } diff --git a/sources/editor/UndoCommand/openelmtcommand.h b/sources/editor/UndoCommand/openelmtcommand.h index e318b4ee3..be85bc744 100644 --- a/sources/editor/UndoCommand/openelmtcommand.h +++ b/sources/editor/UndoCommand/openelmtcommand.h @@ -29,6 +29,7 @@ class OpenElmtCommand : public QUndoCommand { public: OpenElmtCommand(const QDomDocument &document, QPointer scene, QUndoCommand *parent = nullptr); + ~OpenElmtCommand() override; virtual void undo() override; virtual void redo() override; diff --git a/sources/editor/editorcommands.cpp b/sources/editor/editorcommands.cpp index 9be73c34a..ba7ec27c5 100644 --- a/sources/editor/editorcommands.cpp +++ b/sources/editor/editorcommands.cpp @@ -203,58 +203,6 @@ void MovePartsCommand::redo() foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(movement.x(), movement.y()); } -/*** AddPartCommand ***/ -/** - Constructeur - @param name Nom de la partie ajoutee - @param scene ElementScene concernee - @param p partie ajoutee - @param parent QUndoCommand parent -*/ -AddPartCommand::AddPartCommand( - const QString &name, - ElementScene *scene, - QGraphicsItem *p, - QUndoCommand *parent -) : - ElementEditionCommand(QString(QObject::tr("ajout %1", "undo caption")).arg(name), scene, nullptr, parent), - part(p), - first_redo(true) -{ - m_scene -> qgiManager().manage(part); -} - -/// Destructeur -AddPartCommand::~AddPartCommand() -{ - m_scene -> qgiManager().release(part); -} - -/// Annule l'ajout -void AddPartCommand::undo() -{ - m_scene -> removeItem(part); -} - -/// Refait l'ajout -void AddPartCommand::redo() -{ - // le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire - if (first_redo) { - if (!part -> zValue()) { - // the added part has no specific zValue already defined, we put it - // above existing items (but still under terminals) - QList existing_items = m_scene -> zItems(ElementScene::SortByZValue | ElementScene::SelectedOrNot); - qreal z = existing_items.count() ? existing_items.last() -> zValue() + 1 : 1; - part -> setZValue(z); - } - m_scene -> clearSelection(); - first_redo = false; - return; - } - m_scene -> addItem(part); -} - /** Constructeur @param element_scene Element edite diff --git a/sources/editor/editorcommands.h b/sources/editor/editorcommands.h index 6e803b3c9..cad08767c 100644 --- a/sources/editor/editorcommands.h +++ b/sources/editor/editorcommands.h @@ -132,30 +132,6 @@ class MovePartsCommand : public ElementEditionCommand { bool first_redo; }; -/** - This command adds a primitive when editing an electrical element. -*/ -class AddPartCommand : public ElementEditionCommand { - // constructors, destructor - public: - AddPartCommand(const QString &, ElementScene *, QGraphicsItem *, QUndoCommand * = nullptr); - ~AddPartCommand() override; - private: - AddPartCommand(const AddPartCommand &); - - // methods - public: - void undo() override; - void redo() override; - - // attributes - private: - /// Added primitive - QGraphicsItem *part; - /// Prevent the first call to redo() - bool first_redo; -}; - /** This command changes the translated names of an electrical element. */ @@ -311,5 +287,4 @@ private: }; - #endif diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index 2d8d7a302..f04292a9f 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -119,7 +119,6 @@ void ElementScene::mouseMoveEvent(QGraphicsSceneMouseEvent *e) if (m_event_interface->isFinish()) { delete m_event_interface; m_event_interface = nullptr; - emit(partsAdded()); } return; } @@ -151,7 +150,6 @@ void ElementScene::mousePressEvent(QGraphicsSceneMouseEvent *e) if (m_event_interface->isFinish()) { delete m_event_interface; m_event_interface = nullptr; - emit(partsAdded()); } return; } @@ -171,7 +169,6 @@ void ElementScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) if (m_event_interface->isFinish()) { delete m_event_interface; m_event_interface = nullptr; - emit(partsAdded()); } return; } @@ -199,7 +196,6 @@ void ElementScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) if (m_event_interface->isFinish()) { delete m_event_interface; m_event_interface = nullptr; - emit(partsAdded()); } return; } @@ -223,7 +219,6 @@ void ElementScene::keyPressEvent(QKeyEvent *event) { delete m_event_interface; m_event_interface = nullptr; - emit(partsAdded()); } return; } @@ -725,6 +720,38 @@ QETElementEditor* ElementScene::editor() const return m_element_editor; } +/** + * @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 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 items) +{ + for (const auto &item : items) { + removeItem(item); + } + + emit partsRemoved(); +} + /** @brief ElementScene::slot_select Select the item in content, @@ -806,8 +833,7 @@ void ElementScene::slot_delete() m_undo_stack.push(new DeletePartsCommand(this, selected_items)); // removing items does not trigger QGraphicsScene::selectionChanged() - emit(partsRemoved()); - emit(selectionChanged()); + emit selectionChanged(); } /** diff --git a/sources/editor/elementscene.h b/sources/editor/elementscene.h index 3df7819f9..5f275c344 100644 --- a/sources/editor/elementscene.h +++ b/sources/editor/elementscene.h @@ -37,6 +37,9 @@ class QKeyEvent; This class is the canvas allowing the visual edition of an electrial element. It displays the various primitives composing the drawing of the element, the border due to its fixed size and its hotspot. + + For add and remove item prefer use custom method addItems and removeItems instead of + addItem and removeItem, because these methods emit signal partAdded and partRemoved. */ class ElementScene : public QGraphicsScene { @@ -124,6 +127,8 @@ class ElementScene : public QGraphicsScene void cut(); void copy(); QETElementEditor* editor() const; + void addItems(QVector items); + void removeItems(QVector items); protected: void mouseMoveEvent (QGraphicsSceneMouseEvent *) override; diff --git a/sources/editor/esevent/eseventaddarc.cpp b/sources/editor/esevent/eseventaddarc.cpp index 7ba700b08..6fb7dadaa 100644 --- a/sources/editor/esevent/eseventaddarc.cpp +++ b/sources/editor/esevent/eseventaddarc.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddarc.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partarc.h" diff --git a/sources/editor/esevent/eseventadddynamictextfield.cpp b/sources/editor/esevent/eseventadddynamictextfield.cpp index defa52544..71b06d077 100644 --- a/sources/editor/esevent/eseventadddynamictextfield.cpp +++ b/sources/editor/esevent/eseventadddynamictextfield.cpp @@ -17,7 +17,7 @@ */ #include "eseventadddynamictextfield.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partdynamictextfield.h" diff --git a/sources/editor/esevent/eseventaddellipse.cpp b/sources/editor/esevent/eseventaddellipse.cpp index c7dba6b7f..d704f47cb 100644 --- a/sources/editor/esevent/eseventaddellipse.cpp +++ b/sources/editor/esevent/eseventaddellipse.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddellipse.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partellipse.h" diff --git a/sources/editor/esevent/eseventaddline.cpp b/sources/editor/esevent/eseventaddline.cpp index 93f83a320..41fb137d0 100644 --- a/sources/editor/esevent/eseventaddline.cpp +++ b/sources/editor/esevent/eseventaddline.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddline.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partline.h" #include "../ui/qetelementeditor.h" diff --git a/sources/editor/esevent/eseventaddpolygon.cpp b/sources/editor/esevent/eseventaddpolygon.cpp index 357c5c849..1c7e4af04 100644 --- a/sources/editor/esevent/eseventaddpolygon.cpp +++ b/sources/editor/esevent/eseventaddpolygon.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddpolygon.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partpolygon.h" diff --git a/sources/editor/esevent/eseventaddrect.cpp b/sources/editor/esevent/eseventaddrect.cpp index 108b99c65..ed3b038a3 100644 --- a/sources/editor/esevent/eseventaddrect.cpp +++ b/sources/editor/esevent/eseventaddrect.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddrect.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partrectangle.h" diff --git a/sources/editor/esevent/eseventaddterminal.cpp b/sources/editor/esevent/eseventaddterminal.cpp index a48516e99..827136cbb 100644 --- a/sources/editor/esevent/eseventaddterminal.cpp +++ b/sources/editor/esevent/eseventaddterminal.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddterminal.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/partterminal.h" diff --git a/sources/editor/esevent/eseventaddtext.cpp b/sources/editor/esevent/eseventaddtext.cpp index 8f1521f82..816faf23d 100644 --- a/sources/editor/esevent/eseventaddtext.cpp +++ b/sources/editor/esevent/eseventaddtext.cpp @@ -17,7 +17,7 @@ */ #include "eseventaddtext.h" -#include "../editorcommands.h" +#include "../UndoCommand/addpartcommand.h" #include "../elementscene.h" #include "../graphicspart/parttext.h" diff --git a/sources/editor/ui/qetelementeditor.cpp b/sources/editor/ui/qetelementeditor.cpp index 09dcb03de..f5c4f02be 100644 --- a/sources/editor/ui/qetelementeditor.cpp +++ b/sources/editor/ui/qetelementeditor.cpp @@ -1130,7 +1130,6 @@ void QETElementEditor::setupConnection() }); connect(&(m_elmt_scene -> undoStack()), &QUndoStack::indexChanged, [this]() { - this->updatePartsList(); this->updateInformations(); }); } From 57695bbbea3724681c95d98e42794255ee395520 Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 26 Jul 2022 17:03:18 +0200 Subject: [PATCH 4/4] Element editor : improve code Better use of signal partsAdded and partsRemoved --- .../editor/UndoCommand/deletepartscommand.cpp | 66 +++++++++++++++++++ .../editor/UndoCommand/deletepartscommand.h | 48 ++++++++++++++ sources/editor/editorcommands.cpp | 50 +------------- sources/editor/editorcommands.h | 24 +------ sources/editor/elementscene.cpp | 12 ++-- sources/qgimanager.cpp | 12 ++++ sources/qgimanager.h | 8 ++- 7 files changed, 139 insertions(+), 81 deletions(-) create mode 100644 sources/editor/UndoCommand/deletepartscommand.cpp create mode 100644 sources/editor/UndoCommand/deletepartscommand.h diff --git a/sources/editor/UndoCommand/deletepartscommand.cpp b/sources/editor/UndoCommand/deletepartscommand.cpp new file mode 100644 index 000000000..53f768956 --- /dev/null +++ b/sources/editor/UndoCommand/deletepartscommand.cpp @@ -0,0 +1,66 @@ +/* + Copyright 2006-2022 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 . +*/ +#include "deletepartscommand.h" +#include "../elementscene.h" + +/** + * @brief DeletePartsCommand::DeletePartsCommand + * @param scene + * @param parts + * @param parent + */ +DeletePartsCommand::DeletePartsCommand(QPointer scene, + const QVector &parts, + QUndoCommand *parent) : + QUndoCommand{parent}, + m_scene{scene}, + m_parts{parts} +{ + setText(QObject::tr("suppression", "undo caption")); + m_scene->qgiManager().manage(parts); +} + +/** + * @brief DeletePartsCommand::~DeletePartsCommand + */ +DeletePartsCommand::~DeletePartsCommand() +{ + if (m_scene) { + m_scene->qgiManager().release(m_parts); + } +} + +/** + * @brief DeletePartsCommand::undo + */ +void DeletePartsCommand::undo() +{ + if (m_scene) { + m_scene->addItems(m_parts); + } +} + +/** + * @brief DeletePartsCommand::redo + */ +void DeletePartsCommand::redo() +{ + if (m_scene) { + m_scene->removeItems(m_parts); + } +} diff --git a/sources/editor/UndoCommand/deletepartscommand.h b/sources/editor/UndoCommand/deletepartscommand.h new file mode 100644 index 000000000..dde5c45c5 --- /dev/null +++ b/sources/editor/UndoCommand/deletepartscommand.h @@ -0,0 +1,48 @@ +/* + Copyright 2006-2022 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 . +*/ +#ifndef DELETEPARTSCOMMAND_H +#define DELETEPARTSCOMMAND_H + +#include +#include + +class ElementScene; +class QGraphicsItem; + +/** + * @brief The DeletePartsCommand class + * Class used to remove part from an element scene. + */ +class DeletePartsCommand : public QUndoCommand +{ + public: + DeletePartsCommand(QPointer scene, const QVector &parts, QUndoCommand *parent = nullptr); + ~DeletePartsCommand() override; + private: + DeletePartsCommand(const DeletePartsCommand &); + + public: + void undo() override; + void redo() override; + + private: + QPointer m_scene; + QVector m_parts; +}; + +#endif // DELETEPARTSCOMMAND_H diff --git a/sources/editor/editorcommands.cpp b/sources/editor/editorcommands.cpp index ba7ec27c5..02f57795e 100644 --- a/sources/editor/editorcommands.cpp +++ b/sources/editor/editorcommands.cpp @@ -90,54 +90,6 @@ void ElementEditionCommand::setElementView(ElementView *view) { m_view = view; } -/*** DeletePartsCommand ***/ -/** - Constructeur - @param scene ElementScene concernee - @param parts Liste des parties supprimees - @param parent QUndoCommand parent -*/ -DeletePartsCommand::DeletePartsCommand( - ElementScene *scene, - const QList& parts, - QUndoCommand *parent -) : - ElementEditionCommand(QObject::tr("suppression", "undo caption"), scene, nullptr, parent), - deleted_parts(parts) -{ - foreach(QGraphicsItem *qgi, deleted_parts) { - m_scene -> qgiManager().manage(qgi); - } -} - -/// Destructeur : detruit egalement les parties supprimees -DeletePartsCommand::~DeletePartsCommand() -{ - foreach(QGraphicsItem *qgi, deleted_parts) { - m_scene -> qgiManager().release(qgi); - } -} - -/// Restaure les parties supprimees -void DeletePartsCommand::undo() -{ - m_scene -> blockSignals(true); - foreach(QGraphicsItem *qgi, deleted_parts) { - m_scene -> addItem(qgi); - } - m_scene -> blockSignals(false); -} - -/// Supprime les parties -void DeletePartsCommand::redo() -{ - m_scene -> blockSignals(true); - foreach(QGraphicsItem *qgi, deleted_parts) { - m_scene -> removeItem(qgi); - } - m_scene -> blockSignals(false); -} - /*** CutPartsCommand ***/ /** Constructeur @@ -150,7 +102,7 @@ CutPartsCommand::CutPartsCommand( const QList& parts, QUndoCommand *parent ) : - DeletePartsCommand(scene, parts, parent) + DeletePartsCommand(scene, parts.toVector(), parent) { setText(QString(QObject::tr("couper des parties", "undo caption"))); } diff --git a/sources/editor/editorcommands.h b/sources/editor/editorcommands.h index cad08767c..202e4150b 100644 --- a/sources/editor/editorcommands.h +++ b/sources/editor/editorcommands.h @@ -34,6 +34,7 @@ #include "graphicspart/partterminal.h" #include "graphicspart/parttext.h" #include "../QPropertyUndoCommand/qpropertyundocommand.h" +#include "UndoCommand/deletepartscommand.h" /** @@ -71,29 +72,6 @@ class ElementEditionCommand : public QUndoCommand ElementView *m_view; }; -/** - This command deletes one or several primitives/parts when editing an - electrical element. -*/ -class DeletePartsCommand : public ElementEditionCommand { - // constructors, destructor - public: - DeletePartsCommand(ElementScene *, const QList&, QUndoCommand * = nullptr); - ~DeletePartsCommand() override; - private: - DeletePartsCommand(const DeletePartsCommand &); - - // methods - public: - void undo() override; - void redo() override; - - // attributes - private: - /// Deleted primitives - QList deleted_parts; -}; - /** This command cut primitives when editing an electrical element. */ diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index f04292a9f..7bfcc258e 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -823,16 +823,14 @@ void ElementScene::slot_invertSelection() */ void ElementScene::slot_delete() { - // check that there is something selected - // verifie qu'il y a qqc de selectionne - QList selected_items = selectedItems(); - if (selected_items.isEmpty()) return; + const auto selected_items{selectedItems().toVector()}; + if (selected_items.isEmpty()) { + return; + } - // erase everything that is selected - // efface tout ce qui est selectionne m_undo_stack.push(new DeletePartsCommand(this, selected_items)); - // removing items does not trigger QGraphicsScene::selectionChanged() + // removing items does not trigger QGraphicsScene::selectionChanged() emit selectionChanged(); } diff --git a/sources/qgimanager.cpp b/sources/qgimanager.cpp index b72d2eb98..34c7ddecc 100644 --- a/sources/qgimanager.cpp +++ b/sources/qgimanager.cpp @@ -86,6 +86,18 @@ void QGIManager::release(const QList &qgis) { foreach(QGraphicsItem *qgi, qgis) release(qgi); } +void QGIManager::manage(const QVector &items) { + for (const auto &qgi : items) { + manage(qgi); + } +} + +void QGIManager::release(const QVector &items) { + for (const auto &qgi : items) { + release(qgi); + } +} + /** Indique au QGIManager de detruire les QGraphicsItem restants lors de sa destruction si ceux-ci n'appartiennent pas a la scene diff --git a/sources/qgimanager.h b/sources/qgimanager.h index 40c786093..15f24d362 100644 --- a/sources/qgimanager.h +++ b/sources/qgimanager.h @@ -42,8 +42,12 @@ class QGIManager { public: void manage(QGraphicsItem *); void release(QGraphicsItem *); - void manage(const QList &); - void release(const QList &); + QT_DEPRECATED_X("Use QGIManager::manage(const QVector &) instead") + void manage(const QList &); + QT_DEPRECATED_X("Use QGIManager::release(const QVector &) instead") + void release(const QList &); + void manage(const QVector &items); + void release(const QVector &items); void setDestroyQGIOnDelete(bool); bool manages(QGraphicsItem *) const; };